1. 程式人生 > >【LeetCode】334#遞增的三元子序列

【LeetCode】334#遞增的三元子序列

復雜 時間復雜度 一個 暴力破解 pub 對數 體會 表示 分享圖片

題目描述

給定一個未排序的數組,判斷這個數組中是否存在長度為 3 的遞增子序列。

數學表達式如下:

如果存在這樣的 i, j, k, 且滿足 0 ≤ i < j < kn-1,
使得 arr[i] < arr[j] < arr[k] ,返回 true ; 否則返回 false 。

說明: 要求算法的時間復雜度為 O(n),空間復雜度為 O(1) 。

示例 1:

輸入: [1,2,3,4,5]
輸出: true

示例 2:

輸入: [5,4,3,2,1]
輸出: false

解題思路

1、暴力破解

使用三層循環,先找到二元上升序列,再在二元上升序列的基礎上,找三元上升序列,時間復雜度為O(N^3)

源代碼

public boolean increasingTriplet (int[] nums) {
    if (nums.length < 3) return false;
    for (int i = 0; i < nums.length-2; i++) {
        for (int j = i+1; j < nums.length - 1; j++) {
            if (nums[j] > nums[i]) {
                for (int k = j+1; k < nums.length; k++) {
                    if (nums[k] > nums[j]) {
                        return true;
                    }
                }
            }
        }
    }
    return false;
}

2、一次遍歷法

維護兩個常量:minsecond_min,對數組進行遍歷。

其中,min表示遍歷到當前位置最小的元素,second_min表示從min的位置開始一直到當前位置的第二小元素(也就是比min大的元素中最小的那一個)。

確定這兩個元素後,再在後續的元素中找有沒有比second_min大的元素,如果有,就表示存在遞增的三元子序列。

這樣只需要遍歷一次數組,時間復雜度為O(N)

示意圖

技術分享圖片

源代碼

public boolean increasingTriplet (int[] nums) {
    int min = Integer.MAX_VALUE;
    int second_min = Integer.MAX_VALUE;
    for (int num : nums) {
        if (num<=min) min = num;
        else if (num < second_min) second_min = num;
        else if (num > second_min) return true;
    }
    return false;
}

心得體會

一次遍歷法的巧妙就在於設置了兩個變量(或者叫指針)來保存遞增二元子序列,並實時更新,避免了許多重復的判斷。

【LeetCode】334#遞增的三元子序列