leecode_523 连续的子数组和

连续的子数组和

知识点:动态规划

题目:

给定一个包含非负数的数组和一个目标整数 k,编写一个函数来判断该数组是否含有连续的子数组,其大小至少为 2,总和为 k 的倍数,即总和为 n*k,其中 n 也是一个整数。

示例 1:

输入: [23,2,4,6,7], k = 6
输出: True
解释: [2,4] 是一个大小为 2 的子数组,并且和为 6。
示例 2:

输入: [23,2,6,4,7], k = 6
输出: True
解释: [23,2,6,4,7]是大小为 5 的子数组,并且和为 42。

解析

  1. 暴力法

  2. 使用HashMap:

    在这种方法中,我们使用 HashMap 来保存到第 i 个元素为止的累积和,但我们对这个前缀和除以 k取余数。原因如下:
    
    我们遍历一遍给定的数组,记录到当前位置为止的 sum。一旦我们找到新的 sum 的值(即在 HashMap 中没有这个值),我们就往 HashMap 中插入一条记录 (sum%k, i)。
    
    现在,假设第 i 个位置的 sum值为 rem 。如果以 ii 为左端点的任何子数组的和是 kk 的倍数,比方说这个位置为 jj ,那么 HashMap 中第 jj 个元素保存的值为 (rem + n*k)%k,其中 n是某个大于 0 的整数。我们会发现 (rem + n*k)%k = rem ,也就是跟第 ii 个元素保存到 HashMap 中的值相同。
    
    基于这一观察,我们得出结论:无论何时,只要 sum%ksum 的值已经被放入 HashMap 中了,代表着有两个索引 ii 和 jj ,它们之间元素的和是 kk 的整数倍。因此,只要 HashMap 中有相同的 sum%k ,我们就可以直接返回 True。
    
    链接:https://leetcode-cn.com/problems/continuous-subarray-sum/solution/lian-xu-de-zi-
    

    代码

    方法2:

    //使用HashMap    
    public static boolean checkSubarraySum(int[] nums, int k) {
            HashMap<Integer, Integer> map = new HashMap<>();
            map.put(0, -1);
            int sum = 0;
            for (int i = 0; i < nums.length; i++) {
                sum += nums[i];
                if (k != 0)
                    sum = sum % k;
                if (map.containsKey(sum)) {
                    if (i - map.get(sum) > 1) {
                        return true;
                    }
                } else {
                    map.put(sum, i);
                }
            }
            return false;
        }
    

    复杂度:

    时间复杂度: O(n)O(n) 。仅需要遍历 nums数组一遍。
    空间复杂度: O(min(n,k)) 。HashMap最多包含 min(n,k)个不同的元素。

    方法1:

        //1. 暴力解法
        public static boolean checkSubarraySum(int[] nums, int k) {
            int len = nums.length;
            for (int i = 0; i < len; i++) {
                int sum = nums[i];
                for (int j = i + 1; j < len; j++) {
                    sum += nums[j];
                    if (sum == k || (k != 0 && sum % k == 0)) {
                        System.out.println("sum: " + sum + " i: " + i + " j: " + j);
                        return true;
                    }
                }
            }
            return false;
        }
    

    复杂度:

    时间复杂度: O(n^2)。为了考虑每一个子数组,我们需要一个 2 重嵌套的循环。
    空间复杂度: O(n) 。 使用了长度为 n的 sumsum 数组。

你可能感兴趣的:(刷题)