滑動窗口類演算法題

209. 長度最小的子數組

力扣地址

暴力破解思路

時間複雜度有點高,O(n3),通不過測試,要進行優化

func minSubArrayLen(s int, nums []int) int {
    length := len(nums)
    min := length + 1
    for i := 0; i< length; i++{
        for j := i; j<length;j++{
            if j-i+1 >=min{
                break //這一趟已經沒必要找了
            }
            sum := 0
            for k := i;k<=j;k++{
                sum += nums[k]
            }
            if sum >= s{
                min = j-i+1
                break //這一趟已經找到,可以直接返回
            }
        }
    }

    //沒有找到滿足條件的連續子數組,返回0
    if min == length + 1{
        return 0
    }
    return min
}

暴力破解思路優化1

優化方向:暴力破解第三個for循環其實可以去除的,因為我們對[i,j]數組求和是一個連續的過程,是一個一個添加元素的,他們滿足sum[i,j] = sum[i,j-1] + nums[j].

func minSubArrayLen(s int, nums []int) int {
    length := len(nums)
    min := length + 1
    for i := 0; i< length; i++{
        sum := nums[i]
        for j := i; j<length;j++{
            if j-i+1 >=min{
                break //這一趟已經沒必要找了
            }
            if j > i{
               sum += nums[j]
            }
            if sum >= s{
                min = j-i+1
                break //這一趟已經找到,可以直接返回
            }
        }
    }

    //沒有找到滿足條件的連續子數組,返回0
    if min == length + 1{
        return 0
    }
    return min
}

暴力破解思路優化2

優化思路:第二個for循環還是可以加快點,因為數組和sum[i,j]是有序增加的,所以就想到二分查找的優化方法。

滑動窗口思路

func minSubArrayLen(s int, nums []int) int {
    //滑動窗口的解法:因為題目是一個連續子數組最小問題,滿足滑動窗口類型
    length := len(nums)
    l,r := 0,-1 // nums[l,r] 是我們的一個滑動窗口,默認是沒有元素
    sum := 0
    min := length +1 
    for l < length{
        if sum >= s{ //滑動窗口裡面和已經滿足要求,就不用繼續向右滑
            sum -= nums[l]
            l++
        }else if r+1<length{//可以允許右滑
            r++
            sum += nums[r]
        }else{
            break //滑動窗口不能右滑了,找不到,直接返回
        }

        if sum >= s && r-l+1 < min{
            min = r-l+1
        }
    }

    if min == length +1 {
        return 0
    }
    return min
}
  1. 無重複字元的最長子串
  2. Find All Anagrams in a String
  3. 最小覆蓋子串 && 76. Minimum Window Substring