目录
针对连续子数组和相关问题 一般采用前缀和 + hashmap
是K的倍数 采取同余定理
相关题目:
523. 连续的子数组和
public class CheckSubarraySum {
// 前缀和 + 同余定理 + hashmap
public boolean checkSubarraySum(int[] nums, int k) {
int m = nums.length;
if (m < 2) {
return false;
}
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
map.put(0, -1);
int remainder = 0;
for (int i = 0; i < m; i++) {
remainder = (remainder + nums[i]) % k;
if (map.containsKey(remainder)) {
int prevIndex = map.get(remainder);
if (i - prevIndex >= 2) {
return true;
}
} else {
map.put(remainder, i);
}
}
return false;
}
// 前缀和, 超时
public boolean checkSubarraySum2(int[] nums, int k) {
int n = nums.length;
int[] sum = new int[n];
sum[0] = nums[0];
for (int i = 1; i < n; i++) {
sum[i] = sum[i - 1] + nums[i];
}
for (int i = 1; i < n; i++) {
if (sum[i] % k == 0) {
return true;
}
for (int j = 0; j < i - 1; j++) {
if ((sum[i] - sum[j]) % k == 0) {
return true;
}
}
}
return false;
}
// 暴力超时
public boolean checkSubarraySum1(int[] nums, int k) {
int n = nums.length;
for (int i = 0; i < n - 1; i++) {
for (int j = i + 1; j < n; j++) {
int sum = 0;
for (int z = i; z <= j; z++) {
sum += nums[z];
}
if (sum % k == 0) {
return true;
}
}
}
return false;
}
public static void main(String[] args) {
int[] nums = new int[]{23, 2, 6, 4, 7};
CheckSubarraySum solution = new CheckSubarraySum();
System.out.println(solution.checkSubarraySum(nums, 6));
}
}
560. 和为 K 的子数组
public class SubarraySum {
// 560. 和为 K 的子数组
public int subarraySum(int[] nums, int k) {
int count = 0, pre = 0;
HashMap<Integer, Integer> mp = new HashMap<>();
mp.put(0, 1);
for (int num : nums) {
pre += num;
if (mp.containsKey(pre - k))
count += mp.get(pre - k);
mp.put(pre, mp.getOrDefault(pre, 0) + 1);
}
return count;
}
public int subarraySum1(int[] nums, int k) {
int n = nums.length;
int[] sum = new int[n];
sum[0] = nums[0];
for (int i = 1; i < n; i++) {
sum[i] = sum[i - 1] + nums[i];
}
int ans = 0;
for (int i = 0; i < n; i++) {
if (sum[i] == k) {
ans++;
}
for (int j = 0; j < i; j++) {
if (sum[i] - sum[j] == k) {
ans++;
}
}
}
return ans;
}
public static void main(String[] args) {
SubarraySum solution = new SubarraySum();
int[] nums = new int[]{1, 1, 1};
System.out.println(solution.subarraySum(nums, 2));
}
}
974. 和可被 K 整除的子数组
public class SubarraysDivByK {
// 974. 和可被 K 整除的子数组
public int subarraysDivByK(int[] nums, int k) {
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
map.put(0, 1);
int remainder = 0;
int result = 0;
for (int num : nums) {
// 注意负数余数
remainder = ((remainder + num) % k + k) % k;
if (map.containsKey(remainder)) {
result += map.get(remainder);
map.put(remainder, map.get(remainder) + 1);
} else {
map.put(remainder, 1);
}
}
return result;
}
public static void main(String[] args) {
SubarraysDivByK solution = new SubarraysDivByK();
int[] nums = new int[]{4,5,0,-2,-3,1};
System.out.println(solution.subarraysDivByK(nums,5));
}
}
713. 乘积小于K的子数组
public class NumSubarrayProductLessThanK {
// 超时
public int numSubarrayProductLessThanK(int[] nums, int k) {
int n = nums.length;
double[] sum = new double[n];
sum[0] = Math.log(nums[0]);
for (int i = 1; i < n; i++) {
sum[i] = sum[i - 1] + Math.log(nums[i]);
}
int ans = 0;
for (int i = 0; i < n; i++) {
if (sum[i] < Math.log(k) - 1e-9) {
ans++;
}
for (int j = 0; j < i; j++) {
if (sum[i] - sum[j] < Math.log(k) - 1e-9) {
ans++;
}
}
}
return ans;
}
// 滑动窗口
public int numSubarrayProductLessThanK2(int[] nums, int k) {
if (k <= 1) return 0;
int prod = 1, ans = 0, left = 0;
for (int right = 0; right < nums.length; right++) {
prod *= nums[right];
while (prod >= k) prod /= nums[left++];
ans += right - left + 1;
}
return ans;
}
public static void main(String[] args) {
NumSubarrayProductLessThanK solution = new NumSubarrayProductLessThanK();
int[] nums = new int[]{10, 3, 3, 7, 2, 9, 7, 4, 7, 2, 8, 6, 5, 1, 5};
System.out.println(solution.numSubarrayProductLessThanK(nums, 30));
}
}