給你一個整數數組 nums 和一個整數?k ,編寫一個函數來判斷該數組是否含有同時滿足下述條件的連續子數組:
子數組大小 至少為 2 ,且
子數組元素總和為 k 的倍數。
如果存在,返回 true ;否則,返回 false 。
如果存在一個整數 n ,令整數 x 符合 x = n * k ,則稱 x 是 k 的一個倍數。
- 示例 1:
輸入:nums = [23,2,4,6,7], k = 6
輸出:true
解釋:[2,4] 是一個大小為 2 的子數組,并且和為 6 。
- 示例 2:
輸入:nums = [23,2,6,4,7], k = 6
輸出:true
解釋:[23, 2, 6, 4, 7] 是大小為 5 的子數組,并且和為 42 。
42 是 6 的倍數,因為 42 = 7 * 6 且 7 是一個整數。
- 示例 3:
輸入:nums = [23,2,6,4,7], k = 13
輸出:false
解題思路
條件分析
- 數組元素只能是正數
- 數組總和可以用int表示
- 數組長度大,不能暴力
map
一個數字x可以看成由兩部分組成
- k的倍數(n*k)
- 整除k以后的余數y(x%k)組成
例如x=10,k=3
x就可以看成x=3*3+1組成的
假設sum[i]代表子數組[0,i]的和
所以對于sum[j]-sum[i]只要我們保證它們的余數y是相同的,那么前面的算式就變成了k的若干倍-k的若干倍,結果仍然是k的倍數
例如 sum[i]=10,sum[j]=13,k=3,
sum[i]=33+1
sum[j]=43+1
它們對于整除k都有相同的余數,因此直接抵消掉,就變為了n1 * 3-n2 * 3=(n1-n2)*3 ,結果仍然是3的整數倍。
所以我們可以使用map,記錄不同余數以及它們出現的位置(用于判斷子數組長度是否大于1)。
代碼
func checkSubarraySum(nums []int, k int) bool {m := map[int]int{}m[0]=0rem:=0for i, num := range nums {rem=(num+rem)%ki2,ok := m[rem]if ok {if i-i2>=1{return true}}else {m[rem]=i+1}}return false}