From 3882ca7fcb7bf4934156672e4ae65472d6319d70 Mon Sep 17 00:00:00 2001 From: AC_Oier Date: Wed, 12 Jan 2022 10:53:43 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8feat:=20Add=20334?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "Index/\344\272\214\345\210\206.md" | 1 + "Index/\345\272\217\345\210\227 DP.md" | 1 + ...52\345\277\203\347\256\227\346\263\225.md" | 1 + ...10\344\270\255\347\255\211\357\274\211.md" | 199 ++++++++++++++++++ 4 files changed, 202 insertions(+) create mode 100644 "LeetCode/331-340/334. \351\200\222\345\242\236\347\232\204\344\270\211\345\205\203\345\255\220\345\272\217\345\210\227\357\274\210\344\270\255\347\255\211\357\274\211.md" diff --git "a/Index/\344\272\214\345\210\206.md" "b/Index/\344\272\214\345\210\206.md" index 215a097f..9e15d7c2 100644 --- "a/Index/\344\272\214\345\210\206.md" +++ "b/Index/\344\272\214\345\210\206.md" @@ -15,6 +15,7 @@ | [274. H 指数](https://leetcode-cn.com/problems/h-index/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/h-index/solution/gong-shui-san-xie-li-yong-er-duan-xing-z-1jxw/) | 中等 | 🤩🤩🤩 | | [275. H 指数 II](https://leetcode-cn.com/problems/h-index-ii/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/h-index-ii/solution/gong-shui-san-xie-liang-chong-er-fen-ji-sovjb/) | 中等 | 🤩🤩🤩 | | [278. 第一个错误的版本](https://leetcode-cn.com/problems/first-bad-version/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/first-bad-version/solution/gong-shui-san-xie-shi-yong-jiao-hu-han-s-8hpv/) | 简单 | 🤩🤩🤩🤩 | +| [334. 递增的三元子序列](https://leetcode-cn.com/problems/increasing-triplet-subsequence/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/increasing-triplet-subsequence/solution/gong-shui-san-xie-zui-chang-shang-sheng-xa08h/) | 中等 | 🤩🤩🤩🤩 | | [352. 将数据流变为多个不相交区间](https://leetcode-cn.com/problems/data-stream-as-disjoint-intervals/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/data-stream-as-disjoint-intervals/solution/gong-shui-san-xie-yi-ti-shuang-jie-er-fe-afrk/) | 困难 | 🤩🤩🤩🤩 | | [354. 俄罗斯套娃信封问题](https://leetcode-cn.com/problems/russian-doll-envelopes/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/russian-doll-envelopes/solution/zui-chang-shang-sheng-zi-xu-lie-bian-xin-6s8d/) | 困难 | 🤩🤩🤩 | | [363. 矩形区域不超过 K 的最大数值和](https://leetcode-cn.com/problems/max-sum-of-rectangle-no-larger-than-k/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/max-sum-of-rectangle-no-larger-than-k/solution/gong-shui-san-xie-you-hua-mei-ju-de-ji-b-dh8s/) | 困难 | 🤩🤩🤩 | diff --git "a/Index/\345\272\217\345\210\227 DP.md" "b/Index/\345\272\217\345\210\227 DP.md" index f27f840f..1136a33c 100644 --- "a/Index/\345\272\217\345\210\227 DP.md" +++ "b/Index/\345\272\217\345\210\227 DP.md" @@ -1,5 +1,6 @@ | 题目 | 题解 | 难度 | 推荐指数 | | ------------------------------------------------------------ | ------------------------------------------------------------ | ---- | -------- | +| [334. 递增的三元子序列](https://leetcode-cn.com/problems/increasing-triplet-subsequence/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/increasing-triplet-subsequence/solution/gong-shui-san-xie-zui-chang-shang-sheng-xa08h/) | 中等 | 🤩🤩🤩🤩 | | [354. 俄罗斯套娃信封问题](https://leetcode-cn.com/problems/russian-doll-envelopes/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/russian-doll-envelopes/solution/zui-chang-shang-sheng-zi-xu-lie-bian-xin-6s8d/) | 困难 | 🤩🤩🤩🤩🤩 | | [368. 最大整除子集](https://leetcode-cn.com/problems/largest-divisible-subset/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/largest-divisible-subset/solution/gong-shui-san-xie-noxiang-xin-ke-xue-xi-0a3jc/) | 中等 | 🤩🤩🤩🤩 | | [390. 消除游戏](https://leetcode-cn.com/problems/elimination-game/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/elimination-game/solution/gong-shui-san-xie-yue-se-fu-huan-yun-yon-x60m/) | 中等 | 🤩🤩🤩🤩 | diff --git "a/Index/\350\264\252\345\277\203\347\256\227\346\263\225.md" "b/Index/\350\264\252\345\277\203\347\256\227\346\263\225.md" index 68d7310c..78cee9ca 100644 --- "a/Index/\350\264\252\345\277\203\347\256\227\346\263\225.md" +++ "b/Index/\350\264\252\345\277\203\347\256\227\346\263\225.md" @@ -3,6 +3,7 @@ | [11. 盛最多水的容器 ](https://leetcode-cn.com/problems/container-with-most-water/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/container-with-most-water/solution/shua-chuan-lc-shuang-zhi-zhen-tan-xin-ji-52gf/) | 中等 | 🤩🤩🤩🤩🤩 | | [45. 跳跃游戏 II](https://leetcode-cn.com/problems/jump-game-ii/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/jump-game-ii/solution/xiang-jie-dp-tan-xin-shuang-zhi-zhen-jie-roh4/) | 中等 | 🤩🤩🤩🤩 | | [179. 最大数](https://leetcode-cn.com/problems/largest-number/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/largest-number/solution/gong-shui-san-xie-noxiang-xin-ke-xue-xi-vn86e/) | 中等 | 🤩🤩🤩🤩 | +| [334. 递增的三元子序列](https://leetcode-cn.com/problems/increasing-triplet-subsequence/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/increasing-triplet-subsequence/solution/gong-shui-san-xie-zui-chang-shang-sheng-xa08h/) | 中等 | 🤩🤩🤩🤩 | | [397. 整数替换](https://leetcode-cn.com/problems/integer-replacement/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/integer-replacement/solution/gong-shui-san-xie-yi-ti-san-jie-dfsbfs-t-373h/) | 中等 | 🤩🤩🤩🤩 | | [421. 数组中两个数的最大异或值](https://leetcode-cn.com/problems/maximum-xor-of-two-numbers-in-an-array/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/maximum-xor-of-two-numbers-in-an-array/solution/gong-shui-san-xie-noxiang-xin-ke-xue-xi-bmjdg/) | 中等 | 🤩🤩🤩🤩 | | [502. IPO](https://leetcode-cn.com/problems/ipo/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/ipo/solution/gong-shui-san-xie-noxiang-xin-ke-xue-xi-fk1ra/) | 困难 | 🤩🤩🤩 | diff --git "a/LeetCode/331-340/334. \351\200\222\345\242\236\347\232\204\344\270\211\345\205\203\345\255\220\345\272\217\345\210\227\357\274\210\344\270\255\347\255\211\357\274\211.md" "b/LeetCode/331-340/334. \351\200\222\345\242\236\347\232\204\344\270\211\345\205\203\345\255\220\345\272\217\345\210\227\357\274\210\344\270\255\347\255\211\357\274\211.md" new file mode 100644 index 00000000..5126d6f1 --- /dev/null +++ "b/LeetCode/331-340/334. \351\200\222\345\242\236\347\232\204\344\270\211\345\205\203\345\255\220\345\272\217\345\210\227\357\274\210\344\270\255\347\255\211\357\274\211.md" @@ -0,0 +1,199 @@ +### 题目描述 + +这是 LeetCode 上的 **[334. 递增的三元子序列](https://leetcode-cn.com/problems/increasing-triplet-subsequence/solution/gong-shui-san-xie-zui-chang-shang-sheng-xa08h/)** ,难度为 **中等**。 + +Tag : 「LIS」、「最长上升子序列」、「贪心」、「二分」 + + + +给你一个整数数组 `nums`,判断这个数组中是否存在长度为 $3$ 的递增子序列。 + +如果存在这样的三元组下标 `(i, j, k)` 且满足 `i < j < k` ,使得 `nums[i] < nums[j] < nums[k]` ,返回 `true` ;否则,返回 `false`。 + +示例 1: +``` +输入:nums = [1,2,3,4,5] + +输出:true + +解释:任何 i < j < k 的三元组都满足题意 +``` +示例 2: +``` +输入:nums = [5,4,3,2,1] + +输出:false + +解释:不存在满足题意的三元组 +``` +示例 3: +``` +输入:nums = [2,1,5,0,4,6] + +输出:true + +解释:三元组 (3, 4, 5) 满足题意,因为 nums[3] == 0 < nums[4] == 4 < nums[5] == 6 +``` + +提示: +* $1 <= nums.length <= 5 * 10^5$ +* $-2^{31} <= nums[i] <= 2^{31} - 1$ + +进阶:你能实现时间复杂度为 $O(n$) ,空间复杂度为 $O(1)$ 的解决方案吗? + +--- + +### 最长上升子序列(贪心 + 二分) + +题目要我们判断是否存在长度为 $3$ 的上升子序列,问题可以转换为求 $nums$ 的最长上升子序列(`LIS` 问题)的长度。 + +如果 $nums$ 的最长上升子序列长度大于等于 $3$,那么原问题答案为 `True`,否则为 `False`。 + +而求最长上升子序列的最优解是有基于「贪心 + 二分」的 $O(n\log{n})$ 做法,对此不了解的同学,可以先看前置 🧀 :[LCS 问题与 LIS 问题的相互关系,以及 LIS 问题的最优解证明](https://mp.weixin.qq.com/s?__biz=MzU4NDE3MTEyMA==&mid=2247487814&idx=1&sn=e33023c2d474ff75af83eda1c4d01892&chksm=fd9cba59caeb334f1fbfa1aefd3d9b2ab6abfccfcab8cb1dbff93191ae9b787e1b4681bbbde3&token=252055586&lang=zh_CN#rd),里面详细讲解了 `LIS` 的贪心解证明,以及与最长公共子序列(`LCS` 问题)的相互关系,本次不再赘述。 + +**简单来说,就是在遍历每个数 $nums[i]$ 的同时,维护一个具有单调性的 $f[]$ 数组,其中 $f[len] = x$ 代表长度为 $len$ 的最长上升子序列最小结尾元素为 $x$,可以证明 $f$ 数组具有单调性(看 [前置🧀](https://mp.weixin.qq.com/s?__biz=MzU4NDE3MTEyMA==&mid=2247487814&idx=1&sn=e33023c2d474ff75af83eda1c4d01892&chksm=fd9cba59caeb334f1fbfa1aefd3d9b2ab6abfccfcab8cb1dbff93191ae9b787e1b4681bbbde3&token=252055586&lang=zh_CN#rd)),因此每次可以通过二分找到小于 $nums[i]$ 的最大下标,来作为 $nums[i]$ 的前一个数。** + +综上,我们使用 `LIS` 的「贪心 + 二分」做法求得最长上升子序列的最大长度,然后和 $3$ 比较即可得出答案。 + +**代码(感谢 [@🍭可乐可乐吗QAQ](/u/littletime_cc/) 同学提供的其他语言版本):** +```Java +class Solution { + public boolean increasingTriplet(int[] nums) { + int n = nums.length, ans = 1; + int[] f = new int[n + 1]; + Arrays.fill(f, 0x3f3f3f3f); + for (int i = 0; i < n; i++) { + int t = nums[i]; + int l = 1, r = i + 1; + while (l < r) { + int mid = l + r >> 1; + if (f[mid] >= t) r = mid; + else l = mid + 1; + } + f[r] = t; + ans = Math.max(ans, r); + } + return ans >= 3; + } +} +``` +- +```C++ +class Solution { +public: + bool increasingTriplet(vector& nums) { + int n = nums.size(), ans = 1; + vector f(n + 1, INT_MAX); + for(int i = 0; i < n; i++){ + int t = nums[i]; + int L = 1, R = i + 1; + while(L < R){ + int mid = L + R >> 1; + if(f[mid] >= t) R = mid; + else L = mid + 1; + } + f[R] = t; + ans = max(ans, R); + } + return ans >= 3; + } +}; +``` +* 时间复杂度:$O(n\log{n})$ +* 空间复杂度:$O(n)$ + +--- + +### 优化 : 定长上升子序列(贪心) + +利用本题只需要我们判定是否存在长度为 $3$ 的上升子序列,而不需要回答 `LIS` 最大长度。 + +我们可以对 $f$ 数组进行优化:**使用有限变量进行替换(将 $f$ 数组的长度压缩为 $2$),数组含义不变,$f[1] = x$ 代表长度为 $1$ 的上升子序列最小结尾元素为 $x$,$f[2] = y$ 代表长度为 $2$ 的上升子序列的最小结尾元素为 $y$。** + +**从前往后扫描每个 $nums[i]$,每次将 $nums[i]$ 分别与 $f[1]$ 和 $f[2]$ 进行比较,如果能够满足 $nums[i] > f[2]$,代表 $nums[i]$ 能够接在长度为 $2$ 的上升子序列的后面,直接返回 `True`,否则尝试使用 $nums[i]$ 来更新 $f[1]$ 和 $f[2]。$** + +这样,我们只使用了有限变量,每次处理 $nums[i]$ 只需要和有限变量进行比较,时间复杂度为 $O(n)$,空间复杂度为 $O(1)$。 + +**代码(感谢 [@🍭可乐可乐吗QAQ](/u/littletime_cc/) 和 [@Benhao](/u/himymben/) 同学提供的其他语言版本):** +```Java +class Solution { + public boolean increasingTriplet(int[] nums) { + int n = nums.length; + long[] f = new long[3]; + f[1] = f[2] = (int)1e19; + for (int i = 0; i < n; i++) { + int t = nums[i]; + if (f[2] < t) return true; + else if (f[1] < t && t < f[2]) f[2] = t; + else if (f[1] > t) f[1] = t; + } + return false; + } +} +``` +- +```Python +class Solution: + def increasingTriplet(self, nums: List[int]) -> bool: + n = len(nums) + f = [inf] * 3 + for i in range(n): + t = nums[i] + if f[2] < t: + return True + elif f[1] < t < f[2]: + f[2] = t + elif f[1] > t: + f[1] = t + return False +``` +- +```Go +func increasingTriplet(nums []int) bool { + n := len(nums) + f := []int{math.MaxInt32,math.MaxInt32,math.MaxInt32} + for i := 0; i < n; i++ { + t := nums[i] + if f[2] < t{ + return true + } else if f[1] < t && t < f[2]{ + f[2] = t + } else if f[1] > t { + f[1] = t + } + } + return false +} +``` +- +```C++ +class Solution { +public: + bool increasingTriplet(vector& nums) { + int n = nums.size(); + vector f(3, INT_MAX); + for(int i = 0; i < n; i++){ + int t = nums[i]; + if(f[2] < t) return true; + else if(f[1] < t and t < f[2]) f[2] = t; + else if(f[1] > t) f[1] = t; + } + return false; + } +}; +``` +* 时间复杂度:$O(n)$ +* 空间复杂度:$O(1)$ + +--- + +### 最后 + +这是我们「刷穿 LeetCode」系列文章的第 `No.334` 篇,系列开始于 2021/01/01,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先把所有不带锁的题目刷完。 + +在这个系列文章里面,除了讲解解题思路以外,还会尽可能给出最为简洁的代码。如果涉及通解还会相应的代码模板。 + +为了方便各位同学能够电脑上进行调试和提交代码,我建立了相关的仓库:https://github.com/SharingSource/LogicStack-LeetCode 。 + +在仓库地址里,你可以看到系列文章的题解链接、系列文章的相应代码、LeetCode 原题链接和其他优选题解。 +