给定一个数组和整数k,在大小为k的每个子数组中找到最大值
Given an array and integer k find maximum value in each subarray of size k
我正在努力解决一个关于hackerbank deque stl的问题。我已经实现了一种算法,该算法在窗口中找到最大元素并存储其索引,然后只有当最大元素的索引位于下一个窗口的索引之间时,才使用上一个窗口中最大元素的这个索引来在下一个窗口中查找最大元素。使用这个算法和评论中提到的建议,我已经实现了这个更新的算法,但我仍然得到了错误答案。
#include <iostream>
#include <algorithm>
#include <bits/stdc++.h>
using namespace std;
int m,idx;
void maxinwindow(int arr[], int start, int end)
{
/*If the index of the maximum element in the previous window
is between the indexes of next windows then no need to compare
elements that were in previous window */
if(idx>=start)
{
if(arr[idx]>=arr[end])
{
m=arr[idx];
}
else
{
m=arr[end];
idx=end;
}
}
else
{
if(arr[start]>=arr[start+1])
m=arr[start];
else
m=arr[start+1];
for(int k=start+2;k<=end;k++)
{
if(arr[k]>=m)
{
m=arr[k];
idx=k;
}
}
}
}
int main()
{
int arr[100000];
int q;
cin>>q;
for(int i=1,size,ws;i<=q;i++)
{
m=0;
cin>>size; //Array size
cin>>ws; //Window Size
//Entering The Elements In The Array
for(int j=1;j<=size;j++)
{
cin>>arr[j];
}
//Boundary Condition i.e. Windows size is equal to 1
if(ws==1)
{
for(int j=1;j<=size;j++)
{
cout<<arr[j]<<" ";
}
}
else
{
for(int k=1;k<=ws;k++)
{
if(arr[k]>=m)
{
m=arr[k];
idx=k;
}
}
cout<<m<<" ";
for(int k=2,j;k<=(size-(ws-1));k++)
{
j=(k+(ws-1));
maxinwindow(arr,k,j);
cout<<m<<" ";
}
cout<<endl;
}
}
}
简介
为了有效地解决这个问题,请跟踪当前或后续滑动窗口中可能是最大值的元素。
算法
在Hackerrank练习中,您应该使用std::deque
来有效地解决问题。因此,我建议不要偏离这一点,使用std::deque
来解决它。
让我们考虑一个例子。给定一个数组arr = [4, 3, 4, 2, 5]
和窗口k = 3
,如何在每个长度为3
的子数组中找到最大值?
-
遍历第一个
3
元素,并在队列中保留数组元素的相关索引。Step 1 arr: |4| 3 4 2 5 queue : |0|
添加第一个元素的索引,因为队列为空。
Step 2 arr: |4 3| 4 2 5 queue : |0 1|
添加索引
1
,但将0
保留为arr[0] > arr[1]
。但为什么要保留1
呢?即使CCD_ 11在这个滑动窗口中较小,它也可以在没有CCD_ 12的另一个滑动窗口中最大。Step 3 arr: |4 3 4| 2 5 queue : | 2 |
在最后一步中,我们在队列中只保留了
2
。为什么?因为arr[2]
不小于arr[0]
或arr[1]
。因此,将这些指数保持在最大值是没有意义的该子阵列中的值将仍然是CCD_ 17。由于第一个滑动窗口已完成,请打印
arr[queue.front()]
。队列的第一个元素对应于子数组中最大元素的索引。 -
一旦处理了第一个
3
元素,在每次迭代中,滑动窗口开始向右移动:arr: 4 |3 4 2| 5 queue : | 2 3 |
打印
arr[2]
作为最大值。同样,队列的第一个元素对应于子数组中最大元素的索引。CCD_ 21被保留在队列中,因为它可能对应于下一个滑动窗口中的最大值的索引。arr: 4 3 |4 2 5| queue : | 4 |
最后,
4
仍然是唯一的元素,因为无论如何都会弹出2
(它不属于当前窗口)和arr[4] >= arr[3]
,所以保留它是没有意义的
总之,以下是算法的步骤:
-
对于数组的第一个
k
元素,将可能的最大子数组元素的索引存储在队列中。在每次i
迭代中,如果映射的值不超过arr[i]
,则继续从队列中弹出元素,然后将arr[i]
推入队列。最后,队列的第一个元素包含一个最大值的索引。
-
对于剩余的数组元素,在每次迭代
i
上,只有当第一个元素front
不再属于当前滑动窗口时,才会弹出它——i - front == k
。然后,像以前一样,弹出映射值不超过arr[i]
的索引,然后将arr[i]
推入队列(同样,在每次迭代结束时,队列包含最大值的索引)。
希望现在已经清楚了如何实现这个想法。解的时间复杂度为O(n)。空间复杂度也是O(n)。
代码
#include <algorithm>
#include <iostream>
#include <deque>
void printKMax(int arr[], int n, int k){
std::deque<int> queue;
for (int i = 0; i < k; i++) {
while (!queue.empty() && arr[queue.back()] <= arr[i]) {
queue.pop_back();
}
queue.push_back(i);
}
for (int i = k; i < n; i++) {
std::cout << arr[queue.front()] << " ";
// an element with index queue.front() no longer belong to ths window
if (i - queue.front() == k) {
queue.pop_front();
}
// pop all elements that don't exceed arr[i] as they're no longer useful
while (!queue.empty() && arr[queue.back()] <= arr[i]) {
queue.pop_back();
}
queue.push_back(i);
}
std::cout << arr[queue.front()] << "n";
}
- 如何在C++中将数组转换为矢量指针
- 将浮动的heightmap数组导出为16位原始值
- 将C++中的数组转换为字符串
- NLOHMANN 的 JSON 库将数组转换为结构向量
- 将 int 数组转换为 std::vector<int*>
- 在nlohmann json中,如何将嵌套对象的数组转换为嵌套结构的向量
- 无法在 Arduino 中uint8_t数组转换为无符号长整型数组
- 将字节数组转换为带有字节序问题的指针
- 使用 stbi_write_png,如何将 0 和 1 的矩形字节数组转换为单色 png 文件?
- 如何在 C++ 中将数组划分为不同的数组
- 将字符数组转换为时间结构
- 将字节数组转换为多维数组
- 可视化 如何在C++中将字符数组转换为 FILE 类型
- 在 C++ 中将整数数组转换为位集表示形式的最佳方法?
- 无法将字符串数组声明为类成员而不是字符 (C++)
- C++如何将字符数组转换为字节向量(向量<byte>)
- 将字符数组转换为结构时出现问题. 结构的字符数组变量溢出
- 我应该如何将较小的std::数组构造为较大数组的切片
- 将一个std::数组拆分为一个较小大小的std::array元组
- 在最小执行时间内找到给定数组中和为零的所有唯一三元组