1. 程式人生 > >【探索-中級演算法】遞增的三元子序列

【探索-中級演算法】遞增的三元子序列

在這裡插入圖片描述


最先想到的思路,就是用一個 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_ynums[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 肯定是 firstsecond 中最小的,否則,就會把 first 更新,以保證到 second 之間是最小的。

if(first>num) first = num;

if(first<num && second>num) second = num; 是為了保持 second 在大於 first 的基礎上取 secondthird 之間的最小值。

之後如果找到了比 second 還大的數就符合條件返回 true 了。