Leetcode 560 和为K的子数组 前缀和哈希(箭头,反码补码)

  JAVA 暴力:

    public final int subarraySum(int[] nums, int k) {
        int res = 0;
        for (int i = 0; i < nums.length; i++) {
            int currK = k;
            for (int j = i; j < nums.length; j++) {
                currK -= nums[j];
                if (currK == 0) res++;
            }
        }
        return res;
    }

  JAVA 前缀和哈希,时间复杂度由 O(N2) 优化为 O(N) :

    /**
     * @Author Niuxy
     * @Date 2020/11/19 8:35 下午
     * @Description 以 i 开头的子数组中和为 k 的子数组个数
     * 也就是 pre[i]-k = pre[j] 的个数
     */
    public final int subarraySum(int[] nums, int k) {
        Map<Integer, Integer> preMap = new HashMap<Integer, Integer>();
        preMap.put(0,1);
        int res = 0, pre = 0;
        for (int i = 0; i < nums.length; i++) {
            pre += nums[i];
            res += preMap.getOrDefault(pre-k, 0);
            preMap.put(pre, preMap.getOrDefault(pre, 0) + 1);
        }
        return res;
    }

  JS 前缀和哈希:

/**
 * @param {number[]} nums
 * @param {number} k
 * @return {number}
 */
var subarraySum = function (nums, k) {
    Map.prototype.getOrDefault = (key, defaultV) => {
        if (!this.get(key)) return defaultV;
        return this.get(key);
    }
    let preMap = new Map();
    let res = 0, pre = 0;
    for (let i = 0; i < nums.length; i++) {
        pre += nums[i];
        res += preMap.getOrDefault(pre - k, 0);
        preMap.set(pre, preMap.getOrDefault(pre) + 1);
    }
    return res;
};

  需要注意 JS 中,箭头函数与 function 声明函数中,this 的指向是不同的。箭头函数中 this 指向定义函数时的作用域,而 function 声明函数中 this 指向会根据调用时作用域的不同而改变。所以在编辑原型时切不可使用箭头函数(为了保险,包含 this 的函数都不要使用箭头函数声明)。

  另外在做缓存时,如果使用 long 存储两个 int ,需要注意负数的情况。JAVA 中负数是用补码进行保存的,至于补码为何为反码加一,可以这么理解:

  互为补码的两个数,在模内运算时 加a 等于 减b 。 0+a=0-b --> 补码 b =0-a --> 而在运算 0-a 时,会为 0 进位,因此 b=~a+1 (二进制中相减,进位后除最后一位外均取反);

 

posted @ 2020-11-19 21:25  牛有肉  阅读(115)  评论(0编辑  收藏  举报