Skip to content

Commit

Permalink
更新题解列表
Browse files Browse the repository at this point in the history
  • Loading branch information
itcharge committed Jan 30, 2023
1 parent b8d8e66 commit 59d86b7
Show file tree
Hide file tree
Showing 5 changed files with 284 additions and 12 deletions.
39 changes: 35 additions & 4 deletions Solutions/0002. 两数相加.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,42 @@

## 题目大意

描述:给定两个非空的链表 `l1``l2`。分别用来表示两个非负整数,每位数字都是按照逆序的方式存储的,每个节点存储一位数字。
**描述**:给定两个非空的链表 `l1``l2`。分别用来表示两个非负整数,每位数字都是按照逆序的方式存储的,每个节点存储一位数字。

要求:计算两个非负整数的和,并逆序返回表示和的链表。
**要求**:计算两个非负整数的和,并逆序返回表示和的链表。

**说明**

- 每个链表中的节点数在范围 $[1, 100]$ 内。
- $0 \le Node.val \le 9$。
- 题目数据保证列表表示的数字不含前导零。

**示例**

- 示例 1:

![](https://assets.leetcode-cn.com/aliyun-lc-upload/uploads/2021/01/02/addtwonumber1.jpg)

```Python
输入:l1 = [2,4,3], l2 = [5,6,4]
输出:[7,0,8]
解释:342 + 465 = 807.
```

- 示例 2:

```Python
输入:l1 = [0], l2 = [0]
输出:[0]
```

## 解题思路

模拟大数加法,按位相加,将结果添加到新链表上。需要注意进位和对 10 取余。
### 思路 1:模拟

模拟大数加法,按位相加,将结果添加到新链表上。需要注意进位和对 $10$ 取余。

## 代码
### 思路 1:代码

```Python
class Solution:
Expand Down Expand Up @@ -41,3 +68,7 @@ class Solution:
return head.next
```

### 思路 1:复杂度分析

- **时间复杂度**:$O(max(m, n))$。其中,$m$ 和 $n$ 分别是链表 `l1``l2` 的长度。
- **空间复杂度**:$O(1)$。
142 changes: 142 additions & 0 deletions Solutions/0032. 最长有效括号.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
# [0032. 最长有效括号](https://leetcode.cn/problems/longest-valid-parentheses/)

- 标签:栈、字符串、动态规划
- 难度:困难

## 题目大意

**描述**:给定一个只包含 `'('``')'` 的字符串。

**要求**:找出最长有效(格式正确且连续)括号子串的长度。

**说明**

- $0 \le s.length \le 3 * 10^4$。
- `s[i]``'('``')'`

**示例**

- 示例 1:

```Python
输入:s = "(()"
输出:2
解释:最长有效括号子串是 "()"
```

- 示例 2:

```Python
输入:s = ")()())"
输出:4
解释:最长有效括号子串是 "()()"
```

## 解题思路

### 思路 1:动态规划

###### 1. 划分阶段

按照最长有效括号子串的结束位置进行阶段划分。

###### 2. 定义状态

定义状态 `dp[i]` 表示为:以字符 `s[i]` 为结尾的最长有效括号的长度。

###### 3. 状态转移方程

- 如果 `s[i] == '('`,此时以 `s[i]` 结尾的子串不可能构成有效括号对,则 `dp[i] = 0`
- 如果 `s[i] == ')'`,我们需要考虑 `s[i - 1]` 来判断是否能够构成有效括号对。
- 如果 `s[i - 1] == '('`,字符串形如 `......()`,此时 `s[i - 1]``s[i]``()`,则:
- `dp[i]` 取决于「以字符 `s[i - 2]` 为结尾的最长有效括号长度」 + 「`s[i - 1]``s[i]` 构成的有效括号对长度(`2`)」,即 `dp[i] = dp[i - 2] + 2`
- 特别地,如果 `s[i - 2]` 不存在,即 `i - 2 < 0`,则 `dp[i]` 直接取决于 「`s[i - 1]``s[i]` 构成的有效括号对长度(`2`)」,即 `dp[i] = 2`
- 如果 `s[i - 1] == ')'`,字符串形如 `......))`,此时 `s[i - 1]``s[i]``))`。那么以 `s[i - 1]` 为结尾的最长有效长度为 `dp[i - 1]`,则我们需要看 `i - 1 - dp[i - 1]` 位置上的字符 `s[i - 1 - dp[i - 1]]`是否与 `s[i]` 匹配。
- 如果 `s[i - 1 - dp[i - 1]] == '('`,则说明 `s[i - 1 - dp[i - 1]]``s[i]` 相匹配,此时我们需要看以 `s[i - 1 - dp[i - 1]]` 的前一个字符 `s[i - 1 - dp[i - 2]]` 为结尾的最长括号长度是多少,将其加上 ``s[i - 1 - dp[i - 1]]``s[i]`,从而构成更长的有效括号对:
- `dp[i]` 取决于「以字符 `s[i - 1]` 为结尾的最长括号长度」 + 「以字符 `s[i - 1 - dp[i - 2]]` 为结尾的最长括号长度」+ 「`s[i - 1 - dp[i - 1]]``s[i]` 的长度(`2`)」,即 `dp[i] = dp[i - 1] + dp[i - dp[i - 1] - 2] + 2`
- 特别地,如果 `s[i - dp[i - 1] - 2]` 不存在,即 `i - dp[i - 1] - 2 < 0`,则 `dp[i]` 直接取决于「以字符 `s[i - 1]` 为结尾的最长括号长度」+「`s[i - 1 - dp[i - 1]]``s[i]` 的长度(`2`)」,即 `dp[i] = dp[i - 1] + 2`

###### 4. 初始条件

- 默认所有以字符 `s[i]` 为结尾的最长有效括号的长度为 `0`,即 `dp[i] = 0`

###### 5. 最终结果

根据我们之前定义的状态,`dp[i]` 表示为:以字符 `s[i]` 为结尾的最长有效括号的长度。则最终结果为 `max(dp[i])`

### 思路 1:代码

```Python
class Solution:
def longestValidParentheses(self, s: str) -> int:
dp = [0 for _ in range(len(s))]
ans = 0
for i in range(1, len(s)):
if s[i] == '(':
continue
if s[i - 1] == '(':
if i >= 2:
dp[i] = dp[i - 2] + 2
else:
dp[i] = 2
elif i - dp[i - 1] > 0 and s[i - dp[i - 1] - 1] == '(':
if i - dp[i - 1] >= 2:
dp[i] = dp[i - 1] + dp[i - dp[i - 1] - 2] + 2
else:
dp[i] = dp[i - 1] + 2
ans = max(ans, dp[i])

return ans
```

### 思路 1:复杂度分析

- **时间复杂度**:$O(n)$,其中 $n$ 为字符串长度。
- **空间复杂度**:$O(n)$。

### 思路 2:栈

1. 定义一个变量 `ans` 用于维护最长有效括号的长度,初始时,`ans = 0`
2. 定义一个栈用于判定括号对是否匹配(栈中存储的是括号的下标),栈底元素始终保持「最长有效括号子串的开始元素的前一个元素下标」。
3. 初始时,我们在栈中存储 `-1` 作为哨兵节点,表示「最长有效括号子串的开始元素的前一个元素下标为 `-1`」,即 `stack = [-1]`
4. 然后从左至右遍历字符串。
1. 如果遇到左括号,即 `s[i] == '('`,则将其下标 `i` 压入栈,用于后续匹配右括号。
2. 如果遇到右括号,即 `s[i] == ')'`,则将其与最近的左括号进行匹配(即栈顶元素),弹出栈顶元素,与当前右括号进行匹配。弹出之后:
1. 如果栈为空,则说明:
1. 之前弹出的栈顶元素实际上是「最长有效括号子串的开始元素的前一个元素下标」,而不是左括号`(`,此时无法完成合法匹配。
2. 将当前右括号的坐标 `i` 压入栈中,充当「下一个有效括号子串的开始元素前一个下标」。
2. 如果栈不为空,则说明:
1. 之前弹出的栈顶元素为左括号 `(`,此时可完成合法匹配。
2. 当前合法匹配的长度为「当前右括号的下标 `i`」 - 「最长有效括号子串的开始元素的前一个元素下标」。即 `i - stack[-1]`
3. 更新最长匹配长度 `ans``max(ans, i - stack[-1])`
5. 遍历完输出答案 `ans`

### 思路 2:代码

```Python
class Solution:
def longestValidParentheses(self, s: str) -> int:
stack = [-1]
ans = 0
for i in range(len(s)):
if s[i] == '(':
stack.append(i)
else:
stack.pop()
if stack:
ans = max(ans, i - stack[-1])
else:
stack.append(i)
return ans
```

### 思路 2:复杂度分析

- **时间复杂度**:$O(n)$,其中 $n$ 为字符串长度。
- **空间复杂度**:$O(n)$。

## 参考资料

- 【题解】[动态规划思路详解(C++)——32.最长有效括号](https://leetcode.cn/problems/longest-valid-parentheses/solutions/206995/dong-tai-gui-hua-si-lu-xiang-jie-c-by-zhanganan042/)
- 【题解】[32. 最长有效括号 - 力扣(Leetcode)](https://leetcode.cn/problems/longest-valid-parentheses/solutions/314683/zui-chang-you-xiao-gua-hao-by-leetcode-solution/)
- 【题解】[【Nick~Hot一百题系列】超简单思路栈!](https://leetcode.cn/problems/longest-valid-parentheses/solutions/1258643/nickhotyi-bai-ti-xi-lie-chao-jian-dan-si-ggi4/)
57 changes: 50 additions & 7 deletions Solutions/0232. 用栈实现队列.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,56 @@

## 题目大意

仅使用两个栈实现先入先出队列。
**要求**:仅使用两个栈实现先入先出队列。

要求实现 `MyQueue` 类:

- `void push(int x)` 将元素 `x` 推到队列的末尾。
- `int pop()` 从队列的开头移除并返回元素。
- `int peek()` 返回队列开头的元素。
- `boolean empty()` 如果队列为空,返回 `True`;否则,返回 `False`

**说明**

- 只能使用标准的栈操作 —— 也就是只有 `push to top`, `peek / pop from top`, `size`, 和 `is empty` 操作是合法的。
- 可以使用 list 或者 deque(双端队列)来模拟一个栈,只要是标准的栈操作即可。
- $1 <= x <= 9$。
- 最多调用 $100$ 次 `push``pop``peek``empty`
- 假设所有操作都是有效的 (例如,一个空的队列不会调用 `pop` 或者 `peek` 操作)。
- 进阶:实现每个操作均摊时间复杂度为 `O(1)` 的队列。换句话说,执行 `n` 个操作的总时间复杂度为 `O(n)`,即使其中一个操作可能花费较长时间。

**示例**

- 示例 1:

```Python
输入:
["MyQueue", "push", "push", "peek", "pop", "empty"]
[[], [1], [2], [], [], []]
输出:
[null, null, null, 1, 1, false]

解释:
MyQueue myQueue = new MyQueue();
myQueue.push(1); // queue is: [1]
myQueue.push(2); // queue is: [1, 2] (leftmost is front of the queue)
myQueue.peek(); // return 1
myQueue.pop(); // return 1, queue is [2]
myQueue.empty(); // return false
```

## 解题思路

使用两个栈,inStack 用于输入,outStack 用于输出。
### 思路 1:双栈

- push 操作:将元素压入 inStack 中
- pop 操作:如果 outStack 输出栈为空,将 inStack 输入栈元素依次取出,按顺序压入 outStack 栈。这样 outStack 栈的元素顺序和之前 inStack 元素顺序相反,outStack 顶层元素就是要取出的队头元素,将其移出,并返回该元素。如果 outStack 输出栈不为空,则直接取出顶层元素。
- peek 操作:和 pop 操作类似,只不过最后一步不需要取出顶层元素,直接将其返回即可。
- empty 操作:如果 inStack 和 outStack 都为空,则队列为空,否则队列不为空。
使用两个栈,`inStack` 用于输入,`outStack` 用于输出。

## 代码
- `push` 操作:将元素压入 `inStack` 中。
- `pop` 操作:如果 `outStack` 输出栈为空,将 `inStack` 输入栈元素依次取出,按顺序压入 `outStack` 栈。这样 `outStack` 栈的元素顺序和之前 `inStack` 元素顺序相反,`outStack` 顶层元素就是要取出的队头元素,将其移出,并返回该元素。如果 `outStack` 输出栈不为空,则直接取出顶层元素。
- `peek` 操作:和 `pop` 操作类似,只不过最后一步不需要取出顶层元素,直接将其返回即可。
- `empty` 操作:如果 `inStack``outStack` 都为空,则队列为空,否则队列不为空。

### 思路 1:代码

```Python
class MyQueue:
Expand Down Expand Up @@ -68,3 +106,8 @@ class MyQueue:
"""
```

### 思路 1:复杂度分析

- **时间复杂度**`push``empty` 为 $O(1)$,`pop``peek` 为均摊 $O(1)$。
- **空间复杂度**:$O(n)$。

2 changes: 1 addition & 1 deletion Solutions/0678. 有效的括号字符串.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@

###### 3. 状态转移方程

长度大于 `2`时,我们需要根据 `s[i]``s[j]` 的情况,以及子串中间的有效字符串情况来判断 `dp[i][j]`
长度大于 `2` 时,我们需要根据 `s[i]``s[j]` 的情况,以及子串中间的有效字符串情况来判断 `dp[i][j]`

- 如果 `s[i]``s[j]` 分别表示左括号和右括号,或者为 `'*'`(此时 `s[i]``s[j]` 可以分别看做是左括号、右括号)。则如果 `dp[i + 1][j - 1] == True` 时,`dp[i][j] = True`
- 如果可以将从下标 `i` 到下标 `j` 的子串从中间分开为两个有效字符串,则 `dp[i][j] = True`。即如果存在 $i \le k < j$,使得 `dp[i][k] == True` 并且 `dp[k + 1][j] == True`,则 `dp[i][j] = True`
Expand Down
56 changes: 56 additions & 0 deletions Solutions/1903. 字符串中的最大奇数.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# [1903. 字符串中的最大奇数](https://leetcode.cn/problems/largest-odd-number-in-string/)

- 标签:贪心 、数学、字符串
- 难度:简单

## 题目大意

**描述**:给定一个字符串 `num`,表示一个大整数。

**要求**:在字符串 `num` 的所有非空子字符串中找出值最大的奇数,并以字符串形式返回。如果不存在奇数,则返回一个空字符串 `""`

**说明**

- **子字符串**:指的是字符串中一个连续的字符序列。
- $1 \le num.length \le 10^5$
- `num` 仅由数字组成且不含前导零。

**示例**

- 示例 1:

```Python
输入:num = "52"
输出:"5"
解释:非空子字符串仅有 "5""2""52""5" 是其中唯一的奇数。
```

- 示例 2:

```Python
输入:num = "4206"
输出:""
解释:在 "4206" 中不存在奇数。
```

## 解题思路

### 思路 1:贪心算法

1.

### 思路 1:代码

```Python
class Solution:
def largestOddNumber(self, num: str) -> str:
for i in range(len(num) - 1, -1, -1):
if int(num[i]) % 2 == 1:
return num[0: i + 1]
return ""
```

### 思路 1:复杂度分析

- **时间复杂度**:$O(n)$。
- **空间复杂度**:$O(1)$。

0 comments on commit 59d86b7

Please sign in to comment.