LeetCode周赛

LeetCode第187场周赛


本次周赛跟前几次周赛对比一下还是有一点进步的,AC了两道题,第三题第一次做TLE了,然后之后想到用滑动窗口,但奈何程序不会写。最后一道题连题目都看不懂(自己真的太菜了)。
在这里总结一下经验以及分享自己AC前两道题的思路。

一、5400. 旅行终点站
链接:https://leetcode-cn.com/problems/destination-city/.

给你一份旅游线路图,该线路图中的旅行线路用数组 paths 表示,其中 paths[i] = [cityAi, cityBi] 表示该线路将会从 cityAi 直接前往 cityBi 。请你找出这次旅行的终点站,即没有任何可以通往其他城市的线路的城市。
题目数据保证线路图会形成一条不存在循环的线路,因此只会有一个旅行终点站。

刚看到这道题说实话是有一点懵的,不过仔细一想这道题还是比较简单的。我们只需要找出出现在终点而并未出现在起点的位置即可。

public String destCity(List> paths) {
        List list = new ArrayList();
		 for(int i = 0; i < paths.size(); i++){
			 list.add(paths.get(i).get(1));
		 }
		 for(int i = 0; i < paths.size(); i++){
			 String s = paths.get(i).get(0);
			 if(list.contains(s)) list.remove(s);
		 }
		 return list.get(0);
    }

二、5401. 是否所有 1 都至少相隔 k 个元素
链接:https://leetcode-cn.com/problems/check-if-all-1s-are-at-least-length-k-places-away/.
给你一个由若干 0 和 1 组成的数组 nums 以及整数 k。如果所有 1 都至少相隔 k 个元素,则返回 True ;否则,返回 False 。

这道题采用了比较暴力的算法,直接找1的位置,将他们进行相减即可。

//静态数组
public boolean kLengthApart(int[] nums, int k) {
        int n = nums.length;
        int[] res = new int[n];
        int index = 0;
        for(int i = 0; i < n; i++){
            if(nums[i] == 1) res[index ++] = i;
        }
        
        for(int i = 0; i < index - 1; i++){
        //此处需要再-1是因为求得是两个数之间的距离
            if(res[i + 1] - res[i] - 1 < k) return false;
        }
        return true;
    }

当然这道题也可以使用双指针的思路:

//双指针
public boolean kLengthApart(int[] nums, int k) {
		//pre = -10000是参照leetcode上的题解
        for(int pre = -10000, next = 0; next < nums.length; next ++){
            if(nums[next] == 1){
                if(next - pre <= k) return false;
                else pre = next;
            }
        }
        return true;
    }

三、5402. 绝对差不超过限制的最长连续子数组
链接:https://leetcode-cn.com/problems/longest-continuous-subarray-with-absolute-diff-less-than-or-equal-to-limit/.

这道题我的思路是采用暴力的方式,直接求解(当然这个是会超时的),以下附上我所写的暴力的算法。

//暴力解法
public int longestSubarray(int[] nums, int limit) {
        if(nums.length == 1){
            return 1;
        }
        int maxLength = 0;
        for(int i = 0; i < nums.length - 1; i++){
            int max = nums[i], min = nums[i];
            int j = i + 1;
            while(j < nums.length){
                max = Math.max(max, nums[j]);
                min = Math.min(min, nums[j]);
                if(Math.abs(max - min) <= limit){
                    maxLength = Math.max(maxLength, j - i + 1);
                }
                j ++;
            }    
        }
        return maxLength;
    }

之后对暴力解法进行优化:
这道题自己看了大佬写的代码,看不懂,所以看了花花酱的视频,花花酱一共讲了滑动窗口的思路,用到了两种写程序的方式(下文会一一列举出来)。
思路详解:我们首先需要一个窗口,然后将数组中的元素添加进去,如果添加的元素满足limit的条件,那我们继续往下进行,如果不满足,我们需要删除左边的第一个元素(至于为什么删除左边第一个元素,可以详细看一看labuladong公众号上关于滑动窗口详解)。

第一种程序方式:使用的是c++中的multiset算法

public:
    int longestSubarray(vector& nums, int limit) {
        multiset s;
        int l = 0, res = 0;
        for(int r = 0; r < nums.size(); r++){
            s.insert(nums[r]);
            //判断最大值-最小值是否满足条件
            while(*rbegin(s) - *begin(s) > limit){
            //不满足,则去除掉左边元素
                s.erase (s.equal_range (nums[l++]).first);
            }
            res = fmax(res,r - l + 1);
        }
        return res;
    }

第二种方式采取了双队列的方式,一个队列用来存储最大值,另一个队列用来存储最小值。

public int longestSubarray(int[] nums, int limit) {
        int n = nums.length;
        int l = 0, ans = 0;
        Deque max = new ArrayDeque<>();
        Deque min = new ArrayDeque<>();
        for(int r = 0; r < n; r++){
            while(!max.isEmpty() && nums[r] > max.peekLast()){
                max.pollLast();
            }
            max.addLast(nums[r]);
            while(!min.isEmpty() && nums[r] < min.peekLast()){
                min.pollLast();
            }
            min.addLast(nums[r]);
            while(max.peekFirst() - min.peekFirst() > limit){
                if(max.peekFirst() == nums[l]) max.pollFirst();
                if(min.peekFirst() == nums[l]) min.pollFirst();
                l++;
            }
            ans = Math.max(ans, r - l + 1);
        }
        return ans;
    }

如果有不明白的地方,可以在b站看一看花花酱的视频。
视频链接:https://www.bilibili.com/video/BV1Cf4y1m7aN?from=search&seid=573184578394241963.

四、1439. 有序矩阵中的第 k 个最小数组和
等我学会了再补充…

你可能感兴趣的:(leetcode)