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 bb12666

Browse files
authored
Merge branch 'youngyangyang04:master' into master
2 parents 27718a4 + d1419b1 commit bb12666

14 files changed

+413
-39
lines changed

‎problems/0151.翻转字符串里的单词.md

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -639,7 +639,46 @@ func reverse(b []byte) {
639639
}
640640
}
641641
```
642-
642+
```go
643+
//双指针解法。指针逆序遍历,将遍历后得到的单词(间隔为空格,用以区分)顺序放置在额外空间
644+
//时间复杂度O(n),空间复杂度O(n)
645+
func reverseWords(s string) string {
646+
strBytes := []byte(s)
647+
n := len(strBytes)
648+
// 记录有效字符范围的起始和结束位置
649+
start, end := 0, n-1
650+
// 去除开头空格
651+
for start < n && strBytes[start] == 32 {
652+
start++
653+
}
654+
// 处理全是空格或空字符串情况
655+
if start == n {
656+
return ""
657+
}
658+
// 去除结尾空格
659+
for end >= 0 && strBytes[end] == 32 {
660+
end--
661+
}
662+
// 结果切片,预分配容量
663+
res := make([]byte, 0, end-start+1)//这里挺重要的,本人之前没有预分配容量,每次循环都添加单词,导致内存超限(也可能就是我之前的思路有问题)
664+
// 从后往前遍历有效字符范围
665+
for i := end; i >= start; {
666+
// 找单词起始位置,直接通过循环条件判断定位
667+
for ; i >= start && strBytes[i] == 32; i-- {
668+
}
669+
j := i
670+
for ; j >= start && strBytes[j]!= 32; j-- {
671+
}
672+
res = append(res, strBytes[j+1:i+1]...)
673+
// 只在不是最后一个单词时添加空格
674+
if j > start {
675+
res = append(res, 32)
676+
}
677+
i = j
678+
}
679+
return string(res)
680+
}
681+
```
643682

644683

645684
### JavaScript:

‎problems/0416.分割等和子集.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@
6060
* [动态规划:关于01背包问题,你该了解这些!](https://programmercarl.com/背包理论基础01背包-1.html)
6161
* [动态规划:关于01背包问题,你该了解这些!(滚动数组)](https://programmercarl.com/背包理论基础01背包-2.html)
6262

63-
### 01背包问题
63+
## 01背包问题
6464

6565
01背包问题,大家都知道,有N件物品和一个最多能背重量为W 的背包。第i件物品的重量是weight[i],得到的价值是value[i] 。每件物品只能用一次,求解将哪些物品装入背包里物品价值总和最大。
6666

@@ -92,7 +92,7 @@
9292

9393
动规五部曲分析如下:
9494

95-
1. 确定dp数组以及下标的含义
95+
### 1. 确定dp数组以及下标的含义
9696

9797
01背包中,dp[j] 表示: 容量(所能装的重量)为j的背包,所背的物品价值最大可以为dp[j]
9898

@@ -104,7 +104,7 @@
104104

105105
而dp[6] 就可以等于6了,放进1 和 5,那么dp[6] == 6,说明背包装满了。
106106

107-
2. 确定递推公式
107+
### 2. 确定递推公式
108108

109109
01背包的递推公式为:dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);
110110

@@ -113,7 +113,7 @@
113113
所以递推公式:dp[j] = max(dp[j], dp[j - nums[i]] + nums[i]);
114114

115115

116-
3. dp数组如何初始化
116+
### 3. dp数组如何初始化
117117

118118
在01背包,一维dp如何初始化,已经讲过,
119119

@@ -133,7 +133,7 @@
133133
vector<int> dp(10001, 0);
134134
```
135135
136-
4. 确定遍历顺序
136+
### 4. 确定遍历顺序
137137
138138
在[动态规划:关于01背包问题,你该了解这些!(滚动数组)](https://programmercarl.com/背包理论基础01背包-2.html)中就已经说明:如果使用一维dp数组,物品遍历的for循环放在外层,遍历背包的for循环放在内层,且内层for循环倒序遍历!
139139
@@ -148,7 +148,7 @@ for(int i = 0; i < nums.size(); i++) {
148148
}
149149
```
150150

151-
5. 举例推导dp数组
151+
### 5. 举例推导dp数组
152152

153153
dp[j]的数值一定是小于等于j的。
154154

‎problems/0459.重复的子字符串.md

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -689,6 +689,29 @@ var repeatedSubstringPattern = function (s) {
689689
};
690690
```
691691

692+
> 正则匹配
693+
```javascript
694+
/**
695+
* @param {string} s
696+
* @return {boolean}
697+
*/
698+
var repeatedSubstringPattern = function(s) {
699+
let reg = /^(\w+)1円+$/
700+
return reg.test(s)
701+
};
702+
```
703+
> 移动匹配
704+
```javascript
705+
/**
706+
* @param {string} s
707+
* @return {boolean}
708+
*/
709+
var repeatedSubstringPattern = function (s) {
710+
let ss = s + s;
711+
return ss.substring(1, ss.length - 1).includes(s);
712+
};
713+
```
714+
692715
### TypeScript:
693716

694717
> 前缀表统一减一
@@ -894,8 +917,10 @@ impl Solution {
894917
}
895918
```
896919
### C#
920+
921+
> 前缀表不减一
922+
897923
```csharp
898-
// 前缀表不减一
899924
public bool RepeatedSubstringPattern(string s)
900925
{
901926
if (s.Length == 0)
@@ -920,6 +945,13 @@ public int[] GetNext(string s)
920945
}
921946
```
922947

948+
> 移动匹配
949+
```csharp
950+
public bool RepeatedSubstringPattern(string s) {
951+
string ss = (s + s).Substring(1, (s + s).Length - 2);
952+
return ss.Contains(s);
953+
}
954+
```
923955
### C
924956

925957
```c

‎problems/0695.岛屿的最大面积.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444

4545
这里其实涉及到dfs的两种写法。
4646

47-
写法一,dfs只处理下一个节点,即在主函数遇到岛屿就计数为1,dfs处理接下来的相邻陆地
47+
写法一,dfs处理当前节点的相邻节点,即在主函数遇到岛屿就计数为1,dfs处理接下来的相邻陆地
4848

4949
```CPP
5050
// 版本一
@@ -87,7 +87,7 @@ public:
8787
};
8888
```
8989
90-
写法二,dfs处理当前节点,即即在主函数遇到岛屿就计数为0,dfs处理接下来的全部陆地
90+
写法二,dfs处理当前节点,即在主函数遇到岛屿就计数为0,dfs处理接下来的全部陆地
9191
9292
dfs
9393
```CPP

‎problems/0707.设计链表.md

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1191,6 +1191,160 @@ MyLinkedList.prototype.deleteAtIndex = function(index) {
11911191
*/
11921192
```
11931193

1194+
```js
1195+
/**
1196+
定义双头节点的结构:同时包含前指针`prev`和后指针next`
1197+
*/
1198+
class Node {
1199+
constructor(val, prev, next) {
1200+
this.val = val
1201+
this.prev = prev
1202+
this.next = next
1203+
}
1204+
}
1205+
1206+
/**
1207+
双链表:维护 `head` 和 `tail` 两个哨兵节点,这样可以简化对于中间节点的操作
1208+
并且维护 `size`,使得能够以O(1)时间判断操作是否合法
1209+
*/
1210+
var MyLinkedList = function () {
1211+
this.tail = new Node(-1)
1212+
this.head = new Node(-1)
1213+
this.tail.prev = this.head
1214+
this.head.next = this.tail
1215+
this.size = 0
1216+
};
1217+
1218+
/**
1219+
* 获取在index处节点的值
1220+
*
1221+
* @param {number} index
1222+
* @return {number}
1223+
*
1224+
* 时间复杂度: O(n)
1225+
* 空间复杂度: O(1)
1226+
*/
1227+
MyLinkedList.prototype.get = function (index) {
1228+
// 当索引超出范围时,返回-1
1229+
if (index > this.size) {
1230+
return -1
1231+
}
1232+
1233+
let cur = this.head
1234+
for (let i = 0; i <= index; i++) {
1235+
cur = cur.next
1236+
}
1237+
1238+
return cur.val
1239+
};
1240+
1241+
/**
1242+
* 在链表头部添加一个新节点
1243+
*
1244+
* @param {number} val
1245+
* @return {void}
1246+
*
1247+
* 时间复杂度: O(1)
1248+
* 空间复杂度: O(1)
1249+
*/
1250+
MyLinkedList.prototype.addAtHead = function (val) {
1251+
/**
1252+
head <-> [newNode] <-> originNode
1253+
*/
1254+
this.size++
1255+
const originNode = this.head.next
1256+
// 创建新节点,并建立连接
1257+
const newNode = new Node(val, this.head, originNode)
1258+
1259+
// 取消原前后结点的连接
1260+
this.head.next = newNode
1261+
originNode.prev = newNode
1262+
};
1263+
1264+
/**
1265+
* 在链表尾部添加一个新节点
1266+
*
1267+
* @param {number} val
1268+
* @return {void}
1269+
*
1270+
* 时间复杂度: O(1)
1271+
* 空间复杂度: O(1)
1272+
*/
1273+
MyLinkedList.prototype.addAtTail = function (val) {
1274+
/**
1275+
originNode <-> [newNode] <-> tail
1276+
*/
1277+
this.size++
1278+
const originNode = this.tail.prev
1279+
1280+
// 创建新节点,并建立连接
1281+
const newNode = new Node(val, originNode, this.tail)
1282+
1283+
// 取消原前后结点的连接
1284+
this.tail.prev = newNode
1285+
originNode.next = newNode
1286+
};
1287+
1288+
/**
1289+
* 在指定索引位置前添加一个新节点
1290+
*
1291+
* @param {number} index
1292+
* @param {number} val
1293+
* @return {void}
1294+
*
1295+
* 时间复杂度: O(n)
1296+
* 空间复杂度: O(1)
1297+
*/
1298+
MyLinkedList.prototype.addAtIndex = function (index, val) {
1299+
// 当索引超出范围时,直接返回
1300+
if (index > this.size) {
1301+
return
1302+
}
1303+
this.size++
1304+
1305+
let cur = this.head
1306+
for (let i = 0; i < index; i++) {
1307+
cur = cur.next
1308+
}
1309+
1310+
const new_next = cur.next
1311+
1312+
// 创建新节点,并建立连接
1313+
const node = new Node(val, cur, new_next)
1314+
1315+
// 取消原前后结点的连接
1316+
cur.next = node
1317+
new_next.prev = node
1318+
};
1319+
1320+
/**
1321+
* 删除指定索引位置的节点
1322+
*
1323+
* @param {number} index
1324+
* @return {void}
1325+
*
1326+
* 时间复杂度: O(n)
1327+
* 空间复杂度: O(1)
1328+
*/
1329+
MyLinkedList.prototype.deleteAtIndex = function (index) {
1330+
// 当索引超出范围时,直接返回
1331+
if (index >= this.size) {
1332+
return
1333+
}
1334+
1335+
this.size--
1336+
let cur = this.head
1337+
for (let i = 0; i < index; i++) {
1338+
cur = cur.next
1339+
}
1340+
1341+
const new_next = cur.next.next
1342+
// 取消原前后结点的连接
1343+
new_next.prev = cur
1344+
cur.next = new_next
1345+
};
1346+
```
1347+
11941348
### TypeScript:
11951349

11961350
```TypeScript

‎problems/0738.单调递增的数字.md

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -273,22 +273,20 @@ class Solution:
273273
### Go
274274
```go
275275
func monotoneIncreasingDigits(n int) int {
276-
s := strconv.Itoa(N)//将数字转为字符串,方便使用下标
277-
ss := []byte(s)//将字符串转为byte数组,方便更改。
278-
n := len(ss)
279-
if n <= 1 {
280-
return n
281-
}
282-
for i := n-1; i > 0; i-- {
283-
if ss[i-1] > ss[i] { //前一个大于后一位,前一位减1,后面的全部置为9
284-
ss[i-1] -= 1
285-
for j := i; j < n; j++ { //后面的全部置为9
286-
ss[j] = '9'
287-
}
288-
}
289-
}
290-
res, _ := strconv.Atoi(string(ss))
291-
return res
276+
s := strconv.Itoa(n)
277+
// 从左到右遍历字符串,找到第一个不满足单调递增的位置
278+
for i := len(s) - 2; i >= 0; i-- {
279+
if s[i] > s[i+1] {
280+
// 将该位置的数字减1
281+
s = s[:i] + string(s[i]-1) + s[i+1:]
282+
// 将该位置之后的所有数字置为9
283+
for j := i + 1; j < len(s); j++ {
284+
s = s[:j] + "9" + s[j+1:]
285+
}
286+
}
287+
}
288+
result, _ := strconv.Atoi(s)
289+
return result
292290
}
293291
```
294292

@@ -447,3 +445,4 @@ public class Solution
447445
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
448446
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
449447
</a>
448+

0 commit comments

Comments
(0)

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