【探索-中级算法】递增的三元子序列

版权声明:转载请标明出处「OneDeveloper」 https://blog.csdn.net/OneDeveloper/article/details/83587308

在这里插入图片描述


最先想到的思路,就是用一个 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 了。

猜你喜欢

转载自blog.csdn.net/OneDeveloper/article/details/83587308