Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 4defb3d

Browse files
2 parents 5da6c06 + 1e9bb56 commit 4defb3d

20 files changed

+499
-85
lines changed

‎problems/0015.三数之和.md‎

Lines changed: 26 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -313,54 +313,36 @@ func threeSum(nums []int)[][]int{
313313
javaScript:
314314

315315
```js
316-
/**
317-
* @param {number[]} nums
318-
* @return {number[][]}
319-
*/
320-
321-
// 循环内不考虑去重
322-
var threeSum = function(nums) {
323-
const len = nums.length;
324-
if(len < 3) return [];
325-
nums.sort((a, b) => a - b);
326-
const resSet = new Set();
327-
for(let i = 0; i < len - 2; i++) {
328-
if(nums[i] > 0) break;
329-
let l = i + 1, r = len - 1;
330-
while(l < r) {
331-
const sum = nums[i] + nums[l] + nums[r];
332-
if(sum < 0) { l++; continue };
333-
if(sum > 0) { r--; continue };
334-
resSet.add(`${nums[i]},${nums[l]},${nums[r]}`);
335-
l++;
336-
r--;
337-
}
338-
}
339-
return Array.from(resSet).map(i => i.split(","));
340-
};
341-
342-
// 去重优化
343316
var threeSum = function(nums) {
344-
const len = nums.length;
345-
if(len <3) return [];
346-
nums.sort((a, b) => a - b);
347-
constres= [];
348-
for(let i = 0; i <len - 2; i++) {
349-
if(nums[i] >0) break;
350-
// a去重
351-
if(i >0&& nums[i] === nums[i -1]) continue;
352-
let l = i +1, r = len - 1;
317+
const res= [], len = nums.length
318+
// 将数组排序
319+
nums.sort((a, b) => a - b)
320+
for (let i =0; i < len; i++) {
321+
let l = i +1, r =len - 1, iNum = nums[i]
322+
// 数组排过序,如果第一个数大于0直接返回res
323+
if (iNum >0) return res
324+
// 去重
325+
if (iNum == nums[i - 1]) continue
353326
while(l < r) {
354-
const sum = nums[i] + nums[l] + nums[r];
355-
if(sum < 0) { l++; continue };
356-
if(sum > 0) { r--; continue };
357-
res.push([nums[i], nums[l], nums[r]])
358-
// b c 去重
359-
while(l < r && nums[l] === nums[++l]);
360-
while(l < r && nums[r] === nums[--r]);
327+
let lNum = nums[l], rNum = nums[r], threeSum = iNum + lNum + rNum
328+
// 三数之和小于0,则左指针向右移动
329+
if (threeSum < 0) l++
330+
else if (threeSum > 0) r--
331+
else {
332+
res.push([iNum, lNum, rNum])
333+
// 去重
334+
while(l < r && nums[l] == nums[l + 1]){
335+
l++
336+
}
337+
while(l < r && nums[r] == nums[r - 1]) {
338+
r--
339+
}
340+
l++
341+
r--
342+
}
361343
}
362344
}
363-
return res;
345+
return res
364346
};
365347
```
366348
TypeScript:

‎problems/0018.四数之和.md‎

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131

3232
四数之和,和[15.三数之和](https://programmercarl.com/0015.三数之和.html)是一个思路,都是使用双指针法, 基本解法就是在[15.三数之和](https://programmercarl.com/0015.三数之和.html) 的基础上再套一层for循环。
3333

34-
但是有一些细节需要注意,例如: 不要判断`nums[k] > target` 就返回了,三数之和 可以通过 `nums[i] > 0` 就返回了,因为 0 已经是确定的数了,四数之和这道题目 target是任意值。(大家亲自写代码就能感受出来)
34+
但是有一些细节需要注意,例如: 不要判断`nums[k] > target` 就返回了,三数之和 可以通过 `nums[i] > 0` 就返回了,因为 0 已经是确定的数了,四数之和这道题目 target是任意值。比如:数组是`[-4, -3, -2, -1]`,`target``-10`,不能因为`-4 > -10`而跳过。但是我们依旧可以去做剪枝,逻辑变成`nums[i] > target && (nums[i] >=0 || target >= 0)`就可以了。
3535

3636
[15.三数之和](https://programmercarl.com/0015.三数之和.html)的双指针解法是一层for循环num[i]为确定值,然后循环内有left和right下标作为双指针,找到nums[i] + nums[left] + nums[right] == 0。
3737

@@ -72,15 +72,20 @@ public:
7272
vector<vector<int>> result;
7373
sort(nums.begin(), nums.end());
7474
for (int k = 0; k < nums.size(); k++) {
75-
// 这种剪枝是错误的,这道题目target 是任意值
76-
// if (nums[k] > target) {
77-
// return result;
78-
// }
75+
// 剪枝处理
76+
if (nums[k] > target && (nums[k] >= 0 || target >= 0)) {
77+
break; // 这里使用break,统一通过最后的return返回
78+
}
7979
// 去重
8080
if (k > 0 && nums[k] == nums[k - 1]) {
8181
continue;
8282
}
8383
for (int i = k + 1; i < nums.size(); i++) {
84+
// 2级剪枝处理
85+
if (nums[k] + nums[i] > target && (nums[k] + nums[i] >= 0 || target >= 0)) {
86+
break;
87+
}
88+
8489
// 正确去重方法
8590
if (i > k + 1 && nums[i] == nums[i - 1]) {
8691
continue;

‎problems/0056.合并区间.md‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,26 @@ var merge = function(intervals) {
266266
};
267267
```
268268

269+
### TypeScript
270+
271+
```typescript
272+
function merge(intervals: number[][]): number[][] {
273+
const resArr: number[][] = [];
274+
intervals.sort((a, b) => a[0] - b[0]);
275+
resArr[0] = [...intervals[0]]; // 避免修改原intervals
276+
for (let i = 1, length = intervals.length; i < length; i++) {
277+
let interval: number[] = intervals[i];
278+
let last: number[] = resArr[resArr.length - 1];
279+
if (interval[0] <= last[1]) {
280+
last[1] = Math.max(interval[1], last[1]);
281+
} else {
282+
resArr.push([...intervals[i]]);
283+
}
284+
}
285+
return resArr;
286+
};
287+
```
288+
269289

270290

271291
-----------------------

‎problems/0059.螺旋矩阵II.md‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030

3131
相信很多同学刚开始做这种题目的时候,上来就是一波判断猛如虎。
3232

33-
结果运行的时候各种问题,然后开始各种修修补补,最后发现改了这里哪里有问题,改了那里这里又跑不起来了。
33+
结果运行的时候各种问题,然后开始各种修修补补,最后发现改了这里那里有问题,改了那里这里又跑不起来了。
3434

3535
大家还记得我们在这篇文章[数组:每次遇到二分法,都是一看就会,一写就废](https://programmercarl.com/0704.二分查找.html)中讲解了二分法,提到如果要写出正确的二分法一定要坚持**循环不变量原则**
3636

@@ -47,7 +47,7 @@
4747

4848
可以发现这里的边界条件非常多,在一个循环中,如此多的边界条件,如果不按照固定规则来遍历,那就是**一进循环深似海,从此offer是路人**
4949

50-
这里一圈下来,我们要画每四条边,这四条边怎么画,每画一条边都要坚持一致的左闭右开,或者左开又闭的原则,这样这一圈才能按照统一的规则画下来。
50+
这里一圈下来,我们要画每四条边,这四条边怎么画,每画一条边都要坚持一致的左闭右开,或者左开右闭的原则,这样这一圈才能按照统一的规则画下来。
5151

5252
那么我按照左闭右开的原则,来画一圈,大家看一下:
5353

@@ -59,7 +59,7 @@
5959

6060
一些同学做这道题目之所以一直写不好,代码越写越乱。
6161

62-
就是因为在画每一条边的时候,一会左开又闭,一会左闭右闭,一会又来左闭右开,岂能不乱。
62+
就是因为在画每一条边的时候,一会左开右闭,一会左闭右闭,一会又来左闭右开,岂能不乱。
6363

6464
代码如下,已经详细注释了每一步的目的,可以看出while循环里判断的情况是很多的,代码里处理的原则也是统一的左闭右开。
6565

‎problems/0131.分割回文串.md‎

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -454,31 +454,36 @@ var partition = function(s) {
454454

455455
```typescript
456456
function partition(s: string): string[][] {
457-
function isPalindromeStr(s: string, left: number, right: number): boolean {
458-
while (left < right) {
459-
if (s[left++] !== s[right--]) {
460-
return false;
457+
const res: string[][] = []
458+
const path: string[] = []
459+
const isHuiwen = (
460+
str: string,
461+
startIndex: number,
462+
endIndex: number
463+
): boolean => {
464+
for (; startIndex < endIndex; startIndex++, endIndex--) {
465+
if (str[startIndex] !== str[endIndex]) {
466+
return false
461467
}
462468
}
463-
return true;
469+
return true
464470
}
465-
function backTracking(s: string, startIndex: number, route: string[]): void {
466-
let length: number = s.length;
467-
if (length === startIndex) {
468-
resArr.push(route.slice());
469-
return;
471+
const rec = (str: string, index: number): void => {
472+
if (index >= str.length) {
473+
res.push([...path])
474+
return
470475
}
471-
for (let i = startIndex; i < length; i++) {
472-
if (isPalindromeStr(s, startIndex, i)) {
473-
route.push(s.slice(startIndex, i + 1));
474-
backTracking(s, i + 1, route);
475-
route.pop();
476+
for (let i = index; i < str.length; i++) {
477+
if (!isHuiwen(str, index, i)) {
478+
continue
476479
}
480+
path.push(str.substring(index, i + 1))
481+
rec(str, i + 1)
482+
path.pop()
477483
}
478484
}
479-
const resArr: string[][] = [];
480-
backTracking(s, 0, []);
481-
return resArr;
485+
rec(s, 0)
486+
return res
482487
};
483488
```
484489

‎problems/0134.加油站.md‎

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,9 @@ function canCompleteCircuit(gas: number[], cost: number[]): number {
408408

409409
### C
410410

411+
贪心算法:方法一
412+
413+
411414
```c
412415
int canCompleteCircuit(int* gas, int gasSize, int* cost, int costSize){
413416
int curSum = 0;
@@ -437,5 +440,36 @@ int canCompleteCircuit(int* gas, int gasSize, int* cost, int costSize){
437440
}
438441
```
439442
443+
贪心算法:方法二
444+
```c
445+
int canCompleteCircuit(int* gas, int gasSize, int* cost, int costSize){
446+
int curSum = 0;
447+
int totalSum = 0;
448+
int start = 0;
449+
450+
int i;
451+
for(i = 0; i < gasSize; ++i) {
452+
// 当前i站中加油量与耗油量的差
453+
int diff = gas[i] - cost[i];
454+
455+
curSum += diff;
456+
totalSum += diff;
457+
458+
// 若0到i的加油量都为负,则开始位置应为i+1
459+
if(curSum < 0) {
460+
curSum = 0;
461+
// 当i + 1 == gasSize时,totalSum < 0(此时i为gasSize - 1),油车不可能返回原点
462+
start = i + 1;
463+
}
464+
}
465+
466+
// 若总和小于0,加油车无论如何都无法返回原点。返回-1
467+
if(totalSum < 0)
468+
return -1;
469+
470+
return start;
471+
}
472+
```
473+
440474
-----------------------
441475
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>

‎problems/0150.逆波兰表达式求值.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ public:
109109
};
110110
```
111111
112-
# 题外话
112+
## 题外话
113113
114114
我们习惯看到的表达式都是中缀表达式,因为符合我们的习惯,但是中缀表达式对于计算机来说就不是很友好了。
115115
@@ -128,7 +128,7 @@ public:
128128
129129
130130
131-
# 其他语言版本
131+
## 其他语言版本
132132
133133
java:
134134

‎problems/0203.移除链表元素.md‎

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,38 @@ public:
145145
146146
## 其他语言版本
147147
C:
148+
用原来的链表操作:
149+
```c
150+
struct ListNode* removeElements(struct ListNode* head, int val){
151+
struct ListNode* temp;
152+
// 当头结点存在并且头结点的值等于val时
153+
while(head && head->val == val) {
154+
temp = head;
155+
// 将新的头结点设置为head->next并删除原来的头结点
156+
head = head->next;
157+
free(temp);
158+
}
159+
160+
struct ListNode *cur = head;
161+
// 当cur存在并且cur->next存在时
162+
// 此解法需要判断cur存在因为cur指向head。若head本身为NULL或者原链表中元素都为val的话,cur也会为NULL
163+
while(cur && (temp = cur->next)) {
164+
// 若cur->next的值等于val
165+
if(temp->val == val) {
166+
// 将cur->next设置为cur->next->next并删除cur->next
167+
cur->next = temp->next;
168+
free(temp);
169+
}
170+
// 若cur->next不等于val,则将cur后移一位
171+
else
172+
cur = cur->next;
173+
}
174+
175+
// 返回头结点
176+
return head;
177+
}
178+
```
179+
设置一个虚拟头结点:
148180
```c
149181
/**
150182
* Definition for singly-linked list.

‎problems/0209.长度最小的子数组.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ public:
112112

113113
**一些录友会疑惑为什么时间复杂度是O(n)**
114114

115-
不要以为for里放一个while就以为是O(n^2)啊, 主要是看每一个元素被操作的次数,每个元素在滑动窗后进来操作一次,出去操作一次,每个元素都是被被操作两次,所以时间复杂度是 2 ×ばつ n 也就是O(n)。
115+
不要以为for里放一个while就以为是O(n^2)啊, 主要是看每一个元素被操作的次数,每个元素在滑动窗后进来操作一次,出去操作一次,每个元素都是被操作两次,所以时间复杂度是 2 ×ばつ n 也就是O(n)。
116116

117117
## 相关题目推荐
118118

‎problems/0309.最佳买卖股票时机含冷冻期.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -214,8 +214,8 @@ class Solution {
214214

215215
for (int i = 2; i <= prices.length; i++) {
216216
/*
217-
dp[i][0] 第i天未持有股票收益;
218-
dp[i][1] 第i天持有股票收益;
217+
dp[i][0] 第i天持有股票收益;
218+
dp[i][1] 第i天不持有股票收益;
219219
情况一:第i天是冷静期,不能以dp[i-1][1]购买股票,所以以dp[i - 2][1]买股票,没问题
220220
情况二:第i天不是冷静期,理论上应该以dp[i-1][1]购买股票,但是第i天不是冷静期说明,第i-1天没有卖出股票,
221221
则dp[i-1][1]=dp[i-2][1],所以可以用dp[i-2][1]买股票,没问题

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /