Leetcode热门100题 (子串)Day01

 560. 和为K的子数组

给你一个整数数组 nums 和一个整数 k ,请你统计并返回 该数组中和为 k 的连续子数组的个数 

子数组是数组中元素的连续非空序列。

输入:nums = [1,1,1], k = 2
输出:2

思路: 前缀和+哈希表

思路分析:当定义前缀和 pre[ i ] 表示为[0,..,,i], 数组[j..i]的和可以表示为

                                                            k = pre[i] - pre[j-1]

经过移项可得:

                                        ​​​​​​​        ​​​​​​​        ​​​​​​​   pre[j-1] = pre[i]-k

因此,只需要判断pre中有多少值等于pre[i]-k即可得到答案。常见思路可以先得到前缀和数组prep,再通过遍历得到符合条件的值。然而,这里有条件就j<i,因此,我们可以通过类似两数之和的做法,建立哈希表。以 前缀和 为键,前缀和出现的次数 为值。  

通过每次查询哈希表中是否含有  pre[i]-k ,如存在,则在,结果上加上相应的出现次数。

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

239. 滑动窗口最大值

给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。

返回 滑动窗口中的最大值 

输入:nums = [1,3,-1,-3,5,3,6,7], k = 3 输出:[3,3,5,5,6,7]

一般思路:

class Solution {
    public int[] maxSlidingWindow(int[] nums, int k) {
        LinkedList<Integer> quence  = new LinkedList<>();
        List<Integer> ans = new ArrayList<>();

        // 初始队列
        for (int i = 0; i < k; i++) {
            quence.addLast(nums[i]);
        }
        ans.add(Collections.max(quence));
        for (int i = k; i < nums.length ; i++) {
            quence.addLast(nums[i]);
            quence.removeFirst();
            ans.add(Collections.max(quence));
        }


        return ans.stream().mapToInt(Integer::intValue).toArray();
    }
}

使用队列进行出队,入队的遍历。但是超出了时间限制。因此,需要进一步优化。

思路:优先序列

使用优先序列分别保存{nums[i],i},数字和下标。为队列制定降序规则。

每次,向队列中存入一个数,使用下标接着判断这个数是否在滑动窗口内,如果不在滑动窗口内,

则移除最高值。

接着,将最大值导入ans中。

class Solution {
    public int[] maxSlidingWindow(int[] nums, int k) {
        int n = nums.length;
        PriorityQueue<int[]> pq = new PriorityQueue<>((o1, o2) -> -Integer.compare(o1[0],o2[0]));

        for (int i = 0; i < k; i++) {
            pq.offer(new int[] {nums[i],i});
        }
        int[] ans = new int[n-k+1];
        ans[0] = pq.peek()[0];   // 获得优先级最高的元素;

        for (int i = k; i < n; ++i) {
            pq.offer(new int[] {nums[i],i});
            while (pq.peek()[1] <= i - k) {
                pq.poll();
            }
            ans[i - k + 1] = pq.peek()[0];
        }
        return ans;

    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值