LeetCode刷題系列:LeetCode 523. 連續的子數組和

題目:給定一個包含非負數的數組和一個目標整數 k,編寫一個函數來判斷該數組是否含有連續的子數組,其大小至少爲 2,總和爲 k 的倍數,即總和爲 n*k,其中 n 也是一個整數

輸入: [23,2,4,6,7], k = 6
輸出: True
解釋: [2,4] 是一個大小爲 2 的子數組,並且和爲 6。

輸入: [23,2,6,4,7], k = 6
輸出: True
解釋: [23,2,6,4,7]是大小爲 5 的子數組,並且和爲 42。

說明:

  1. 數組的長度不會超過10,000。
  2. 你可以認爲所有數字總和在 32 位有符號整數範圍內。
 思路:以sum[i] 表示從下標0 到 下標 i 子數組的和,則下標  i 到 j的子數組,記爲 [i,j]的和爲 sum[j] - sum[i-1],
   子數組 [i,j] 如果是 k 的倍數,則有 (sum[j] - sum[i-1])%k 等於 0 ,即 sum[j]%k == sum[i-1]%k。
   我們可以用一個 map結構存放 (sum[i]%k,index) 的值,index爲下標,再遍歷 map 結構,
   1、當key==0時,     *   
       只需要數組中有兩個連續的 0 即可
   2、當key!=0時
     1)如果對應的鏈表只有一個元素,即只有一個下標時,看是否該下標 i 大於1(因爲要求數組大小最少爲2),是的話,則證明sum[i]%k == 0,子數組[0,i]之和爲k的倍數
     2)如果對應的鏈表有兩個及以上個元素,則說明一定滿足有個子數組長度大於2 ,且和爲k 的倍數的條件
      注意: 子數組有兩個連續的0時,也算做滿足條件,因爲 (0 + 0) /k = 0
public boolean checkSubarraySum(int[] nums, int k) {

    boolean flag = false;
    if(nums.length<2){
        return false;
    }
    Map<Integer,List<Integer>>  map = new HashMap<>(); //key = sum[i]%k ,value = [index1,index2,...]

    if(k!=0) {
        int[]  sum = new int[nums.length];  //存放數組從下標0開始,到當前下標i的和sum[i]
        for(int i=0;i<nums.length;i++){
            if(i==0){
                sum[i] = nums[i];
            }else {
                if(nums[i] ==0 && nums[i-1] == 0){ // 子數組有兩個連續的0時,也算做滿足條件,因爲 (0 + 0) /k = 0
                    flag = true;
                    break;
                }
                sum[i] = sum[i-1] + nums[i];
            }
        }
        //填充 map 結構,key = sum[i]%k ,value = [index1,index2,...]
        for(int i=0;i<sum.length;i++){
            int key = sum[i]%k;
            if(!map.containsKey(key)){
                List<Integer> list = new ArrayList<>();
                list.add(i);
                map.put(key,list);
            }else {
                map.get(key).add(i);
            }
        }

            for(Map.Entry<Integer,List<Integer>> entry:map.entrySet()){
                if(entry.getKey()==0){
                    if(map.get(0).size()>=2){
                        flag = true;
                        break;
                    }else if(map.get(0).get(0)>=1){
                        flag = true;
                        break;
                    }
                }
                List<Integer>  list = entry.getValue();
                for (int i= list.size()-1;i>0;i--){
                    int index = list.get(i);
                    if(nums[index]!=0&&index-list.get(0)>1){ //排除類似於 [2,0] k = 2 這種情況
                        flag = true;
                        break;
                }
                if(flag){
                    break;
                }
            }
            if(flag){
                break;
            }
        }
    }else {
        for (int i = 1; i < nums.length; i++) {
            if(nums[i-1] == 0 && nums[i] ==0){   //當 k等於 0的時候,只需要數組中有兩個連續的 0 即可
                flag = true;
                break;
            }
        }
    }

    return flag;
}

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章