【探索-中級演算法】遞增的三元子序列
最先想到的思路,就是用一個 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.csdn.net/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
了。