[LeetCode 连续的子数组和 && 和为K的子数组] | 刷题打卡

80 阅读1分钟

523. 连续的子数组和

leetcode-cn.com/problems/co…

  • 前缀和
/**
 * @param {number[]} nums
 * @param {number} k
 * @return {boolean}
 */
var checkSubarraySum = function(nums, k) {
    const prefixSum = [0]
    for(let i=0;i<nums.length;i++){
        prefixSum[i+1] = prefixSum[i] + nums[i]
    }

    for(let i=0;i<nums.length;i++){
        for(let j=i+1;j<nums.length;j++){
            const res = prefixSum[j+1] - prefixSum[i] 
            if(res % k ===0  || (res ===0 && k===0)){
                return true
            }
        }
    }
    return false

};
  • 前缀和 + 哈希
    • 设位置 j < i :
    • 0 到 j 的前缀和 preSum1 = 某常数1 * k + 余数1
    • 0 到 i 的前缀和 preSum2 = 某常数2 * k + 余数2
    • 当找到 余数1 等于 余数2时, 则 j + 1 到 i 的连续和 = preSum2 - preSum1 = (某常数2 - 某常数1) * k, 必为 k 的倍数, 返回true
/**
 * @param {number[]} nums
 * @param {number} k
 * @return {boolean}
 */
var checkSubarraySum = function(nums, k) {
    let prefixSum =0
    const map = {0:-1}
    for(let i=0;i<nums.length;i++){
        prefixSum = prefixSum + nums[i]
        if(k !==0){
            prefixSum = prefixSum % k
        }

        if(map[prefixSum]!==undefined){
            if(i - map[prefixSum] > 1){
                return true
            }
        }else{
            map[prefixSum] = i
        }
    }
    return false

};

560. 和为K的子数组

leetcode-cn.com/problems/su…

  • 暴力解法 超时
const subarraySum = (nums, k) => {
  let count = 0;
  for (let i = 0; i < nums.length; i++) {
    let sum = 0;
    for (let j = i; j < nums.length; j++) {
      sum += nums[j];
      if (sum == k) count++;
    }
  }
  return count;
};

  • 前缀和 超时
/**
 * @param {number[]} nums
 * @param {number} k
 * @return {number}
 */
var subarraySum = function (nums, k) {
    const prefixSum = [0]
    let counter = 0
    for (let i = 0; i < nums.length; i++) {
        prefixSum[i+1] = prefixSum[i] + nums[i]
    }
    for(let i=0;i<nums.length;i++){
        for(let j=i;j<nums.length;j++){
            if(prefixSum[j+1] - prefixSum[i] ===k){
                counter ++
            }
        }
    }
    return counter
};
  • 前缀和 + 哈希
    • 每个元素对应一个“前缀和”
    • 遍历数组,根据当前“前缀和”,在 map 中寻找「与之相减 == k」的历史前缀和
    • 当前“前缀和”与历史前缀和差分出一个子数组,该历史前缀和出现过 n 次,等价于当前项找到 n 个子数组求和等于 k。
    • 遍历数组过程中,n 不断加给 count,最后返回 count
/**
 * @param {number[]} nums
 * @param {number} k
 * @return {number}
 */
var subarraySum = function (nums, k) {
    let prefixSum = 0
    const map = new Map()
    map.set(0,1)
    let counter = 0
    for (let i = 0; i < nums.length; i++) {
        prefixSum = prefixSum + nums[i]
        if(map.get(prefixSum - k)){
            counter = counter + map.get(prefixSum - k)
        }
        const val = map.get(prefixSum)
        if(val){
            map.set(prefixSum,val+1)
        }else{
            map.set(prefixSum,1)
        }
    }
    return counter
};