目录
1.左右两边子数组的和相等
题目:
给你一个整数数组 nums
,请计算数组的 中心下标 。
数组 中心下标 是数组的一个下标,其左侧所有元素相加的和等于右侧所有元素相加的和。
如果中心下标位于数组最左端,那么左侧数之和视为 0
,因为在下标的左侧不存在元素。这一点对于中心下标位于数组最右端同样适用。
如果数组有多个中心下标,应该返回 最靠近左边 的那一个。如果数组不存在中心下标,返回 -1
。
示例 1:
输入:nums = [1,7,3,6,5,6] 输出:3 解释: 中心下标是 3 。 左侧数之和 sum = nums[0] + nums[1] + nums[2] = 1 + 7 + 3 = 11 , 右侧数之和 sum = nums[4] + nums[5] = 5 + 6 = 11 ,二者相等。
示例 2:
输入:nums = [1, 2, 3] 输出:-1 解释: 数组中不存在满足此条件的中心下标。
示例 3:
输入:nums = [2, 1, -1] 输出:0 解释: 中心下标是 0 。 左侧数之和 sum = 0 ,(下标 0 左侧不存在元素), 右侧数之和 sum = nums[1] + nums[2] = 1 + -1 = 0 。
代码实现:
class Solution {
public int pivotIndex(int[] nums) {
int n=nums.length;
int[] left=new int[n+1];//该数组是nums的前缀和数组
int[] right=new int[n+1];//该数组是nums的后缀和数组
for(int i=1;i<n;i++){//从前向后遍历相加
left[i]=left[i-1]+nums[i-1];
}
for(int x=n-2;x>=0;x--){//从后向前遍历相加
right[x]=right[x+1]+nums[x+1];
}
for(int y=0;y<n;y++){//遍历两个数组,若出现前缀和等于后缀和说明此下标是中心下标
if(left[y]==right[y]){
return y;
}
}
return -1;
}
}
结果:
2.和可被 K 整除的子数组
题目:
给定一个整数数组 nums
和一个整数 k
,返回其中元素之和可被 k
整除的(连续、非空) 子数组 的数目。
子数组 是数组的 连续 部分。
示例 1:
输入:nums = [4,5,0,-2,-3,1], k = 5 输出:7 解释: 有 7 个子数组满足其元素之和可被 k = 5 整除: [4, 5, 0, -2, -3, 1], [5], [5, 0], [5, 0, -2, -3], [0], [0, -2, -3], [-2, -3]
示例 2:
输入: nums = [5], k = 9 输出: 0
代码实现:
class Solution {
public int subarraysDivByK(int[] nums, int k) {
int n=nums.length;
int left=0;
int right=0;
int num=0;
int sum=1;
while(right<n){
sum +=nums[right];
if(sum%k==0){//当sum大于k,左指针右移,并将上一个左指针的值减去
sum -=nums[left];
left++;
num++;
}
right++;
num++;
}
return num;
}
}
使用的滑动窗口算法,但第二个结果不符合
正确代码:
class Solution {
public int subarraysDivByK(int[] nums, int k) {
Map<Integer, Integer> record = new HashMap<Integer, Integer>();
record.put(0, 1);
int sum = 0, ans = 0;
for (int elem : nums) {
sum += elem;
// 注意 Java 取模的特殊性,当被除数为负数时取模结果为负数,需要纠正
int modulus = (sum % k + k) % k;
int same = record.getOrDefault(modulus, 0);
ans += same;
record.put(modulus, same + 1);
}
return ans;
}
}
结果: