这个函数的时间复杂度是多少?
What is the time complexity of this function?
这是 Java 中 Sliding Window Maximum 问题的示例解决方案。
Given an array nums, there is a sliding window of size k which is
moving from the very left of the array to the very right. You can only
see the k numbers in the window. Each time the sliding window moves
right by one position.
我想获取此函数的时间和 space 复杂度。这是我认为的答案:
时间:O((n-k)(k * logk))
== O(nklogk)
Space(辅助):O(n)
代表 return int[]
和 O(k)
代表 pq
。总计 O(n)
.
这是正确的吗?
private static int[] maxSlidingWindow(int[] a, int k) {
if(a == null || a.length == 0) return new int[] {};
PriorityQueue<Integer> pq = new PriorityQueue<Integer>(k, new Comparator<Integer>() {
// max heap
public int compare(Integer o1, Integer o2) {
return o2 - o1;
}
});
int[] result = new int[a.length - k + 1];
int count = 0;
// time: n - k times
for (int i = 0; i < a.length - k + 1; i++) {
for (int j = i; j < i + k; j++) {
// time k*logk (the part I'm not sure about)
pq.offer(a[j]);
}
// logk
result[count] = pq.poll();
count = count + 1;
pq.clear();
}
return result;
}
除了-
,你大部分都是对的
for (int j = i; j < i + k; j++) {
// time k*logk (the part I'm not sure about)
pq.offer(a[j]);
}
此处总执行次数为log1 + log2 + log3 + log4 + ... + logk
。这个系列的总和-
log1 + log2 + log3 + log4 + ... + logk = log(k!)
第二个想法是,你可以使用双端队列 属性 比你的线性时间解决方案做得更好,这将是 O(n)
。这是我的解决方案 -
public int[] maxSlidingWindow(int[] nums, int k) {
if (nums == null || k <= 0) {
return new int[0];
}
int n = nums.length;
int[] result = new int[n - k + 1];
int indx = 0;
Deque<Integer> q = new ArrayDeque<>();
for (int i = 0; i < n; i++) {
// remove numbers out of range k
while (!q.isEmpty() && q.peek() < i - k + 1) {
q.poll();
}
// remove smaller numbers in k range as they are useless
while (!q.isEmpty() && nums[q.peekLast()] < nums[i]) {
q.pollLast();
}
q.offer(i);
if (i >= k - 1) {
result[indx++] = nums[q.peek()];
}
}
return result;
}
HTH.
这是 Java 中 Sliding Window Maximum 问题的示例解决方案。
Given an array nums, there is a sliding window of size k which is moving from the very left of the array to the very right. You can only see the k numbers in the window. Each time the sliding window moves right by one position.
我想获取此函数的时间和 space 复杂度。这是我认为的答案:
时间:O((n-k)(k * logk))
== O(nklogk)
Space(辅助):O(n)
代表 return int[]
和 O(k)
代表 pq
。总计 O(n)
.
这是正确的吗?
private static int[] maxSlidingWindow(int[] a, int k) {
if(a == null || a.length == 0) return new int[] {};
PriorityQueue<Integer> pq = new PriorityQueue<Integer>(k, new Comparator<Integer>() {
// max heap
public int compare(Integer o1, Integer o2) {
return o2 - o1;
}
});
int[] result = new int[a.length - k + 1];
int count = 0;
// time: n - k times
for (int i = 0; i < a.length - k + 1; i++) {
for (int j = i; j < i + k; j++) {
// time k*logk (the part I'm not sure about)
pq.offer(a[j]);
}
// logk
result[count] = pq.poll();
count = count + 1;
pq.clear();
}
return result;
}
除了-
,你大部分都是对的for (int j = i; j < i + k; j++) {
// time k*logk (the part I'm not sure about)
pq.offer(a[j]);
}
此处总执行次数为log1 + log2 + log3 + log4 + ... + logk
。这个系列的总和-
log1 + log2 + log3 + log4 + ... + logk = log(k!)
第二个想法是,你可以使用双端队列 属性 比你的线性时间解决方案做得更好,这将是 O(n)
。这是我的解决方案 -
public int[] maxSlidingWindow(int[] nums, int k) {
if (nums == null || k <= 0) {
return new int[0];
}
int n = nums.length;
int[] result = new int[n - k + 1];
int indx = 0;
Deque<Integer> q = new ArrayDeque<>();
for (int i = 0; i < n; i++) {
// remove numbers out of range k
while (!q.isEmpty() && q.peek() < i - k + 1) {
q.poll();
}
// remove smaller numbers in k range as they are useless
while (!q.isEmpty() && nums[q.peekLast()] < nums[i]) {
q.pollLast();
}
q.offer(i);
if (i >= k - 1) {
result[indx++] = nums[q.peek()];
}
}
return result;
}
HTH.