算法-和为K的子数组

算法-和为K的子数组

  • 1、和为K的子数组

1、和为K的子数组

560. 和为K的子数组

给定一个整数数组和一个整数 k,你需要找到该数组中和为 k 的连续的子数组的个数。

示例 1 :

输入:nums = [1,1,1], k = 2
输出: 2 , [1,1] 与 [1,1] 为两种不同的情况。
说明 :

数组的长度为 [1, 20,000]。
数组中元素的范围是 [-1000, 1000] ,且整数 k 的范围是 [-1e7, 1e7]。

这个题是字节面试题,也是Leetcode上一道medium级别的题,题目的意图也比较明显,就是找和为K的连续序列个数。但本题中,数字有可能是乱序的,不能再像剑指offer上那样用数学法做了。

当然,本题存在暴力解法,时间复杂度为O(N)。主要思想是声明两个指针,一个指向连续序列起始位置,另一个指向连续序列的结尾处,我们利用两层遍历,就可以解决这个问题了。方法比较简单,但时间复杂度为O(N^2),虽然也能通过测试用例,但要几百毫秒,换成python这样的语言一定会超时。

    public int subarraySum(int[] nums, int k) {
        int slow=0,quick=0;
        int tempK=k;
        int count=0;
        while(slow<nums.length){
            if(quick==nums.length){
                tempK=k;
                quick=++slow;
            }else if(tempK-nums[quick]==0){
                count++;
                tempK-=nums[quick++];   
            }else{
                tempK-=nums[quick++];   
            }
        }
        return count;
    }

我们可以用哈希表实现另一种解法,还记得leetcode的第一题吗?two sum问题,存在着一种使用HashMap实现的O(N)解法,本题目思想和它是一致的。

我们用hashmap来保存同一个sum出现的次数,一旦当前sum等于目标和,那么当前符合条件的数列数量+1,如果包含sum-k,那么和为sum-k的m个子序列与当前元素都可以组成连续序列,所以,当前连续子序列个数要加上m。最后,我们要记录每个和sum的出现次数。

    public int subarraySum(int[] nums, int k) {
        int sum=0,count=0;
        Map<Integer,Integer> map=new HashMap<>();
        for (int i=0;i<nums.length;i++){
            sum+=nums[i];
            if(sum==k){
                count++;
            }
            if(map.containsKey(sum-k)){
                count+=map.get(sum-k);
            }
            if(!map.containsKey(sum)){
                map.put(sum,1);
            }else {
                map.put(sum,map.get(sum)+1);
            }
        }
        return count;
    }

代码写的比较清晰,不过多解读了。

你可能感兴趣的:(数据结构与算法分析,算法,指针,leetcode,java,数据结构)