Leetcode523. 连续的子数组和

链接:https://leetcode-cn.com/problems/continuous-subarray-sum

给定一个包含非负数的数组和一个目标整数 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。
说明:

数组的长度不会超过10,000。
你可以认为所有数字总和在 32 位有符号整数范围内。

解1:优化的暴力

  先预处理前缀和,然后暴力枚举所有可能的区间下标 [ i, j ],然后由两个前缀和相减得到区间和,再判断是否满足  n%k==sum。时间复杂度O(n2)

  需要注意的是  sum=0  和 k=0 的情况,搞不好就除零异常了。

class Solution {
public:
    bool checkSubarraySum(vector<int>& nums, int k) {
        int n=nums.size();
        vector<int> pre_sum(n+1);
        for(int i=1;i<=n;i++){
            pre_sum[i]+=pre_sum[i-1]+nums[i-1];
        }
        for(int i=0;i<n-1;i++){
            for(int j=i+1;j<n;j++){
                int sum=pre_sum[j+1]-pre_sum[i];
                if(sum==0 ||(k && sum%k==0))return true;
            }
        }
        return false;
    }
};

解2:哈希表----引自力扣题解

  在这种方法中,我们使用 HashMap 来保存到第 i 个元素为止的累积和,但我们对这个前缀和除以 k 取余数。原因如下:

我们遍历一遍给定的数组,记录到当前位置为止的 sum%k 。一旦我们找到新的 sum%k的值(即在 HashMap 中没有这个值),我们就往 HashMap 中插入一条记录 (sum%k, i)

  现在,假设第 i 个位置的 sum%k 的值为 rem 。如果以 i 为左端点的任何子数组的和是 k 的倍数,比方说这个位置为 j ,那么 HashMap 中第 j 个元素保存的值为 (rem+n∗k)%k ,其中 n 是某个大于 0 的整数。我们会发现 (rem+n∗k)%k=rem ,也就是跟第 i 个元素保存到 HashMap 中的值相同。

基于这一观察,我们得出结论:无论何时,只要 sum%k 的值已经被放入 HashMap 中了,代表着有两个索引 i 和 j ,它们之间元素的和是 k 的整数倍。因此,只要 HashMap 中有相同的 sum%k ,我们就可以直接返回 True 。

class Solution {
public:
    bool checkSubarraySum(vector<int>& nums, int k) {
        map<int,int> mp;
        int presum=0;
        mp[0]=-1;          //?
        for(int i=0;i<nums.size();i++){
            presum+=nums[i];              //
            if(k!=0) presum%=k;

            if(1 == mp.count(presum)){
                if(i-mp[presum]>1)       //
                    return true;
            }
            else mp[presum]=i;
        }
        return false;
    }
};

原文地址:https://www.cnblogs.com/reflecter/p/12037023.html

时间: 2024-11-06 09:28:20

Leetcode523. 连续的子数组和的相关文章

一个有N个整数元素的一维数组{A[0],A[1],....,A[N-1],A[N]},这个数组有很多连续的子数组,那么连续子数组之和的最大的一个的值是什么?

1.动态规划的思想解决 /** * 在时间复杂度为O(N)内找出数组中最大的子序列的累加和 */ public static int sumNum(int[] array) { int n = array.length; int all = array[n - 1], start = array[n - 1]; int count = 0; for (int i = n - 2; i >= 0; i--) { if ((start + array[i]) > array[i]) { start

674. Longest Continuous Increasing Subsequence最长连续递增子数组

[抄题]: Given an unsorted array of integers, find the length of longest continuous increasing subsequence (subarray). Example 1: Input: [1,3,5,4,7] Output: 3 Explanation: The longest continuous increasing subsequence is [1,3,5], its length is 3. Even t

Leetcode 581.最短无序连续子数组

最短无序连续子数组 给定一个整数数组,你需要寻找一个连续的子数组,如果对这个子数组进行升序排序,那么整个数组都会变为升序排序. 你找到的子数组应是最短的,请输出它的长度. 示例 1: 输入: [2, 6, 4, 8, 10, 9, 15] 输出: 5 解释: 你只需要对 [6, 4, 8, 10, 9] 进行升序排序,那么整个表都会变为升序排序. 说明 : 输入的数组长度范围在 [1, 10,000]. 输入的数组可能包含重复元素 ,所以升序的意思是<=. 题目给了我们一个nums array,

最短无序连续子数组

题目描述 给定一个整数数组,你需要寻找一个连续的子数组,如果对这个子数组进行升序排序,那么整个数组都会变为升序排序. 你找到的子数组应是最短的,请输出它的长度. 示例 1: 输入: [2, 6, 4, 8, 10, 9, 15] 输出: 5 解释: 你只需要对 [6, 4, 8, 10, 9] 进行升序排序,那么整个表都会变为升序排序. 说明 : 输入的数组长度范围在 [1, 10,000]. 输入的数组可能包含重复元素 ,所以升序的意思是<=. 分析 这个题目我就比较偷懒了,直接排序然后找前后

LeetCode 581. 最短无序连续子数组(Shortest Unsorted Continuous Subarray)

581. 最短无序连续子数组 581. Shortest Unsorted Continuous Subarray 题目描述 给定一个整型数组,你需要寻找一个连续的子数组,如果对这个子数组进行升序排序,那么整个数组都会变为升序排序. 你找到的子数组应是最短的,请输出它的长度. LeetCode581. Shortest Unsorted Continuous Subarray 示例 1: 输入: [2, 6, 4, 8, 10, 9, 15] 输出: 5 解释: 你只需要对 [6, 4, 8,

LeetCode 53. Maximum Subarray(最大的子数组)

Find the contiguous subarray within an array (containing at least one number) which has the largest sum. For example, given the array [-2,1,-3,4,-1,2,1,-5,4],the contiguous subarray [4,-1,2,1] has the largest sum = 6. click to show more practice. Mor

找出一个整数数组的和最大的连续子数组

题目: 给任意一个整数数组,找出这个数组的和最大的连续子数组(子数组的和最大且子数组连续).要求:算法的时间复杂度为O(n). 程序设计思想: 1:用maxValue记录当前连续子数组和为最大的和的值,初始化其值为:maxValue=a[0].注:记数组为a[n]. 2:这个过程总的思想就是,从数组头开始往后,每次加进一个值,它们的和记为tempValue,若tempValue比新加进来的数值本身要小,应该从这个位置开始重新开始计算tempValue的值.而每次的tempValue都应该和max

[LeetCode] Shortest Unsorted Continuous Subarray 最短无序连续子数组

Given an integer array, you need to find one continuous subarray that if you only sort this subarray in ascending order, then the whole array will be sorted in ascending order, too. You need to find the shortest such subarray and output its length. E

(算法)和为0的最大连续子数组

题目: 和为零的最大连续子数组 思路: 我首先想到的是前缀数组和,遍历一遍数组,计算出sum[i](表示从0-i的子数组之和). 有了前缀数组和,只要sum[i]=sum[j](i<j),那么区间[i+1,j]就是和为零的子数组,只要在遍历前缀数组和时记录最长的区间即可. 需要注意的是:当sum[i]等于0时,其区间为[0,i]. 在判断sum[i]=sum[j](i<j)时,有个查找的过程,要么直接遍历j左边的所有数(增加时间复杂度),要么通过map来存储对应和的下标位置(空间换时间).(详