精品推荐:
《征服数据结构》专栏:50多种数据结构彻底征服
《经典图论算法》专栏:50多种经典图论算法全部掌握
一实习的网友因为在公司群里抢了一个红包,被领导问:你一个实习的抢什么?我还以为是多大红包呢,总共就发200块钱,这格局……,怪不得网友评论说:今天我抢你红包,明天我抢你风头,后天我抢你老婆,大后天我还抢你位置。。。
在给大家来一道智力测试题:
A blind man is alone on a deserted island. He has two blue pills and two red pills. He must take exactly one red pill and one blue pill or he will die.
How does he do it?
翻译过来就是:
一个盲人独自一人待在一个荒岛上。他有两粒蓝色药丸和两粒红色药丸。他必须服用一粒红色药丸和一粒蓝色药丸,否则他就会死。
他应该怎么做?一小时之后评论区见答案。
--------------下面是今天的算法题--------------
来看下今天的算法题,这题是LeetCode的第220题:存在重复元素 III。
问题描述
来源:LeetCode第220题
难度:困难
给你一个整数数组 nums 和两个整数 indexDiff 和 valueDiff 。找出满足下述条件的下标对 (i, j):
1,i != j
2,abs(i - j) <= indexDiff
3,abs(nums[i] - nums[j]) <= valueDiff
如果存在,返回 true ;否则,返回 false 。
示例1:
输入:nums = [1,2,3,1], indexDiff = 3, valueDiff = 0
输出:true
解释:可以找出 (i, j) = (0, 3) 。
满足下述 3 个条件:
i != j --> 0 != 3
abs(i - j) <= indexDiff --> abs(0 - 3) <= 3
abs(nums[i] - nums[j]) <= valueDiff --> abs(1 - 1) <= 0
示例2:
输入:nums = [1,5,9,1,5,9], indexDiff = 2, valueDiff = 3
输出:false
解释:尝试所有可能的下标对 (i, j) ,均无法满足这 3 个条件,因此返回 false 。
2 <= nums.length <= 10^5
-10^9 <= nums[i] <= 10^9
1 <= indexDiff <= nums.length
0 <= valueDiff <= 10^9
问题分析
这题是存在重复元素的第 3 题,前面两道题都比较简单,具体可以看下:
这题要求的是在数组中找出两个元素,它们的下标差与值的差都小于给定的值。这题也是一道滑动窗口问题,窗口的大小是indexDiff+1,这样我们就可以保证在窗口中的任何两个元素的下标差都不会大于indexDiff。
然后我们在窗口中找出与当前元素差值最小的元素,判断它俩的差值是否小于等于valueDiff。
为了方便查找,我们使用TreeSet作为窗口,每次查找和当前元素最接近的,一个比它大的一个比它小的值。
JAVA:
public boolean containsNearbyAlmostDuplicate(int[] nums, int indexDiff, int valueDiff) {
TreeSet<Integer> set = new TreeSet<>();
for (int i = 0; i < nums.length; i++) {
int num = nums[i];
// 查找集合中小于或者等于num的最大值
Integer floor = set.floor(num);
// 查找集合中大于或者等于num的最小值
Integer ceiling = set.ceiling(num);
// 如果查找到任何一个,他们的值相差小于等于valueDiff,直接返回true
if ((floor != null && num - floor <= valueDiff) ||
(ceiling != null && ceiling - num <= valueDiff)) {
return true;
}
// 否则把当前元素加入到集合set中
set.add(num);
if (i >= indexDiff) {
// 把最前面的给移除,因为最前面的元素和当前元素的下标
// 大于indexDiff了,即使他们的差小于等于valueDiff,
// 也不会满足条件
set.remove(nums[i - indexDiff]);
}
}
return false;
}
笔者简介
博哥,真名:王一博,毕业十多年,《算法秘籍》作者,专注于数据结构和算法的讲解,在全球30多个算法网站中累计做题2000多道,在公众号中写算法题解800多题,对算法题有自己独特的解题思路和解题技巧,喜欢的可以给个关注,也可以下载我整理的1000多页的PDF算法文档。
数组,稀疏表(Sparse Table),单向链表,双向链表,块状链表,跳表,队列和循环队列,双端队列,单调队列,栈,单调栈,双端栈,散列表,堆,字典树(Trie树),ArrayMap,SparseArray,二叉树,二叉搜索树(BST),笛卡尔树,AVL树,树堆(Treap),FHQ-Treap
……
图的介绍,图的表示方式,邻接矩阵转换,广度优先搜索(BFS),深度优先搜索(DFS),A*搜索算法,迭代深化深度优先搜索(IDDFS),IDA*算法,双向广度优先搜索,迪杰斯特拉算法(Dijkstra),贝尔曼-福特算法(Bellman-Ford),SPFA算法,弗洛伊德算法(Floyd)
……