leetcode 523. 连续的子数组和

leetcode 每日一题 523. 连续的子数组和

我的思路

  1. 遍历数组,遍历以第 i 个元素为起点的所有子数组,用 temp 记录当前的总和,并计算是否为 k 的倍数,如果是则返回 true;否则,遍历结束后返回 false。
    时间复杂度 O ( n 2 ) O(n^2) O(n2),空间复杂度 O ( 1 ) O(1) O(1)只是 temp 占用了空间。
    93 / 94 个通过测试用例。 最后一个果然超时了。
var checkSubarraySum = function (nums, k) {
  for (let i = 1; i < nums.length; i++) {
    temp = nums[i] + nums[i - 1];
    if (temp % k == 0) {
      return true;
    } else {
      for (let j = i + 1; j < nums.length; j++) {
        temp += nums[j];
        if (temp % k == 0) {
          return true;
        }
      }
    }
  }
  return false;
};
  1. 前缀和,想了想前缀和还是要遍历啊,这可怎么办,还是超时。
var checkSubarraySum = function (nums, k) {
  var prefix = [];
  prefix[0] = nums[0];
  for (let i = 1; i < nums.length; i++) {
    prefix[i] = prefix[i - 1] + nums[i];
    if (prefix[i] % k == 0) {
      return true;
    }
  }
  for (let i = nums.length - 1; i >= 0; i--) {
    for (let j = 0; j <= i - 2; j++) {
      if ((prefix[i] - prefix[j]) % k == 0) {
        return true;
      }
    }
  }
  return false;
};

看看题解

官方题解也确实用到了前缀和的方法。

官方题解的思路是:如果两个前缀和除以 k 的余数相等,那么这两个前缀和的差一定是 k 的倍数。此时只要两个前缀和并不相邻,即满足子数组大小至少为 2,且子数组元素总和为 k 的倍数。

/**
 * @param {number[]} nums
 * @param {number} k
 * @return {boolean}
 */
var checkSubarraySum = function (nums, k) {
  const map = new Map();
  map.set(0, -1);
  var temp = 0;
  for (let i = 0; i < nums.length; i++) {
    temp = (temp + nums[i]) % k;
    if (map.has(temp)) {
      var pre = map.get(temp);
      if (i - pre >= 2) {
        return true;
      }
    } else {
      map.set(temp, i);
    }
  }
  return false;
};

总结

  1. 有一种能做出来是你觉得你能做出来。其实仔细思考下来需要避开的坑非常多。就比如本题中的前缀和,知道要用前缀和来节约时间,但是没有细想怎么实现,那其实简单实现了之后才发现并没有达到节约时间的目的。

  2. 学到了 JS 的 hash 表 Map() 的基本使用方法

    创建 map 对象

    var map = new Map([
      ["key1", value1],
      ["key2", value2],
    ]);
    

    将键值对放入 map 对象

    map.set("key3", value3);
    

    根据 key 获取 map 值

    map.get("key1");
    

    查看 map 中是否有给定的 key

    map.has("key"); //false
    

    删除 map 指定对象

    map.delete("key1");
    

    循环遍历 map

    map.forEach(function (key) {
      console.log("key", key);
    });
    
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值