滑動窗口技術(Sliding windows technique)

一、用途:
該技術將很少出現問題的嵌套for循環轉換爲單個for循環,從而減少時間複雜度。
二、例題:

例題1:
給定一個長度爲n的數組。
求連續k個元素的和最大值sum
Input : arr[] = {100, 200, 300, 400}
k = 2
Output : 700

  • 方法一:暴力嵌套
int maxSum(int arr[], int k) 
{ 
    int max_sum = INT_MIN; 
    for (int i = 0; i < arr.length - k + 1; i++) { 
        int current_sum = 0; 
        for (int j = 0; j < k; j++) 
            current_sum = current_sum + arr[i + j]; 
        max_sum = max(current_sum, max_sum); 
    } 
    return max_sum; 
} 
  • 方法二:我們利用滑動窗口技術將它改成一個for循環,以減少時間複雜度

1.我們使用一個窗口,窗口一共有k個窗格,第一個窗格放在數組元素的最最左邊。我們利用一個for循環算出這個窗口中數組前k個元素的和,並把值存入window_sum

2.我們線性地移動這個窗口,直到這個窗口最右邊的窗格到達數組的最右邊元素。

3.爲了得到移動 後的窗口中的元素的和,將原來窗口的第一個窗格的元素除去,並且加上當前窗口最右邊的值

	public int maxSum(int arr[],int k)
	{
	//第一個窗口的值
		int window_sum=0;
		for(int i=0;i<k;i++)
			window_sum=window_sum+arr[i];
			//初始化最大值
		int max_sum=window_sum;
		
		for(int i=k;i<arr.length;i++)
		{
		//線性移動窗口,直到窗口最右邊窗格到達數組盡頭
			window_sum=window_sum+arr[i]-arr[i-k];
			max_sum=Math.max(max_sum,window_sum);
		}
		return max_sum;
	}

例題2:
給定一個數組 nums,有一個大小爲 k 的滑動窗口從數組的最左側移動到數組的最右側。你只可以看到在滑動窗口 k 內的數字。滑動窗口每次只向右移動一位。
返回滑動窗口最大值。
示例:
輸入: nums = [1,3,-1,-3,5,3,6,7], 和 k = 3
輸出: [3,3,5,5,6,7]

該題是LeetCode239題。
在這裏插入圖片描述
利用滑動窗口。
思路:
特殊情況:長度爲0的數組,則返回[]
一般情況:

  • 1.利用一個 雙端隊列,在隊列中存儲元素在數組中的位置角標, 並且使隊列的首元素是最大值
  • 2.當遍歷到一個新元素時:
    如果隊列裏有比當前元素小的,就將其移除隊列;
    如果隊列裏沒有比當前元素小的,就將其添加到隊列裏;
    如果隊列元素位置之差大於 k,就將隊首元素移除。
  • 3。將隊列中的第一個元素添加到數組ans中,返回ans
public int[] maxSlidingWindow(int[] nums,int k)
	{
		if(nums.length==0)
			return new int[0];
			
		int[] res = new int[nums.length - k + 1];
		Deque<Integer> deque = new LinkedList<>();
		for (int i = 0; i < nums.length; i++) {
while(!deque.isEmpty()&&nums[i]>nums[deque.getLast()])
				deque.removeLast();
			deque.add(i);
			if(deque.getFirst()==i-k)
				deque.removeFirst();	
			if(i>=k-1)
				res[i-k+1]=nums[deque.getFirst()];
		}
		return res;
	}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章