【力扣】523. 连续的子数组和
给你一个整数数组 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
提示:
1 <= nums.length <= 105
0 <= nums[i] <= 109
0 <= sum(nums[i]) <= 231 - 1
1 <= k <= 231 - 1来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/continuous-subarray-sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解法1:
public boolean checkSubarraySum(int[] nums, int k) { //两个条件: //1.子数组的长度>=2 //2.子数组元素总和为k的倍数 //首先是比较简单就可以想起来的方法: int length = nums.length; for(int i = 0; i< length; i++){ for(int j = i+1; j < length; j++){ //定义j= i+1这样说吗 i 和 j之间的差值是大于等于1的,两个之间的长度为大于等于2 int temp = 0; for(int z = i ; z <= j; z++){ temp+=nums[z]; } if((temp % k == 0 && temp >= k) || temp == 0){ //System.out.println("i = " + i + "; j = " + j); return true; } } } return false; }
使用暴力破解,时间复杂度为:O(n^3),答案很明显的超出了时间限制
解法2:
public boolean checkSubarraySum(int[] nums, int k) { //两个条件: //1.子数组的长度>=2 //2.子数组元素总和为k的倍数 //还有什么可以优化的方案吗? //使用额外的空间,使用空间换时间的想法 //我们可以看到,有很大一部分计算,实际上之前可能已经计算过了 int length = nums.length; if(length < 2){ return false; } //使用额外的空间 //key = 储存当前前缀和的余数 //value = 当前余数对应的索引位置,以最先出现的为准 //终止条件: //当map中出现余数相同的key,value对应的索引的位置 >=2 Map<Integer, Integer> map = new HashMap<Integer, Integer>(); //这个字段的含义是什么? //是当前能够求的余数 int remainder = 0; // map.put(remainder, -1); for(int i = 0; i < length; i++){ //得到 之前求得的余数跟现在的数相加得到的余数 remainder = (remainder + nums[i]) % k; if(map.containsKey(remainder)){ int index = map.get(remainder); if(i - index >= 2 ){ return true; } } else { map.put(remainder,i); } } return false; }
一个入行不久的Java开发,越学习越感觉知识太多,自身了解太少,只能不断追寻