惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Hugging Face - Blog
Hugging Face - Blog
GbyAI
GbyAI
Engineering at Meta
Engineering at Meta
有赞技术团队
有赞技术团队
博客园 - 【当耐特】
H
Hackread – Cybersecurity News, Data Breaches, AI and More
WordPress大学
WordPress大学
博客园_首页
美团技术团队
H
Help Net Security
MongoDB | Blog
MongoDB | Blog
宝玉的分享
宝玉的分享
大猫的无限游戏
大猫的无限游戏
小众软件
小众软件
J
Java Code Geeks
A
About on SuperTechFans
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
IT之家
IT之家
T
The Blog of Author Tim Ferriss
Microsoft Azure Blog
Microsoft Azure Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
B
Blog
雷峰网
雷峰网
爱范儿
爱范儿

Long Luo's Life Notes

夏至日测地球:利用太阳影子计算地球半径 2009年江西高考数学压轴题:陶平生老师又藏了什么数学机关? 《茶杯里的风暴》读书笔记:从日常生活中的小事,看懂背后的物理学 2008年江西高考数学压轴题详解:为什么它被称为史上最难高考数学题? 太阳温度是怎么计算出来的? 《大象的时间,老鼠的时间》读书笔记:生命节奏背后的数学规律 小港流到哪里去? 如何用一根棍子测出地球有多大?复刻埃拉托色尼的春分实验 2007江苏高考数学第20题解析:一道通向黄金分割数的数列压轴题 Google经典面试题: 鸡蛋应该怎么扔? 2010年江苏高考数学压轴题解析:巧用余弦定理与数学归纳法 2011年清华大学自主招生数学题解析:一道经典数列题的解法与思路 2011年清华大学自主招生数学题解析:一道经典数列题的解法与思路 2006年江西高考理科数学压轴题解析:递推、放缩与不等式结构 2006年江西高考理科数学压轴题解析:递推、放缩与不等式结构 一道初中数学极值题的多种解法:柯西不等式、几何法、函数法详解 扔几个骰子,怎么算出期望?——拼多多校招笔试算法题的数学故事 拼多多校招笔试算法题:一行公式搞定“多多的魔术盒子” 斯特林公式(Stirling's Formula):我一个阶乘表达式,怎么就和圆扯上关系了呢? 我爱做题:2010年江西高考理科数学压轴题 热机的效率上限在哪里?解析卡诺循环(Carnot Cycle) 为什么 2024 年会有 366 天? 数学之美:几何视角下的高斯积分(Gaussian Integral) 从最小二乘法到正态分布:高斯是如何找到失踪的谷神星的? 正态分布(Normal Distribution)公式为什么长这样? 高速公路编号背后的数学密码 2024阿里巴巴全球数学竞赛预选赛试题及解答 库函数 (libm) 是如何计算三角函数值的? payne hanek 归约算法 音乐背后的数学
LeetCode 334. Increasing Triplet Subsequence Why Greedy W...
2022-10-11 · via Long Luo's Life Notes

By Long Luo

This article is the solution Why Greedy Works? of Problem 334. Increasing Triplet Subsequence.

Intution

We can easily find that whether there exists a triple of indices \((i, j, k)\) such that \(i < j < k\) and \(nums[i] < \textit{nums}[j] < \textit{nums}[k]\) only traversing the array once, but the problem is how to make our mind into algorithms.

Brute Force

It’s easy to use Brute Force way to solve this problem, but the time complexity is \(O(n^3)\), it will TLE, so we need to find a better way.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public static boolean increasingTriplet(int[] nums) {
if (nums == null || nums.length < 3) {
return false;
}

int len = nums.length;
for (int i = 0; i < len; i++) {
for (int j = i + 1; j < len; j++) {
for (int k = j + 1; k < len; k++) {
if (nums[i] < nums[j] && nums[j] < nums[k]) {
return true;
}
}
}
}

return false;
}

Analysis

  • Time Complexity: \(O(n^3)\)
  • Space Complexity: \(O(1)\)

Dynamic Programming

We can also use DP method to solve it.

Let \(dp[i]\) represents the maximum length of a increasing sequence.

\[ dp[i] = \begin{cases} 1 & dp[i] \le dp[j], 0 < j < i \\ dp[j] + 1 & dp[i] > dp[j], 0 < j < i \end{cases} \]

​ We can reduce the time complexity to \(O(n^2)\), but it still will TLE.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public boolean increasingTriplet(int[] nums) {
int len = nums.length;

int[] dp = new int[len];
Arrays.fill(dp, 1);

for (int i = 0; i < len; i++) {
for (int j = 0; j < i; j++) {
if (nums[j] < nums[i]) {
dp[i] = dp[j] + 1;
}

if (dp[i] >= 3) {
return true;
}
}
}

return false;
}

Analysis

  • Time Complexity: \(O(n^2)\)
  • Space Complexity: \(O(n)\)

Two Pointers

When traversing the array \(\textit{nums}[j]\), \(0 < j < n − 1\), if there is an element on the left of \(\textit{nums}[i] < \textit{nums}[j]\), \(0 \le i < j\), and an element on the right of \(\textit{nums}[k]\), \(j < k < len\).

Therefore, we can maintain the minimum value on the left and the maximum value on the right of each element in the array.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
 
public static boolean increasingTriplet_tp(int[] nums) {
if (nums == null || nums.length < 3) {
return false;
}

int len = nums.length;
int[] leftMin = new int[len];
leftMin[0] = nums[0];
for (int i = 1; i < len; i++) {
leftMin[i] = Math.min(leftMin[i - 1], nums[i]);
}

int[] rightMax = new int[len];
rightMax[len - 1] = nums[len - 1];
for (int i = len - 2; i >= 0; i--) {
rightMax[i] = Math.max(rightMax[i + 1], nums[i]);
}

for (int i = 0; i < len; i++) {
if (nums[i] > leftMin[i] && nums[i] < rightMax[i]) {
return true;
}
}

return false;
}

Analysis

  • Time Complexity: \(O(n)\)
  • Space Complexity: \(O(n)\)

We can easily know that we can find the answer with just traverse the array once.

Assuming that we already have two numbers \(\textit{first}\) and \(\textit{second}\), with \(\textit{second} > \textit{first}\), now we have to find the \(\textit{third}\) number while traversing the array.

The \(third\) number can be as follows:

  1. If \(\textit{third} > \textit{second}\), we have found it and return true directly.

  2. If \(\textit{third} < \textit{second}\) && \(\textit{third} > \textit{first}\), we make \(\textit{second} = \textit{third}\), and continue traversing the rest array to find the \(third\) number.

  3. If \(\textit{third} < \textit{first}\), we make \(\textit{first} = \textit{third}\), and then continue to search for the \(\textit{third}\).

The trick is here.

  1. You would worry that the \(\textit{first}\) is now behind the \(\textit{second}\). Image if we meet \(\textit{third} > \textit{second}\), we can use the old \(\textit{first}\) that meets \(\textit{first} < \textit{second} < \textit{third}\).

  2. We make \(\textit{first} = \textit{third}\), we can select a lower \(\textit{second}\) and \(\textit{third}\) because the \(\textit{first}\) become smaller.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
 
public boolean increasingTriplet(int[] nums) {
if (nums == null || nums.length < 3) {
return false;
}

int first = nums[0];
int second = Integer.MAX_VALUE;

for (int third : nums) {
if (third > second) {
return true;
} else if (third > first) {
second = third;
} else {
first = third;
}
}

return false;
}

Analysis

  • Time Complexity: \(O(n)\)
  • Space Complexity: \(O(1)\)

All suggestions are welcome. If you have any query or suggestion please comment below. Please upvote👍 if you like💗 it. Thank you:-)

Explore More Leetcode Solutions. 😉😃💗