
最先想到的思路,就是用一个 Map<Integer, List<Integer>>,其中 key 对应下标 index,value 为当 index_x > index 时,如果 nums[index_x] > nums[index],则将该 index_x 添加到 index 对应到链表中,该链表的作用就是收集在 index 右边的比 nums[index] 大的元素的标。
收集完成后,再一个一个的遍历收集的 list 中的元素 index_,如果 index_ 在 map 中存在,就表示 nums 中还有比 nums[index_] 大的数且该数的下标在 index_ 的右边(即比 index_ 大)。
因此就有 index < index_x < index_y 且 nums[index] < nums[index_x] < nums[index_y]。
public boolean increasingTriplet(int[] nums) {
Map<Integer, List<Integer>> map = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
for (int j = i+1; j < nums.length; j++) {
if (nums[j] > nums[i]) {
if (map.containsKey(i)) {
map.get(i).add(j);
} else {
List<Integer> list = new ArrayList<>();
list.add(j);
map.put(i, list);
}
}
}
}
// 存在 index,就表示有 index2 > index && nums[index2] > nums[index]
for (List<Integer> list : map.values()) {
for (Integer index : list) {
if (map.containsKey(index)) return true;
}
}
return false;
}
上述实现在性能上还是存在不足,后来有看到 LeetCode 上的 3ms 范例:
(同样也可以参考 https://blog.youkuaiyun.com/liangzhaoyang1/article/details/50973304)
public boolean increasingTriplet(int[] nums) {
int first = Integer.MAX_VALUE,second = Integer.MAX_VALUE;
if(nums.length<3){
return false;
}
for(int num:nums){
if(first>num){
first = num;
}else if(first<num && second>num){
second = num;
}else if(num>second){
return true;
}
}
return false;
这样的实现可以说是很好的了,因为传入的是 nums 数组,所以数组中的最大值最大也就为 Integer.MAX_VALUE,这是需要注意的一个前提。
上面的算法,思想也很简单,就是利用了题目中说的规律,然后利用两个指针辅助。
假设 nums 数组中至少有一个符合题意的子序列 first、second、third:
x1 x2 ... first ... xi ... second ... xj ... third ... xk
那么,first 肯定是 first 到 second 中最小的,否则,就会把 first 更新,以保证到 second 之间是最小的。
if(first>num) first = num;
而 if(first<num && second>num) second = num; 是为了保持 second 在大于 first 的基础上取 second 与 third 之间的最小值。
之后如果找到了比 second 还大的数就符合条件返回 true 了。

本文探讨了在数组中寻找递增三元组的有效算法,包括使用哈希映射和双指针技巧的方法。首先介绍了一种基于哈希映射的解决方案,虽然直观但效率较低。随后提出了一种更高效的3ms范例算法,通过维护两个指针来跟踪数组中的最小值和次小值,从而简化搜索过程。
3607

被折叠的 条评论
为什么被折叠?



