LeetCode 523. 连续的子数组和

题目链接

523. 连续的子数组和

思路分析

这个题我第一次做的时候只会暴力查,外层循环i遍历整个数组,内层循环遍历[i, nums.length - 1],内层循环计算当前连续数组的和,如果遇到sum == k或者k != 0 && sum % k == 0的情况,就返回true。当外层循环也遍历结束后,我们应该返回false
这样做的时间复杂度是O(n^2), 空间复杂度是O(1)。

代码实现

class Solution {
    public boolean checkSubarraySum(int[] nums, int k) {
        for(int i = 0; i < nums.length; i++){
            int sum = nums[i];
            for(int j = i+1; j < nums.length; j++){
                sum += nums[j];
                if(sum == k || (k != 0 && sum % k == 0)){
                    return true;
                }
            }
        }
        return false;
    }
}

后记

在做完之后,我看到了用HashMap做的O(n)时间复杂度的做法,说实话真的NB,但是第一次做肯定是想不到这种思路的- -
利用同余的思想,如果两个余数相等,代表这两个余数之间的数组和是K的倍数,但是因为要求数组长度必须大于等于2,所以还得判断其距离差。
HashMapkey用于存放余数,value用于存放余数出现的位置。
不得不说这个做法是真的巧妙~

O(n)官方实现

class Solution {
public boolean checkSubarraySum(int[] nums, int k){
        int sum = 0;
        Map<Integer, Integer> map = new HashMap<>(); // 键为 preSum % k, 值为索引,当然要特殊处理k == 0的情况
        map.put(0, -1);
        for (int i = 0; i < nums.length; i++) {
            sum += nums[i];
            int temp = k == 0 ? sum : sum % k;
            if(map.containsKey(temp)){ // 出现相同的键,如果子数组长度少于2, 不需要更新值。
                if(i - map.get(temp) > 1) // 子数组要求长度至少为2。
                    return true;
                continue;
            }
            map.put(temp, i);
        }
        return false;
    }
}
posted @ 2020-10-11 19:59  ZJPang  阅读(75)  评论(0编辑  收藏  举报