Skip to content

Commit 0263d87

Browse files
committed
[Feature] add for new
1 parent 4fe5fb6 commit 0263d87

File tree

1 file changed

+248
-0
lines changed

1 file changed

+248
-0
lines changed
Lines changed: 248 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,248 @@
1+
---
2+
title: LC334. 递增的三元子序列 increasing-triplet-subsequence
3+
date: 2025-08-31
4+
categories: [Leetcode-75]
5+
tags: [leetcode, Leetcode-75, string]
6+
published: true
7+
---
8+
9+
# 334. 递增的三元子序列
10+
11+
给你一个整数数组 nums ,判断这个数组中是否存在长度为 3 的递增子序列。
12+
13+
如果存在这样的三元组下标 (i, j, k) 且满足 i < j < k ,使得 nums[i] < nums[j] < nums[k] ,返回 true ;否则,返回 false 。
14+
15+
16+
17+
示例 1:
18+
19+
输入:nums = [1,2,3,4,5]
20+
输出:true
21+
解释:任何 i < j < k 的三元组都满足题意
22+
示例 2:
23+
24+
输入:nums = [5,4,3,2,1]
25+
输出:false
26+
解释:不存在满足题意的三元组
27+
示例 3:
28+
29+
输入:nums = [2,1,5,0,4,6]
30+
输出:true
31+
解释:其中一个满足题意的三元组是 (3, 4, 5),因为 nums[3] == 0 < nums[4] == 4 < nums[5] == 6
32+
33+
34+
提示:
35+
36+
1 <= nums.length <= 5 * 10^5
37+
-2^31 <= nums[i] <= 2^31 - 1
38+
39+
40+
进阶:你能实现时间复杂度为 O(n) ,空间复杂度为 O(1) 的解决方案吗?
41+
42+
# v1-暴力
43+
44+
## 思路
45+
46+
管他 3*7,直接暴力。
47+
48+
## 实现
49+
50+
```java
51+
public boolean increasingTriplet(int[] nums) {
52+
int n = nums.length;
53+
if(n < 3) {
54+
return false;
55+
}
56+
57+
for(int i = 0; i < n-2; i++) {
58+
for(int j = i+1; j < n-1; j++) {
59+
for(int k = j+1; k < n; k++) {
60+
if(nums[i] < nums[j] && nums[j] < nums[k]) {
61+
return true;
62+
}
63+
}
64+
}
65+
}
66+
67+
return false;
68+
}
69+
```
70+
71+
72+
## 效果
73+
74+
出时间限制
75+
34 / 86 个通过的测试用例
76+
77+
## 复杂度
78+
79+
TC: O(n^3)
80+
81+
## 反思
82+
83+
炸的意料之中,为什么这么慢?
84+
85+
如何优化?
86+
87+
# v2-避免 string 创建
88+
89+
## 思路
90+
91+
我们不用 stack 试一下
92+
93+
## 实现
94+
95+
```java
96+
public String reverseWords(String s) {
97+
char pre = '\0';
98+
99+
int n = s.length();
100+
101+
StringBuilder sb = new StringBuilder();
102+
103+
Stack<String> stack = new Stack<>();
104+
StringBuilder temp = new StringBuilder();
105+
for(int i = 0; i < n; i++) {
106+
char c = s.charAt(i);
107+
108+
// 处理
109+
if(c != ' ') {
110+
temp.append(c);
111+
} else {
112+
if(temp.length() > 0) {
113+
sb.append(temp.reverse()).append(' ');
114+
// reset
115+
temp.setLength(0);
116+
}
117+
}
118+
119+
pre = c;
120+
}
121+
// 最后也要入队
122+
if(temp.length() > 0) {
123+
sb.append(temp.reverse()).append(' ');
124+
// reset
125+
temp.setLength(0);
126+
}
127+
128+
129+
// 删除最后一个空格
130+
sb.deleteCharAt(sb.length()-1);
131+
132+
return sb.reverse().toString();
133+
}
134+
```
135+
136+
## 效果
137+
138+
5ms 击败 68.93%
139+
140+
## 反思
141+
142+
略有提升,但是不多,因为逆序也是比较消耗性的
143+
144+
有没有方法可以避免反转?
145+
146+
147+
# v3-单词前插入
148+
149+
## 思路
150+
151+
有的,这个其实是对 stringbuiler 的理解。
152+
153+
我们可以把单词插入到前面,而不是末尾,这样就省的反转了。
154+
155+
## 实现
156+
157+
```java
158+
public String reverseWords(String s) {
159+
int n = s.length();
160+
StringBuilder sb = new StringBuilder();
161+
StringBuilder temp = new StringBuilder();
162+
163+
for (int i = 0; i < n; i++) {
164+
char c = s.charAt(i);
165+
if (c != ' ') {
166+
temp.append(c);
167+
} else {
168+
if (temp.length() > 0) {
169+
if (sb.length() > 0) sb.insert(0, ' '); // 前插空格
170+
sb.insert(0, temp); // 前插单词
171+
temp.setLength(0);
172+
}
173+
}
174+
}
175+
176+
// 最后一个单词
177+
if (temp.length() > 0) {
178+
if (sb.length() > 0) sb.insert(0, ' ');
179+
sb.insert(0, temp);
180+
}
181+
182+
return sb.toString();
183+
}
184+
```
185+
186+
## 效果
187+
188+
5ms 击败 68.93%
189+
190+
## 反思
191+
192+
感觉 v3 其实是一种很巧妙的解法了,但是效果一般
193+
194+
怀疑底层还是会涉及到 char[] 数组的移动。
195+
196+
# v4-原始数组处理
197+
198+
## 思路
199+
200+
我们可以用空间换时间。
201+
202+
1)临时数组,用于存储去除多余空格后的字符串
203+
204+
2)逆序遍历原始的数组,单词可以从 i 位置向前,用 j 来找到单词的开头。一直到新的 ' ' 或者开头。从 s[j ... i],依然是一个完整的单词。
205+
206+
通过 j 寻找,和直接逆序,效果应该是类似的。
207+
208+
## 实现
209+
210+
```java
211+
public String reverseWords(String s) {
212+
int n = s.length();
213+
char[] arr = new char[n]; // 不用 n+1
214+
int right = 0; // 写入 arr 的位置
215+
216+
int i = n - 1;
217+
while (i >= 0) {
218+
// 跳过空格
219+
while (i >= 0 && s.charAt(i) == ' ') i--;
220+
if (i < 0) break;
221+
222+
int j = i;
223+
// 找到单词起始位置
224+
while (j >= 0 && s.charAt(j) != ' ') j--;
225+
226+
// s[j+1 .. i] 是一个单词,顺序写入 arr
227+
if (right > 0) arr[right++] = ' '; // 单词间空格
228+
for (int k = j + 1; k <= i; k++) {
229+
arr[right++] = s.charAt(k);
230+
}
231+
232+
i = j - 1; // 移动到下一个单词
233+
}
234+
235+
return new String(arr, 0, right);
236+
}
237+
```
238+
239+
## 效果
240+
241+
2ms 击败 97.75%
242+
243+
## 反思
244+
245+
这种写法的技巧性比较强,也体现了我们对于数组的深刻理解。
246+
247+
# 参考资料
248+

0 commit comments

Comments
 (0)