一、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 个最小数组和
等我学会了再补充…