正常做法应该是双端队列,但是我最开始没想到,属于取巧了。我怎么做的就不多说了,代码会放在文末,具体说说标准做法。
双端队列
因为数据规模大,因此二重循环肯定不行。所以需要在一次遍历的过程中就找到每个窗口中的最大值和最小值。以最小值为例,首先创建双端队列(直接用deque),在遍历的过程中将当前遍历到的数入队,之后只要入队的元素比当前队列中队头的数小,则让队列中所有元素出队,将当前的数放到队头。这样队头元素只有在遇到比他小的数才更新,意味着队头元素永远是窗口中的最小值。
此外,还要注意队列溢出的情况。需要在队列元素个数等于k的时候将队头元素抛出,直到队头元素是当前队列中的最小值。
代码如下:
#include <iostream> #include <deque> using namespace std; int a[100000000]; int b[100000000]; int c[100000000]; int main() { int n, k; cin >> n >> k; for (int i = 0; i < n; i++) { cin >> a[i]; } deque<int> q1, q2; //找最小值 for (int i = 0; i < n; i++) { if (i==0) { q1.push_back(a[i]); continue; } if (q1.front() > a[i]) { while (!q1.empty()) { q1.pop_front(); } } q1.push_back(a[i]); if (i == n - 1 && i >= k - 1) { cout << q1.front() << endl; } else if(i != n - 1 && i >= k - 1) { cout << q1.front() << " "; } if (q1.size() == k) { q1.pop_front(); int nmin = q1.front(); for (int j = i - k + 2;j<=i;j++) { nmin = min(nmin, a[j]); } while (q1.front() !=nmin) { q1.pop_front(); } } } //找最大值 for (int i = 0; i < n; i++) { if (i == 0) { q2.push_back(a[i]); continue; } if (q2.front() < a[i]) { while (!q2.empty()) { q2.pop_front(); } } q2.push_back(a[i]); if (i == n - 1 && i >= k - 1) { cout << q2.front() << endl; } else if (i != n - 1 && i >= k - 1) { cout << q2.front() << " "; } if (q2.size() == k) { q2.pop_front(); int nmax = q2.front(); for (int j = i - k + 2; j <= i; j++) { nmax = max(nmax, a[j]); } while (q2.front() != nmax) { q2.pop_front(); } } } }本人硬想想出来的方法如下:
#include <iostream> #include <string> using namespace std; int a[1000000] = { 0 }; int b[1000000] = { 0 }; int main() { int n, k; cin >> n >> k; int s=0; for (int i = 0; i < n; i++) { cin >> a[i]; } int nmax = a[0]; int nmin = a[0]; for (int i = 0; i < n; i++) { nmax = max(nmax, a[i]); nmin = min(nmin, a[i]); if (i >= k-1) { b[s] = nmax; if (i == n-1) { cout << nmin << endl; } else { cout << nmin << " "; } // if (nmax == a[i-k+1]) { nmax = a[i - k + 2]; for (int j = i - k + 2; j <= i; j++) { nmax = max(nmax, a[j]); } } else if (nmin == a[i - k + 1]) { nmin = a[i - k + 2]; for (int j = i - k + 2; j <= i; j++) { nmin = min(nmin, a[j]); } } s++; } } for (int i = 0; i < n - k+1; i++) { if (i == n - k ) { cout << b[i] << endl; } else { cout << b[i] << " "; } } }