# LeetCode 日記 #008: 334. Increasing Triplet Subsequence | 貪心算法 Greedy > Given an integer array nums, return true if there exists a triple of indices (i, j, k) such that i < j < k and nums[i] < nums[j] < nums[k]. If no such indices exists, return false. - **Example 1:** Input: nums = [1,2,3,4,5] Output: true Explanation: Any triplet where i < j < k is valid. - **Example 2:** Input: nums = [5,4,3,2,1] Output: false Explanation: No triplet exists. - **Example 3:** Input: nums = [2,1,5,0,4,6] Output: true Explanation: nums[3] == 0 < nums[4] == 4 < nums[5] == 6. ### 題目概述 判斷題目給定的原始陣列中,是否存在連續三個元素是呈現遞增的子陣列,有的話返回 true,沒有則返回 false。要解決這題就必須學習一個新的算法思想與策略——**貪心算法 (Greedy)**。 ## 貪心算法 (Greedy) 貪心算法的核心思想是,在每一步選擇中都採取當前狀態下最優的選擇(局部最優),期待最終能得到「全局最優」。 ### 特性 * **局部最優選擇**:每一步的選擇都是當前看起來最好的,不考慮全局 * **無後效性**:當前的決策不會影響未來的決策 * **子問題最優性質**:問題的最優解包含子問題的最優解 * **簡單高效**:通常實現簡單且時間複雜度較低 * **不需要回溯**:一旦做出選擇,就不會回頭重新考慮 ### 使用時機 * **問題可以分解為子問題**:整體問題可以分解為一系列子問題 * **滿足最優子結構**:問題的最優解包含子問題的最優解 * **具有貪心選擇性質**:每一步的局部最優選擇能導致全局最優解 * **子問題之間相互獨立**:一個子問題的解不會影響其他子問題 判斷問題是否適合使用貪心算法,可以考慮以下幾點: * **「問題是否有明顯的局部最優選擇」**:例如「選擇當前最小/最大值」 * **「局部最優是否能推導出全局最優」**:需要證明局部選擇不會導致次優解 * **「問題是否具有無後效性」**:當前決策不會影響未來的決策空間 * **「問題是否具有貪心選擇性質」**:每一步的最優選擇能導致全局最優解 ## 題解 第一眼看到這題時,可從以下幾個角度來分析是否適用貪心算法: 1. **問題結構**: 首先,觀察到這個問題的核心是尋找三個遞增的元素,而不是求所有可能的遞增子序列。這種「是否存在」的問題通常比「找出所有」的問題更適合使用貪心或者更簡單的算法。 2. **子問題與獨立性分析**: 當分析如何判斷陣列中是否存在遞增的三元組時,關鍵問題變成: - 如何有效地記錄已經看到的最小值 - 如何記錄基於這個最小值的第二小值 - 如何判斷是否存在第三個值大於前兩個值 > 這種子問題結構表明可能不需要記住所有歷史信息,只需要記住關鍵狀態。 3. **最優子結構特性識別**: 如果已經找到當前最小值 first 和第二小值 second,那麼只要找到任何一個大於 second 的值,就能確定存在遞增三元組,這符合貪心算法的最優子結構特性 - 維護當前最優的 first 和 second 有助於找到全局解。 4. **局部最優選擇分析**: 考慮在迭代時的每一步決策,如果遇到一個更小的值,更新 first 是局部最優的(讓後續找到合適的 second 和第三個值的可能性更大)如果遇到一個介於 first 和 second 之間的值,更新 second 是局部最優的,如果遇到一個大於 second 的值,我們直接找到了答案。這種每一步的局部最優選擇,能夠指向全局最優解,是貪心算法的核心特徵。 5. **無後效性判斷**: 當我更新 first 或 second 時,我不需要考慮它們之前的值或相對位置,只關心數值大小關係。這種特性表明問題具有無後效性,適合使用貪心算法。 ```java class Solution { public boolean increasingTriplet(int[] nums) { int first = Integer.MAX_VALUE; int second = Integer.MAX_VALUE; for (int i = 0; i < nums.length; i++) { if (nums[i] > second) { return true; } else if (nums[i] > first && nums[i] < second) { second = nums[i]; } else if (nums[i] < first) { first = nums[i]; } } return false; } } ``` ### 總結 綜合以上分析,當看到這類「尋找特定模式」且只需要「是/否」答案的問題時,可優先考慮是否適用貪心算法。特別是當問題可以通過維護少量關鍵變量(如 first 和 second)來表達狀態,並且每一步都有明確的局部最優選擇時。如果使用貪心策略,整個算法只需要 O(n) 的時間複雜度和 O(1) 的空間複雜度,非常高效。貪心算法通常比動態規劃或回溯算法更簡潔高效。