結論:
求最大值時使用雙端對維護遞減資料,即佇列中資料依次遞減,佇列頭部資料始終為最大值,每次將遍歷到的資料與佇列尾部的資料進行比較
如果不違反佇列的遞減規律(遍歷到的資料元素小於佇列尾部資料)就直接插入佇列尾部
如果違反了佇列的遞減規律就依次從佇列尾部彈出資料,直到找到能夠保持佇列遞減規律的位置。
求最小值時使用雙端對維護遞增資料,即佇列中資料依次遞增,佇列頭部資料始終為最小值,每次將遍歷到的資料與佇列尾部的資料進行比較
如果不違反佇列的遞減少規律(遍歷到的資料元素小於佇列尾部資料)就直接插入佇列尾部
如果違反了佇列的遞增規律,就依次從佇列尾部彈出資料,直到找到能夠保持佇列遞增規律的位置。
求最大值時,滑動視窗新進來的資料arr[i] ,視窗內的資料最大值一定是 ≥ arr[i] ,所以要彈出佇列內小於 arr[i] 的資料,且視窗在包含的 arr[i] 區域內移動時,最大值也一定 ≥ arr[i],同理求最小值。
求最大值時,如果 arr[i] 比 佇列尾部資料要小,直接加入到佇列尾部,因為陣列 arr[i] 之後如果一直在減少,arr[i] 就有可能會成為最大值,所以要將 arr[i] 加入到佇列尾部。
時間複雜度為o(n)
題目:有乙個整型陣列 arr
和乙個大小為 w 的視窗從陣列的最左邊滑到最右邊,視窗每次向右邊 滑乙個位置。
例如,陣列為[4,3,5,4,3,3,6,7]
,視窗大小為
3 時:
[4 3 5] 4 3 3 6 7 視窗中最大值為 5
4 [3 5 4] 3 3 6 7 視窗中最大值為 5
4 3 [5 4 3] 3 6 7 視窗中最大值為 5
4 3 5 [4 3 3] 6 7 視窗中最大值為 4
4 3 5 4 [3 3 6] 7 視窗中最大值為 6
4 3 5 4 3 [3 6 7] 視窗中最大值為 7
如果陣列長度為
n ,視窗大小為
w ,則一共產生 n -
w +1
個視窗的最大值。
請實現乙個函式。
輸入:整型陣列
arr,視窗大小為
w 。
輸出:乙個長度為 n -
w +1
的陣列
res,
res[i]
表示每一種視窗狀態下的最大值。
以本題為例,結果應該返回
解題思路:
視窗滑動過程中如果最大值位於視窗的最末尾,移除的是視窗的最大值,就需要找到新的最大值,所以可以用乙個陣列或佇列記錄下視窗內已排好續的陣列索引,每次滑動視窗時比較是否是移除了最尾部的最大值。
可以用雙端佇列來優化,始終將最大值到隊頭,如果最大值移除了,就輪循佇列,找到新的最大值。
使用了乙個佇列儲存將視窗內的值的索引,且將索引對應的陣列值進行由大到小的排序,佇列頭部放最大值索引,佇列尾部放小值索引(佇列中資料對應的陣列值是由大到小的排序)每次新來乙個值時,與佇列尾部的資料進行比較,如果比尾部的資料大,就將尾部資料彈出,在比較尾部的下乙個資料,直到找小於佇列尾部資料的值或者隊列為空的位置將新的arr[i]的索引插入到佇列,之所以要彈出小於arr[i]的值,是因為在當前的視窗內最大值一定是 ≥ arr[i],並且在接下來的包含arr[i] 的 (w-1)個 視窗內,最大值也一定是 ≥ arr[i],所以沒有必要保留小於arr[i]的值,因為佇列內部的資料是陣列的索引 且是由小到大的,注意佇列儲存的不是陣列的具體值而是陣列的索引,每次新增完成後需要校驗佇列頭部的資料即最大值的索引是否在 當前的視窗範圍內,如果不在了,需要從隊頭彈出不在視窗內的陣列索引。
假設遍歷到 arr[i],qmax 的放入規則為:
.如果 qmax 為空,直接把下標 i 放進 qmax,放入過程結束。
.如果 qmax 不為空,取出當前 qmax 隊尾存放的下標,假設為 j。
1)如果 arr[j]>arr[i],直接把下標 i 放進 qmax 的隊尾,放入過程結束。
2)如果 arr[j]<=arr[i],把 j 從 qmax 中彈出,重複 qmax 的放入規則。
public static void main(string args) ;
int res = getres(arr, 3);
system.out.println(arrays.tostring(res));
} /**
* 視窗滑動走掉的值是最大值時就得用新新增的值,與舊得視窗值比較找到最大得值
* 可以用雙端佇列來優化,始終將最大值到隊頭,如果最大值移除了,就輪循佇列,找到新的最大值
* * 假設遍歷到 arr[i],qmax 的放入規則為:
* 1.如果 qmax 為空,直接把下標 i 放進 qmax,放入過程結束。
* 2.如果 qmax 不為空,取出當前 qmax 隊尾存放的下標,假設為 j。
* 1)如果 arr[j]>arr[i],直接把下標 i 放進 qmax 的隊尾,放入過程結束。
* 2)如果 arr[j]<=arr[i],把 j 從 qmax 中彈出,重複 qmax 的放入規則。
*/public static int getres(int arr, int w) else
}if (maxindexqueue.peekfirst() == i-w )
if (i+1>=w) res[i+1-w] = arr[maxindexqueue.peekfirst()];
} return res; }
/*** 優化中間的while迴圈,優化思路就是取if的反值
*/public static int getres2(int arr, int w)
// 如果arr[i] 小於最末尾值值時,直接加入佇列,
// 陣列 arr[i]之後的資料一直在遞減,某一時刻 arr[i]就會成為最大值
maxindexqueue.add(i);
if (maxindexqueue.peekfirst() == i-w )
if (i+1>=w) res[i+1-w] = arr[maxindexqueue.peekfirst()];
} return res; }
/*** 滑動視窗最小值
*/public static int getmin(int arr, int w)
minque.addlast(i);
if (minque.size() > w) minque.removefirst();
if (i + 1 >= w)
} return result;
}
滑動最小值
時間限制 1 sec 記憶體限制 128 mb 提交 127 解決 27 提交 狀態 討論版 命題人 admin 題目描述 給定乙個長度為 n 的數列 a0,a1,an 1和乙個整數k。求數列 bi min ai,ai 1 ai k 1 i 0,n 特別的,對於 i n k 的 bi 0。輸入第一行...
求滑動視窗中的最大值和最小值
滑動視窗 一般使用雙指標演算法,左指標l和右指標r之間的空間稱為視窗,由於指標是不斷移動的,從而視窗也可以移動,稱為滑動視窗。滑動視窗的最值 由於視窗是移動的,移動的過程中有新元素的加入也有舊元素的彈出。每一次元素的加入或彈出都可能使視窗中元素的最值發生變化,也正是會發生變化,使得無法直接獲取任意時...
滑動視窗的最大值 最小值更新結構
視窗 可以理解為一段連續子陣列,下標範圍為 l,r 滑動視窗 l r會改變,改變方式是右移,r會右移,l也會右移,但始終保持l滑動視窗的最大值 最小值更新結構 對某乙個陣列,初始時,l r均位於最左端,l r只可以向右移,且始終有l以陣列arr 為例解釋滑動視窗最大值更新結構維護的過程,使用 來表示...