14
README.md
14
README.md
@@ -5,10 +5,11 @@
|
||||
|
||||
> 1. **介绍**:本项目是一套完整的刷题计划,旨在帮助大家少走弯路,循序渐进学算法,[关注作者](#关于作者)
|
||||
> 2. **PDF版本** : [「代码随想录」算法精讲 PDF 版本](https://programmercarl.com/other/algo_pdf.html) 。
|
||||
> 3. **刷题顺序** : README已经将刷题顺序排好了,按照顺序一道一道刷就可以。
|
||||
> 4. **学习社区** : 一起学习打卡/面试技巧/如何选择offer/大厂内推/职场规则/简历修改/技术分享/程序人生。欢迎加入[「代码随想录」知识星球](https://programmercarl.com/other/kstar.html) 。
|
||||
> 5. **提交代码**:本项目统一使用C++语言进行讲解,但已经有Java、Python、Go、JavaScript等等多语言版本,感谢[这里的每一位贡献者](https://github.com/youngyangyang04/leetcode-master/graphs/contributors),如果你也想贡献代码点亮你的头像,[点击这里](https://mp.weixin.qq.com/s/tqCxrMEU-ajQumL1i8im9A)了解提交代码的方式。
|
||||
> 6. **转载须知** :以下所有文章皆为我([程序员Carl](https://github.com/youngyangyang04))的原创。引用本项目文章请注明出处,发现恶意抄袭或搬运,会动用法律武器维护自己的权益。让我们一起维护一个良好的技术创作环境!
|
||||
> 3. **最强八股文:**:[代码随想录知识星球精华PDF](https://www.programmercarl.com/other/kstar_baguwen.html)
|
||||
> 4. **刷题顺序** : README已经将刷题顺序排好了,按照顺序一道一道刷就可以。
|
||||
> 5. **学习社区** : 一起学习打卡/面试技巧/如何选择offer/大厂内推/职场规则/简历修改/技术分享/程序人生。欢迎加入[「代码随想录」知识星球](https://programmercarl.com/other/kstar.html) 。
|
||||
> 6. **提交代码**:本项目统一使用C++语言进行讲解,但已经有Java、Python、Go、JavaScript等等多语言版本,感谢[这里的每一位贡献者](https://github.com/youngyangyang04/leetcode-master/graphs/contributors),如果你也想贡献代码点亮你的头像,[点击这里](https://mp.weixin.qq.com/s/tqCxrMEU-ajQumL1i8im9A)了解提交代码的方式。
|
||||
> 7. **转载须知** :以下所有文章皆为我([程序员Carl](https://github.com/youngyangyang04))的原创。引用本项目文章请注明出处,发现恶意抄袭或搬运,会动用法律武器维护自己的权益。让我们一起维护一个良好的技术创作环境!
|
||||
|
||||
<p align="center">
|
||||
<a href="programmercarl.com" target="_blank">
|
||||
@@ -88,8 +89,7 @@
|
||||
|
||||
## 前序
|
||||
|
||||
* [「代码随想录」后序安排](https://mp.weixin.qq.com/s/4eeGJREy6E-v6D7cR_5A4g)
|
||||
* [「代码随想录」学习社区](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ)
|
||||
* [「代码随想录」学习社区](https://programmercarl.com/other/kstar.html)
|
||||
|
||||
|
||||
* 编程语言
|
||||
@@ -123,7 +123,7 @@
|
||||
|
||||
* 算法性能分析
|
||||
* [关于时间复杂度,你不知道的都在这里!](./problems/前序/关于时间复杂度,你不知道的都在这里!.md)
|
||||
* [$O(n)$的算法居然超时了,此时的n究竟是多大?](./problems/前序/On的算法居然超时了,此时的n究竟是多大?.md)
|
||||
* [O(n)的算法居然超时了,此时的n究竟是多大?](./problems/前序/On的算法居然超时了,此时的n究竟是多大?.md)
|
||||
* [通过一道面试题目,讲一讲递归算法的时间复杂度!](./problems/前序/通过一道面试题目,讲一讲递归算法的时间复杂度!.md)
|
||||
* [本周小结!(算法性能分析系列一)](./problems/周总结/20201210复杂度分析周末总结.md)
|
||||
* [关于空间复杂度,可能有几个疑问?](./problems/前序/关于空间复杂度,可能有几个疑问?.md)
|
||||
|
||||
@@ -462,7 +462,92 @@ var longestPalindrome = function(s) {
|
||||
};
|
||||
```
|
||||
|
||||
## C
|
||||
动态规划:
|
||||
```c
|
||||
//初始化dp数组,全部初始为false
|
||||
bool **initDP(int strLen) {
|
||||
bool **dp = (bool **)malloc(sizeof(bool *) * strLen);
|
||||
int i, j;
|
||||
for(i = 0; i < strLen; ++i) {
|
||||
dp[i] = (bool *)malloc(sizeof(bool) * strLen);
|
||||
for(j = 0; j < strLen; ++j)
|
||||
dp[i][j] = false;
|
||||
}
|
||||
return dp;
|
||||
}
|
||||
|
||||
char * longestPalindrome(char * s){
|
||||
//求出字符串长度
|
||||
int strLen = strlen(s);
|
||||
//初始化dp数组,元素初始化为false
|
||||
bool **dp = initDP(strLen);
|
||||
int maxLength = 0, left = 0, right = 0;
|
||||
|
||||
//从下到上,从左到右遍历
|
||||
int i, j;
|
||||
for(i = strLen - 1; i >= 0; --i) {
|
||||
for(j = i; j < strLen; ++j) {
|
||||
//若当前i与j所指字符一样
|
||||
if(s[i] == s[j]) {
|
||||
//若i、j指向相邻字符或同一字符,则为回文字符串
|
||||
if(j - i <= 1)
|
||||
dp[i][j] = true;
|
||||
//若i+1与j-1所指字符串为回文字符串,则i、j所指字符串为回文字符串
|
||||
else if(dp[i + 1][j - 1])
|
||||
dp[i][j] = true;
|
||||
}
|
||||
//若新的字符串的长度大于之前的最大长度,进行更新
|
||||
if(dp[i][j] && j - i + 1 > maxLength) {
|
||||
maxLength = j - i + 1;
|
||||
left = i;
|
||||
right = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
//复制回文字符串,并返回
|
||||
char *ret = (char*)malloc(sizeof(char) * (maxLength + 1));
|
||||
memcpy(ret, s + left, maxLength);
|
||||
ret[maxLength] = 0;
|
||||
return ret;
|
||||
}
|
||||
```
|
||||
|
||||
双指针:
|
||||
```c
|
||||
int left, maxLength;
|
||||
void extend(char *str, int i, int j, int size) {
|
||||
while(i >= 0 && j < size && str[i] == str[j]) {
|
||||
//若当前子字符串长度大于最长的字符串长度,进行更新
|
||||
if(j - i + 1 > maxLength) {
|
||||
maxLength = j - i + 1;
|
||||
left = i;
|
||||
}
|
||||
//左指针左移,右指针右移。扩大搜索范围
|
||||
++j, --i;
|
||||
}
|
||||
}
|
||||
|
||||
char * longestPalindrome(char * s){
|
||||
left = right = maxLength = 0;
|
||||
int size = strlen(s);
|
||||
|
||||
int i;
|
||||
for(i = 0; i < size; ++i) {
|
||||
//长度为单数的子字符串
|
||||
extend(s, i, i, size);
|
||||
//长度为双数的子字符串
|
||||
extend(s, i, i + 1, size);
|
||||
}
|
||||
|
||||
//复制子字符串
|
||||
char *subStr = (char *)malloc(sizeof(char) * (maxLength + 1));
|
||||
memcpy(subStr, s + left, maxLength);
|
||||
subStr[maxLength] = 0;
|
||||
|
||||
return subStr;
|
||||
}
|
||||
```
|
||||
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
||||
@@ -138,8 +138,12 @@ public:
|
||||
*/
|
||||
if (nums[i] + nums[left] + nums[right] > 0) {
|
||||
right--;
|
||||
// 当前元素不合适了,可以去重
|
||||
while (left < right && nums[right] == nums[right + 1]) right--;
|
||||
} else if (nums[i] + nums[left] + nums[right] < 0) {
|
||||
left++;
|
||||
// 不合适,去重
|
||||
while (left < right && nums[left] == nums[left - 1]) left++;
|
||||
} else {
|
||||
result.push_back(vector<int>{nums[i], nums[left], nums[right]});
|
||||
// 去重逻辑应该放在找到一个三元组之后
|
||||
|
||||
@@ -91,9 +91,13 @@ public:
|
||||
// nums[k] + nums[i] + nums[left] + nums[right] > target 会溢出
|
||||
if (nums[k] + nums[i] > target - (nums[left] + nums[right])) {
|
||||
right--;
|
||||
// 当前元素不合适了,可以去重
|
||||
while (left < right && nums[right] == nums[right + 1]) right--;
|
||||
// nums[k] + nums[i] + nums[left] + nums[right] < target 会溢出
|
||||
} else if (nums[k] + nums[i] < target - (nums[left] + nums[right])) {
|
||||
left++;
|
||||
// 不合适,去重
|
||||
while (left < right && nums[left] == nums[left - 1]) left++;
|
||||
} else {
|
||||
result.push_back(vector<int>{nums[k], nums[i], nums[left], nums[right]});
|
||||
// 去重逻辑应该放在找到一个四元组之后
|
||||
|
||||
@@ -159,7 +159,7 @@ class Solution {
|
||||
```
|
||||
|
||||
Python:
|
||||
```python3
|
||||
```python
|
||||
# 方法一,仅使用栈,更省空间
|
||||
class Solution:
|
||||
def isValid(self, s: str) -> bool:
|
||||
@@ -180,7 +180,7 @@ class Solution:
|
||||
return True if not stack else False
|
||||
```
|
||||
|
||||
```python3
|
||||
```python
|
||||
# 方法二,使用字典
|
||||
class Solution:
|
||||
def isValid(self, s: str) -> bool:
|
||||
@@ -283,8 +283,60 @@ var isValid = function(s) {
|
||||
};
|
||||
```
|
||||
|
||||
TypeScript:
|
||||
|
||||
版本一:普通版
|
||||
|
||||
```typescript
|
||||
function isValid(s: string): boolean {
|
||||
let helperStack: string[] = [];
|
||||
for (let i = 0, length = s.length; i < length; i++) {
|
||||
let x: string = s[i];
|
||||
switch (x) {
|
||||
case '(':
|
||||
helperStack.push(')');
|
||||
break;
|
||||
case '[':
|
||||
helperStack.push(']');
|
||||
break;
|
||||
case '{':
|
||||
helperStack.push('}');
|
||||
break;
|
||||
default:
|
||||
if (helperStack.pop() !== x) return false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return helperStack.length === 0;
|
||||
};
|
||||
```
|
||||
|
||||
版本二:优化版
|
||||
|
||||
```typescript
|
||||
function isValid(s: string): boolean {
|
||||
type BracketMap = {
|
||||
[index: string]: string;
|
||||
}
|
||||
let helperStack: string[] = [];
|
||||
let bracketMap: BracketMap = {
|
||||
'(': ')',
|
||||
'[': ']',
|
||||
'{': '}'
|
||||
}
|
||||
for (let i of s) {
|
||||
if (bracketMap.hasOwnProperty(i)) {
|
||||
helperStack.push(bracketMap[i]);
|
||||
} else if (i !== helperStack.pop()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return helperStack.length === 0;
|
||||
};
|
||||
```
|
||||
|
||||
Swift
|
||||
|
||||
```swift
|
||||
func isValid(_ s: String) -> Bool {
|
||||
var stack = [String.Element]()
|
||||
|
||||
@@ -106,6 +106,37 @@ public:
|
||||
|
||||
旧文链接:[数组:就移除个元素很难么?](https://programmercarl.com/0027.移除元素.html)
|
||||
|
||||
```CPP
|
||||
/**
|
||||
* 相向双指针方法,基于元素顺序可以改变的题目描述改变了元素相对位置,确保了移动最少元素
|
||||
* 时间复杂度:$O(n)$
|
||||
* 空间复杂度:$O(1)$
|
||||
*/
|
||||
class Solution {
|
||||
public:
|
||||
int removeElement(vector<int>& nums, int val) {
|
||||
int leftIndex = 0;
|
||||
int rightIndex = nums.size() - 1;
|
||||
while (leftIndex <= rightIndex) {
|
||||
// 找左边等于val的元素
|
||||
while (leftIndex <= rightIndex && nums[leftIndex] != val){
|
||||
++leftIndex;
|
||||
}
|
||||
// 找右边不等于val的元素
|
||||
while (leftIndex <= rightIndex && nums[rightIndex] == val) {
|
||||
-- rightIndex;
|
||||
}
|
||||
// 将右边不等于val的元素覆盖左边等于val的元素
|
||||
if (leftIndex < rightIndex) {
|
||||
nums[leftIndex++] = nums[rightIndex--];
|
||||
}
|
||||
}
|
||||
return leftIndex; // leftIndex一定指向了最终数组末尾的下一个元素
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
## 相关题目推荐
|
||||
|
||||
* 26.删除排序数组中的重复项
|
||||
@@ -142,7 +173,7 @@ class Solution {
|
||||
|
||||
Python:
|
||||
|
||||
```python3
|
||||
```python
|
||||
class Solution:
|
||||
"""双指针法
|
||||
时间复杂度:O(n)
|
||||
|
||||
@@ -929,6 +929,83 @@ var strStr = function (haystack, needle) {
|
||||
};
|
||||
```
|
||||
|
||||
TypeScript版本:
|
||||
|
||||
> 前缀表统一减一
|
||||
|
||||
```typescript
|
||||
function strStr(haystack: string, needle: string): number {
|
||||
function getNext(str: string): number[] {
|
||||
let next: number[] = [];
|
||||
let j: number = -1;
|
||||
next[0] = j;
|
||||
for (let i = 1, length = str.length; i < length; i++) {
|
||||
while (j >= 0 && str[i] !== str[j + 1]) {
|
||||
j = next[j];
|
||||
}
|
||||
if (str[i] === str[j + 1]) {
|
||||
j++;
|
||||
}
|
||||
next[i] = j;
|
||||
}
|
||||
return next;
|
||||
}
|
||||
if (needle.length === 0) return 0;
|
||||
let next: number[] = getNext(needle);
|
||||
let j: number = -1;
|
||||
for (let i = 0, length = haystack.length; i < length; i++) {
|
||||
while (j >= 0 && haystack[i] !== needle[j + 1]) {
|
||||
j = next[j];
|
||||
}
|
||||
if (haystack[i] === needle[j + 1]) {
|
||||
if (j === needle.length - 2) {
|
||||
return i - j - 1;
|
||||
}
|
||||
j++;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
};
|
||||
```
|
||||
|
||||
> 前缀表不减一
|
||||
|
||||
```typescript
|
||||
// 不减一版本
|
||||
function strStr(haystack: string, needle: string): number {
|
||||
function getNext(str: string): number[] {
|
||||
let next: number[] = [];
|
||||
let j: number = 0;
|
||||
next[0] = j;
|
||||
for (let i = 1, length = str.length; i < length; i++) {
|
||||
while (j > 0 && str[i] !== str[j]) {
|
||||
j = next[j - 1];
|
||||
}
|
||||
if (str[i] === str[j]) {
|
||||
j++;
|
||||
}
|
||||
next[i] = j;
|
||||
}
|
||||
return next;
|
||||
}
|
||||
if (needle.length === 0) return 0;
|
||||
let next: number[] = getNext(needle);
|
||||
let j: number = 0;
|
||||
for (let i = 0, length = haystack.length; i < length; i++) {
|
||||
while (j > 0 && haystack[i] !== needle[j]) {
|
||||
j = next[j - 1];
|
||||
}
|
||||
if (haystack[i] === needle[j]) {
|
||||
if (j === needle.length - 1) {
|
||||
return i - j;
|
||||
}
|
||||
j++;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
```
|
||||
|
||||
Swift 版本
|
||||
|
||||
> 前缀表统一减一
|
||||
|
||||
@@ -81,7 +81,7 @@ public:
|
||||
for (int j = nums.size() - 1; j > i; j--) {
|
||||
if (nums[j] > nums[i]) {
|
||||
swap(nums[j], nums[i]);
|
||||
sort(nums.begin() + i + 1, nums.end());
|
||||
reverse(nums.begin() + i + 1, nums.end());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -246,7 +246,7 @@ func searchInsert(nums []int, target int) int {
|
||||
```
|
||||
|
||||
### Python
|
||||
```python3
|
||||
```python
|
||||
class Solution:
|
||||
def searchInsert(self, nums: List[int], target: int) -> int:
|
||||
left, right = 0, len(nums) - 1
|
||||
|
||||
@@ -264,7 +264,7 @@ class Solution {
|
||||
|
||||
## Python
|
||||
**回溯**
|
||||
```python3
|
||||
```python
|
||||
class Solution:
|
||||
def __init__(self):
|
||||
self.path = []
|
||||
@@ -296,7 +296,7 @@ class Solution:
|
||||
self.path.pop() # 回溯
|
||||
```
|
||||
**剪枝回溯**
|
||||
```python3
|
||||
```python
|
||||
class Solution:
|
||||
def __init__(self):
|
||||
self.path = []
|
||||
|
||||
@@ -334,7 +334,7 @@ class Solution {
|
||||
|
||||
## Python
|
||||
**回溯+巧妙去重(省去使用used**
|
||||
```python3
|
||||
```python
|
||||
class Solution:
|
||||
def __init__(self):
|
||||
self.paths = []
|
||||
@@ -374,7 +374,7 @@ class Solution:
|
||||
sum_ -= candidates[i] # 回溯,为了下一轮for loop
|
||||
```
|
||||
**回溯+去重(使用used)**
|
||||
```python3
|
||||
```python
|
||||
class Solution:
|
||||
def __init__(self):
|
||||
self.paths = []
|
||||
|
||||
@@ -491,7 +491,7 @@ class Solution:
|
||||
return res
|
||||
```
|
||||
动态规划
|
||||
```python3
|
||||
```python
|
||||
class Solution:
|
||||
def trap(self, height: List[int]) -> int:
|
||||
leftheight, rightheight = [0]*len(height), [0]*len(height)
|
||||
|
||||
@@ -142,6 +142,7 @@ public:
|
||||
|
||||
### Java
|
||||
```Java
|
||||
// 版本一
|
||||
class Solution {
|
||||
public int jump(int[] nums) {
|
||||
if (nums == null || nums.length == 0 || nums.length == 1) {
|
||||
@@ -172,7 +173,30 @@ class Solution {
|
||||
}
|
||||
```
|
||||
|
||||
```java
|
||||
// 版本二
|
||||
class Solution {
|
||||
public int jump(int[] nums) {
|
||||
int result = 0;
|
||||
// 当前覆盖的最远距离下标
|
||||
int end = 0;
|
||||
// 下一步覆盖的最远距离下标
|
||||
int temp = 0;
|
||||
for (int i = 0; i <= end && end < nums.length - 1; ++i) {
|
||||
temp = Math.max(temp, i + nums[i]);
|
||||
// 可达位置的改变次数就是跳跃次数
|
||||
if (i == end) {
|
||||
end = temp;
|
||||
result++;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Python
|
||||
|
||||
```python
|
||||
class Solution:
|
||||
def jump(self, nums: List[int]) -> int:
|
||||
|
||||
@@ -243,7 +243,7 @@ class Solution:
|
||||
usage_list[i] = False
|
||||
```
|
||||
**回溯+丢掉usage_list**
|
||||
```python3
|
||||
```python
|
||||
class Solution:
|
||||
def __init__(self):
|
||||
self.path = []
|
||||
|
||||
@@ -143,5 +143,65 @@ var totalNQueens = function(n) {
|
||||
return count;
|
||||
};
|
||||
```
|
||||
|
||||
C
|
||||
```c
|
||||
//path[i]为在i行,path[i]列上存在皇后
|
||||
int *path;
|
||||
int pathTop;
|
||||
int answer;
|
||||
//检查当前level行index列放置皇后是否合法
|
||||
int isValid(int index, int level) {
|
||||
int i;
|
||||
//updater为若斜角存在皇后,其所应在的列
|
||||
//用来检查左上45度是否存在皇后
|
||||
int lCornerUpdater = index - level;
|
||||
//用来检查右上135度是否存在皇后
|
||||
int rCornerUpdater = index + level;
|
||||
for(i = 0; i < pathTop; ++i) {
|
||||
//path[i] == index检查index列是否存在皇后
|
||||
//检查斜角皇后:只要path[i] == updater,就说明当前位置不可放置皇后。
|
||||
//path[i] == lCornerUpdater检查左上角45度是否有皇后
|
||||
//path[i] == rCornerUpdater检查右上角135度是否有皇后
|
||||
if(path[i] == index || path[i] == lCornerUpdater || path[i] == rCornerUpdater)
|
||||
return 0;
|
||||
//更新updater指向下一行对应的位置
|
||||
++lCornerUpdater;
|
||||
--rCornerUpdater;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
//回溯算法:level为当前皇后行数
|
||||
void backTracking(int n, int level) {
|
||||
//若path中元素个数已经为n,则证明有一种解法。answer+1
|
||||
if(pathTop == n) {
|
||||
++answer;
|
||||
return;
|
||||
}
|
||||
|
||||
int i;
|
||||
for(i = 0; i < n; ++i) {
|
||||
//若当前level行,i列是合法的放置位置。就将i放入path中
|
||||
if(isValid(i, level)) {
|
||||
path[pathTop++] = i;
|
||||
backTracking(n, level + 1);
|
||||
//回溯
|
||||
--pathTop;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int totalNQueens(int n){
|
||||
answer = 0;
|
||||
pathTop = 0;
|
||||
path = (int *)malloc(sizeof(int) * n);
|
||||
|
||||
backTracking(n, 0);
|
||||
|
||||
return answer;
|
||||
}
|
||||
```
|
||||
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
[力扣题目链接](https://leetcode-cn.com/problems/spiral-matrix-ii/)
|
||||
|
||||
给定一个正整数 n,生成一个包含 1 到 $n^2$ 所有元素,且元素按顺时针顺序螺旋排列的正方形矩阵。
|
||||
给定一个正整数 n,生成一个包含 1 到 n^2 所有元素,且元素按顺时针顺序螺旋排列的正方形矩阵。
|
||||
|
||||
示例:
|
||||
|
||||
@@ -188,9 +188,9 @@ class Solution {
|
||||
}
|
||||
```
|
||||
|
||||
python:
|
||||
python3:
|
||||
|
||||
```python3
|
||||
```python
|
||||
class Solution:
|
||||
|
||||
def generateMatrix(self, n: int) -> List[List[int]]:
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
</a>
|
||||
<p align="center"><strong><a href="https://mp.weixin.qq.com/s/tqCxrMEU-ajQumL1i8im9A">参与本项目</a>,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!</strong></p>
|
||||
|
||||
## 63. 不同路径 II
|
||||
# 63. 不同路径 II
|
||||
|
||||
[力扣题目链接](https://leetcode-cn.com/problems/unique-paths-ii/)
|
||||
|
||||
@@ -22,23 +22,22 @@
|
||||
|
||||

|
||||
|
||||
输入:obstacleGrid = [[0,0,0],[0,1,0],[0,0,0]]
|
||||
输出:2
|
||||
* 输入:obstacleGrid = [[0,0,0],[0,1,0],[0,0,0]]
|
||||
* 输出:2
|
||||
解释:
|
||||
3x3 网格的正中间有一个障碍物。
|
||||
从左上角到右下角一共有 2 条不同的路径:
|
||||
1. 向右 -> 向右 -> 向下 -> 向下
|
||||
2. 向下 -> 向下 -> 向右 -> 向右
|
||||
* 3x3 网格的正中间有一个障碍物。
|
||||
* 从左上角到右下角一共有 2 条不同的路径:
|
||||
1. 向右 -> 向右 -> 向下 -> 向下
|
||||
2. 向下 -> 向下 -> 向右 -> 向右
|
||||
|
||||
示例 2:
|
||||
|
||||

|
||||
|
||||
输入:obstacleGrid = [[0,1],[0,0]]
|
||||
输出:1
|
||||
* 输入:obstacleGrid = [[0,1],[0,0]]
|
||||
* 输出:1
|
||||
|
||||
提示:
|
||||
|
||||
* m == obstacleGrid.length
|
||||
* n == obstacleGrid[i].length
|
||||
* 1 <= m, n <= 100
|
||||
@@ -171,7 +170,7 @@ public:
|
||||
|
||||
## 其他语言版本
|
||||
|
||||
Java:
|
||||
### Java
|
||||
|
||||
```java
|
||||
class Solution {
|
||||
@@ -199,7 +198,7 @@ class Solution {
|
||||
```
|
||||
|
||||
|
||||
Python:
|
||||
### Python
|
||||
|
||||
```python
|
||||
class Solution:
|
||||
@@ -262,7 +261,7 @@ class Solution:
|
||||
```
|
||||
|
||||
|
||||
Go:
|
||||
### Go
|
||||
|
||||
```go
|
||||
func uniquePathsWithObstacles(obstacleGrid [][]int) int {
|
||||
@@ -295,8 +294,8 @@ func uniquePathsWithObstacles(obstacleGrid [][]int) int {
|
||||
|
||||
```
|
||||
|
||||
Javascript
|
||||
``` Javascript
|
||||
### Javascript
|
||||
```Javascript
|
||||
var uniquePathsWithObstacles = function(obstacleGrid) {
|
||||
const m = obstacleGrid.length
|
||||
const n = obstacleGrid[0].length
|
||||
|
||||
@@ -143,10 +143,10 @@ class Solution {
|
||||
}
|
||||
```
|
||||
|
||||
Python:
|
||||
Python3:
|
||||
|
||||
|
||||
```python3
|
||||
```python
|
||||
class Solution:
|
||||
def climbStairs(self, n: int) -> int:
|
||||
dp = [0]*(n + 1)
|
||||
|
||||
@@ -174,7 +174,7 @@ class Solution {
|
||||
```
|
||||
|
||||
Python:
|
||||
```python3
|
||||
```python
|
||||
class Solution:
|
||||
def combine(self, n: int, k: int) -> List[List[int]]:
|
||||
res=[] #存放符合条件结果的集合
|
||||
|
||||
@@ -203,7 +203,7 @@ class Solution {
|
||||
```
|
||||
|
||||
## Python
|
||||
```python3
|
||||
```python
|
||||
class Solution:
|
||||
def __init__(self):
|
||||
self.path: List[int] = []
|
||||
|
||||
@@ -277,9 +277,9 @@ class Solution {
|
||||
}
|
||||
```
|
||||
|
||||
Python:
|
||||
Python3:
|
||||
|
||||
```python3
|
||||
```python
|
||||
|
||||
# 双指针;暴力解法(leetcode超时)
|
||||
class Solution:
|
||||
|
||||
@@ -304,6 +304,48 @@ class Solution {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
//方法二:比上面的方法时间复杂度低,更好地剪枝,优化时间复杂度
|
||||
class Solution {
|
||||
List<String> result = new ArrayList<String>();
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
|
||||
public List<String> restoreIpAddresses(String s) {
|
||||
restoreIpAddressesHandler(s, 0, 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
// number表示stringbuilder中ip段的数量
|
||||
public void restoreIpAddressesHandler(String s, int start, int number) {
|
||||
// 如果start等于s的长度并且ip段的数量是4,则加入结果集,并返回
|
||||
if (start == s.length() && number == 4) {
|
||||
result.add(stringBuilder.toString());
|
||||
return;
|
||||
}
|
||||
// 如果start等于s的长度但是ip段的数量不为4,或者ip段的数量为4但是start小于s的长度,则直接返回
|
||||
if (start == s.length() || number == 4) {
|
||||
return;
|
||||
}
|
||||
// 剪枝:ip段的长度最大是3,并且ip段处于[0,255]
|
||||
for (int i = start; i < s.length() && i - start < 3 && Integer.parseInt(s.substring(start, i + 1)) >= 0
|
||||
&& Integer.parseInt(s.substring(start, i + 1)) <= 255; i++) {
|
||||
// 如果ip段的长度大于1,并且第一位为0的话,continue
|
||||
if (i + 1 - start > 1 && s.charAt(start) - '0' == 0) {
|
||||
continue;
|
||||
}
|
||||
stringBuilder.append(s.substring(start, i + 1));
|
||||
// 当stringBuilder里的网段数量小于3时,才会加点;如果等于3,说明已经有3段了,最后一段不需要再加点
|
||||
if (number < 3) {
|
||||
stringBuilder.append(".");
|
||||
}
|
||||
number++;
|
||||
restoreIpAddressesHandler(s, i + 1, number);
|
||||
number--;
|
||||
// 删除当前stringBuilder最后一个网段,注意考虑点的数量的问题
|
||||
stringBuilder.delete(start + number, i + number + 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## python
|
||||
@@ -339,7 +381,7 @@ class Solution(object):
|
||||
```
|
||||
|
||||
python3:
|
||||
```python3
|
||||
```python
|
||||
class Solution:
|
||||
def __init__(self):
|
||||
self.result = []
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
</a>
|
||||
<p align="center"><strong><a href="https://mp.weixin.qq.com/s/tqCxrMEU-ajQumL1i8im9A">参与本项目</a>,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!</strong></p>
|
||||
|
||||
## 96.不同的二叉搜索树
|
||||
# 96.不同的二叉搜索树
|
||||
|
||||
[力扣题目链接](https://leetcode-cn.com/problems/unique-binary-search-trees/)
|
||||
|
||||
@@ -163,7 +163,7 @@ public:
|
||||
## 其他语言版本
|
||||
|
||||
|
||||
Java:
|
||||
### Java
|
||||
```Java
|
||||
class Solution {
|
||||
public int numTrees(int n) {
|
||||
@@ -184,7 +184,7 @@ class Solution {
|
||||
}
|
||||
```
|
||||
|
||||
Python:
|
||||
### Python
|
||||
```python
|
||||
class Solution:
|
||||
def numTrees(self, n: int) -> int:
|
||||
@@ -196,7 +196,7 @@ class Solution:
|
||||
return dp[-1]
|
||||
```
|
||||
|
||||
Go:
|
||||
### Go
|
||||
```Go
|
||||
func numTrees(n int)int{
|
||||
dp:=make([]int,n+1)
|
||||
@@ -210,7 +210,7 @@ func numTrees(n int)int{
|
||||
}
|
||||
```
|
||||
|
||||
Javascript:
|
||||
### Javascript
|
||||
```Javascript
|
||||
const numTrees =(n) => {
|
||||
let dp = new Array(n+1).fill(0);
|
||||
@@ -227,7 +227,34 @@ const numTrees =(n) => {
|
||||
};
|
||||
```
|
||||
|
||||
C:
|
||||
```c
|
||||
//开辟dp数组
|
||||
int *initDP(int n) {
|
||||
int *dp = (int *)malloc(sizeof(int) * (n + 1));
|
||||
int i;
|
||||
for(i = 0; i <= n; ++i)
|
||||
dp[i] = 0;
|
||||
return dp;
|
||||
}
|
||||
|
||||
int numTrees(int n){
|
||||
//开辟dp数组
|
||||
int *dp = initDP(n);
|
||||
//将dp[0]设为1
|
||||
dp[0] = 1;
|
||||
|
||||
int i, j;
|
||||
for(i = 1; i <= n; ++i) {
|
||||
for(j = 1; j <= i; ++j) {
|
||||
//递推公式:dp[i] = dp[i] + 根为j时左子树种类个数 * 根为j时右子树种类个数
|
||||
dp[i] += dp[j - 1] * dp[i - j];
|
||||
}
|
||||
}
|
||||
|
||||
return dp[n];
|
||||
}
|
||||
```
|
||||
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
||||
@@ -574,6 +574,75 @@ var isSymmetric = function(root) {
|
||||
};
|
||||
```
|
||||
|
||||
## TypeScript:
|
||||
|
||||
> 递归法
|
||||
|
||||
```typescript
|
||||
function isSymmetric(root: TreeNode | null): boolean {
|
||||
function recur(node1: TreeNode | null, node2: TreeNode | null): boolean {
|
||||
if (node1 === null && node2 === null) return true;
|
||||
if (node1 === null || node2 === null) return false;
|
||||
if (node1.val !== node2.val) return false
|
||||
let isSym1: boolean = recur(node1.left, node2.right);
|
||||
let isSym2: boolean = recur(node1.right, node2.left);
|
||||
return isSym1 && isSym2
|
||||
}
|
||||
if (root === null) return true;
|
||||
return recur(root.left, root.right);
|
||||
};
|
||||
```
|
||||
|
||||
> 迭代法
|
||||
|
||||
```typescript
|
||||
// 迭代法(队列)
|
||||
function isSymmetric(root: TreeNode | null): boolean {
|
||||
let helperQueue: (TreeNode | null)[] = [];
|
||||
let tempNode1: TreeNode | null,
|
||||
tempNode2: TreeNode | null;
|
||||
if (root !== null) {
|
||||
helperQueue.push(root.left);
|
||||
helperQueue.push(root.right);
|
||||
}
|
||||
while (helperQueue.length > 0) {
|
||||
tempNode1 = helperQueue.shift()!;
|
||||
tempNode2 = helperQueue.shift()!;
|
||||
if (tempNode1 === null && tempNode2 === null) continue;
|
||||
if (tempNode1 === null || tempNode2 === null) return false;
|
||||
if (tempNode1.val !== tempNode2.val) return false;
|
||||
helperQueue.push(tempNode1.left);
|
||||
helperQueue.push(tempNode2.right);
|
||||
helperQueue.push(tempNode1.right);
|
||||
helperQueue.push(tempNode2.left);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// 迭代法(栈)
|
||||
function isSymmetric(root: TreeNode | null): boolean {
|
||||
let helperStack: (TreeNode | null)[] = [];
|
||||
let tempNode1: TreeNode | null,
|
||||
tempNode2: TreeNode | null;
|
||||
if (root !== null) {
|
||||
helperStack.push(root.left);
|
||||
helperStack.push(root.right);
|
||||
}
|
||||
while (helperStack.length > 0) {
|
||||
tempNode1 = helperStack.pop()!;
|
||||
tempNode2 = helperStack.pop()!;
|
||||
if (tempNode1 === null && tempNode2 === null) continue;
|
||||
if (tempNode1 === null || tempNode2 === null) return false;
|
||||
if (tempNode1.val !== tempNode2.val) return false;
|
||||
helperStack.push(tempNode1.left);
|
||||
helperStack.push(tempNode2.right);
|
||||
helperStack.push(tempNode1.right);
|
||||
helperStack.push(tempNode2.left);
|
||||
}
|
||||
return true;
|
||||
};
|
||||
```
|
||||
|
||||
## Swift:
|
||||
|
||||
> 递归
|
||||
|
||||
@@ -83,10 +83,10 @@ public:
|
||||
};
|
||||
```
|
||||
|
||||
python代码:
|
||||
python3代码:
|
||||
|
||||
|
||||
```python3
|
||||
```python
|
||||
|
||||
class Solution:
|
||||
"""二叉树层序遍历迭代解法"""
|
||||
@@ -246,7 +246,35 @@ var levelOrder = function(root) {
|
||||
|
||||
```
|
||||
|
||||
TypeScript:
|
||||
|
||||
```typescript
|
||||
function levelOrder(root: TreeNode | null): number[][] {
|
||||
let helperQueue: TreeNode[] = [];
|
||||
let res: number[][] = [];
|
||||
let tempArr: number[] = [];
|
||||
if (root !== null) helperQueue.push(root);
|
||||
let curNode: TreeNode;
|
||||
while (helperQueue.length > 0) {
|
||||
for (let i = 0, length = helperQueue.length; i < length; i++) {
|
||||
curNode = helperQueue.shift()!;
|
||||
tempArr.push(curNode.val);
|
||||
if (curNode.left !== null) {
|
||||
helperQueue.push(curNode.left);
|
||||
}
|
||||
if (curNode.right !== null) {
|
||||
helperQueue.push(curNode.right);
|
||||
}
|
||||
}
|
||||
res.push(tempArr);
|
||||
tempArr = [];
|
||||
}
|
||||
return res;
|
||||
};
|
||||
```
|
||||
|
||||
Swift:
|
||||
|
||||
```swift
|
||||
func levelOrder(_ root: TreeNode?) -> [[Int]] {
|
||||
var res = [[Int]]()
|
||||
@@ -454,7 +482,31 @@ var levelOrderBottom = function(root) {
|
||||
};
|
||||
```
|
||||
|
||||
TypeScript:
|
||||
|
||||
```typescript
|
||||
function levelOrderBottom(root: TreeNode | null): number[][] {
|
||||
let helperQueue: TreeNode[] = [];
|
||||
let resArr: number[][] = [];
|
||||
let tempArr: number[] = [];
|
||||
let tempNode: TreeNode;
|
||||
if (root !== null) helperQueue.push(root);
|
||||
while (helperQueue.length > 0) {
|
||||
for (let i = 0, length = helperQueue.length; i < length; i++) {
|
||||
tempNode = helperQueue.shift()!;
|
||||
tempArr.push(tempNode.val);
|
||||
if (tempNode.left !== null) helperQueue.push(tempNode.left);
|
||||
if (tempNode.right !== null) helperQueue.push(tempNode.right);
|
||||
}
|
||||
resArr.push(tempArr);
|
||||
tempArr = [];
|
||||
}
|
||||
return resArr.reverse();
|
||||
};
|
||||
```
|
||||
|
||||
Swift:
|
||||
|
||||
```swift
|
||||
func levelOrderBottom(_ root: TreeNode?) -> [[Int]] {
|
||||
var res = [[Int]]()
|
||||
@@ -657,7 +709,28 @@ var rightSideView = function(root) {
|
||||
};
|
||||
```
|
||||
|
||||
TypeScript:
|
||||
|
||||
```typescript
|
||||
function rightSideView(root: TreeNode | null): number[] {
|
||||
let helperQueue: TreeNode[] = [];
|
||||
let resArr: number[] = [];
|
||||
let tempNode: TreeNode;
|
||||
if (root !== null) helperQueue.push(root);
|
||||
while (helperQueue.length > 0) {
|
||||
for (let i = 0, length = helperQueue.length; i < length; i++) {
|
||||
tempNode = helperQueue.shift()!;
|
||||
if (i === length - 1) resArr.push(tempNode.val);
|
||||
if (tempNode.left !== null) helperQueue.push(tempNode.left);
|
||||
if (tempNode.right !== null) helperQueue.push(tempNode.right);
|
||||
}
|
||||
}
|
||||
return resArr;
|
||||
};
|
||||
```
|
||||
|
||||
Swift:
|
||||
|
||||
```swift
|
||||
func rightSideView(_ root: TreeNode?) -> [Int] {
|
||||
var res = [Int]()
|
||||
@@ -868,7 +941,32 @@ var averageOfLevels = function(root) {
|
||||
};
|
||||
```
|
||||
|
||||
TypeScript:
|
||||
|
||||
```typescript
|
||||
function averageOfLevels(root: TreeNode | null): number[] {
|
||||
let helperQueue: TreeNode[] = [];
|
||||
let resArr: number[] = [];
|
||||
let total: number = 0;
|
||||
let tempNode: TreeNode;
|
||||
if (root !== null) helperQueue.push(root);
|
||||
while (helperQueue.length > 0) {
|
||||
let length = helperQueue.length;
|
||||
for (let i = 0; i < length; i++) {
|
||||
tempNode = helperQueue.shift()!;
|
||||
total += tempNode.val;
|
||||
if (tempNode.left) helperQueue.push(tempNode.left);
|
||||
if (tempNode.right) helperQueue.push(tempNode.right);
|
||||
}
|
||||
resArr.push(total / length);
|
||||
total = 0;
|
||||
}
|
||||
return resArr;
|
||||
};
|
||||
```
|
||||
|
||||
Swift:
|
||||
|
||||
```swift
|
||||
func averageOfLevels(_ root: TreeNode?) -> [Double] {
|
||||
var res = [Double]()
|
||||
@@ -1092,7 +1190,30 @@ var levelOrder = function(root) {
|
||||
};
|
||||
```
|
||||
|
||||
TypeScript:
|
||||
|
||||
```typescript
|
||||
function levelOrder(root: Node | null): number[][] {
|
||||
let helperQueue: Node[] = [];
|
||||
let resArr: number[][] = [];
|
||||
let tempArr: number[] = [];
|
||||
if (root !== null) helperQueue.push(root);
|
||||
let curNode: Node;
|
||||
while (helperQueue.length > 0) {
|
||||
for (let i = 0, length = helperQueue.length; i < length; i++) {
|
||||
curNode = helperQueue.shift()!;
|
||||
tempArr.push(curNode.val);
|
||||
helperQueue.push(...curNode.children);
|
||||
}
|
||||
resArr.push(tempArr);
|
||||
tempArr = [];
|
||||
}
|
||||
return resArr;
|
||||
};
|
||||
```
|
||||
|
||||
Swift:
|
||||
|
||||
```swift
|
||||
func levelOrder(_ root: Node?) -> [[Int]] {
|
||||
var res = [[Int]]()
|
||||
@@ -1272,7 +1393,34 @@ var largestValues = function(root) {
|
||||
};
|
||||
```
|
||||
|
||||
TypeScript:
|
||||
|
||||
```typescript
|
||||
function largestValues(root: TreeNode | null): number[] {
|
||||
let helperQueue: TreeNode[] = [];
|
||||
let resArr: number[] = [];
|
||||
let tempNode: TreeNode;
|
||||
let max: number = 0;
|
||||
if (root !== null) helperQueue.push(root);
|
||||
while (helperQueue.length > 0) {
|
||||
for (let i = 0, length = helperQueue.length; i < length; i++) {
|
||||
tempNode = helperQueue.shift()!;
|
||||
if (i === 0) {
|
||||
max = tempNode.val;
|
||||
} else {
|
||||
max = max > tempNode.val ? max : tempNode.val;
|
||||
}
|
||||
if (tempNode.left) helperQueue.push(tempNode.left);
|
||||
if (tempNode.right) helperQueue.push(tempNode.right);
|
||||
}
|
||||
resArr.push(max);
|
||||
}
|
||||
return resArr;
|
||||
};
|
||||
```
|
||||
|
||||
Swift:
|
||||
|
||||
```swift
|
||||
func largestValues(_ root: TreeNode?) -> [Int] {
|
||||
var res = [Int]()
|
||||
@@ -1463,6 +1611,31 @@ var connect = function(root) {
|
||||
};
|
||||
|
||||
```
|
||||
TypeScript:
|
||||
|
||||
```typescript
|
||||
function connect(root: Node | null): Node | null {
|
||||
let helperQueue: Node[] = [];
|
||||
let preNode: Node, curNode: Node;
|
||||
if (root !== null) helperQueue.push(root);
|
||||
while (helperQueue.length > 0) {
|
||||
for (let i = 0, length = helperQueue.length; i < length; i++) {
|
||||
if (i === 0) {
|
||||
preNode = helperQueue.shift()!;
|
||||
} else {
|
||||
curNode = helperQueue.shift()!;
|
||||
preNode.next = curNode;
|
||||
preNode = curNode;
|
||||
}
|
||||
if (preNode.left) helperQueue.push(preNode.left);
|
||||
if (preNode.right) helperQueue.push(preNode.right);
|
||||
}
|
||||
preNode.next = null;
|
||||
}
|
||||
return root;
|
||||
};
|
||||
```
|
||||
|
||||
go:
|
||||
|
||||
```GO
|
||||
@@ -1689,6 +1862,31 @@ var connect = function(root) {
|
||||
return root;
|
||||
};
|
||||
```
|
||||
TypeScript:
|
||||
|
||||
```typescript
|
||||
function connect(root: Node | null): Node | null {
|
||||
let helperQueue: Node[] = [];
|
||||
let preNode: Node, curNode: Node;
|
||||
if (root !== null) helperQueue.push(root);
|
||||
while (helperQueue.length > 0) {
|
||||
for (let i = 0, length = helperQueue.length; i < length; i++) {
|
||||
if (i === 0) {
|
||||
preNode = helperQueue.shift()!;
|
||||
} else {
|
||||
curNode = helperQueue.shift()!;
|
||||
preNode.next = curNode;
|
||||
preNode = curNode;
|
||||
}
|
||||
if (preNode.left) helperQueue.push(preNode.left);
|
||||
if (preNode.right) helperQueue.push(preNode.right);
|
||||
}
|
||||
preNode.next = null;
|
||||
}
|
||||
return root;
|
||||
};
|
||||
```
|
||||
|
||||
go:
|
||||
|
||||
```GO
|
||||
@@ -1933,7 +2131,28 @@ var maxDepth = function(root) {
|
||||
};
|
||||
```
|
||||
|
||||
TypeScript:
|
||||
|
||||
```typescript
|
||||
function maxDepth(root: TreeNode | null): number {
|
||||
let helperQueue: TreeNode[] = [];
|
||||
let resDepth: number = 0;
|
||||
let tempNode: TreeNode;
|
||||
if (root !== null) helperQueue.push(root);
|
||||
while (helperQueue.length > 0) {
|
||||
resDepth++;
|
||||
for (let i = 0, length = helperQueue.length; i < length; i++) {
|
||||
tempNode = helperQueue.shift()!;
|
||||
if (tempNode.left) helperQueue.push(tempNode.left);
|
||||
if (tempNode.right) helperQueue.push(tempNode.right);
|
||||
}
|
||||
}
|
||||
return resDepth;
|
||||
};
|
||||
```
|
||||
|
||||
Swift:
|
||||
|
||||
```swift
|
||||
func maxDepth(_ root: TreeNode?) -> Int {
|
||||
guard let root = root else {
|
||||
@@ -2130,7 +2349,29 @@ var minDepth = function(root) {
|
||||
};
|
||||
```
|
||||
|
||||
TypeScript:
|
||||
|
||||
```typescript
|
||||
function minDepth(root: TreeNode | null): number {
|
||||
let helperQueue: TreeNode[] = [];
|
||||
let resMin: number = 0;
|
||||
let tempNode: TreeNode;
|
||||
if (root !== null) helperQueue.push(root);
|
||||
while (helperQueue.length > 0) {
|
||||
resMin++;
|
||||
for (let i = 0, length = helperQueue.length; i < length; i++) {
|
||||
tempNode = helperQueue.shift()!;
|
||||
if (tempNode.left === null && tempNode.right === null) return resMin;
|
||||
if (tempNode.left !== null) helperQueue.push(tempNode.left);
|
||||
if (tempNode.right !== null) helperQueue.push(tempNode.right);
|
||||
}
|
||||
}
|
||||
return resMin;
|
||||
};
|
||||
```
|
||||
|
||||
Swift:
|
||||
|
||||
```swift
|
||||
func minDepth(_ root: TreeNode?) -> Int {
|
||||
guard let root = root else {
|
||||
|
||||
@@ -523,8 +523,8 @@ func maxdepth(root *treenode) int {
|
||||
|
||||
```javascript
|
||||
var maxdepth = function(root) {
|
||||
if (!root) return root
|
||||
return 1 + math.max(maxdepth(root.left), maxdepth(root.right))
|
||||
if (root === null) return 0;
|
||||
return 1 + Math.max(maxdepth(root.left), maxdepth(root.right))
|
||||
};
|
||||
```
|
||||
|
||||
@@ -541,7 +541,7 @@ var maxdepth = function(root) {
|
||||
//3. 确定单层逻辑
|
||||
let leftdepth=getdepth(node.left);
|
||||
let rightdepth=getdepth(node.right);
|
||||
let depth=1+math.max(leftdepth,rightdepth);
|
||||
let depth=1+Math.max(leftdepth,rightdepth);
|
||||
return depth;
|
||||
}
|
||||
return getdepth(root);
|
||||
@@ -591,14 +591,90 @@ var maxDepth = function(root) {
|
||||
count++
|
||||
while(size--) {
|
||||
let node = queue.shift()
|
||||
node && (queue = [...queue, ...node.children])
|
||||
for (let item of node.children) {
|
||||
item && queue.push(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
return count
|
||||
};
|
||||
```
|
||||
|
||||
## TypeScript:
|
||||
|
||||
> 二叉树的最大深度:
|
||||
|
||||
```typescript
|
||||
// 后续遍历(自下而上)
|
||||
function maxDepth(root: TreeNode | null): number {
|
||||
if (root === null) return 0;
|
||||
return Math.max(maxDepth(root.left), maxDepth(root.right)) + 1;
|
||||
};
|
||||
|
||||
// 前序遍历(自上而下)
|
||||
function maxDepth(root: TreeNode | null): number {
|
||||
function recur(node: TreeNode | null, count: number) {
|
||||
if (node === null) {
|
||||
resMax = resMax > count ? resMax : count;
|
||||
return;
|
||||
}
|
||||
recur(node.left, count + 1);
|
||||
recur(node.right, count + 1);
|
||||
}
|
||||
let resMax: number = 0;
|
||||
let count: number = 0;
|
||||
recur(root, count);
|
||||
return resMax;
|
||||
};
|
||||
|
||||
// 层序遍历(迭代法)
|
||||
function maxDepth(root: TreeNode | null): number {
|
||||
let helperQueue: TreeNode[] = [];
|
||||
let resDepth: number = 0;
|
||||
let tempNode: TreeNode;
|
||||
if (root !== null) helperQueue.push(root);
|
||||
while (helperQueue.length > 0) {
|
||||
resDepth++;
|
||||
for (let i = 0, length = helperQueue.length; i < length; i++) {
|
||||
tempNode = helperQueue.shift()!;
|
||||
if (tempNode.left) helperQueue.push(tempNode.left);
|
||||
if (tempNode.right) helperQueue.push(tempNode.right);
|
||||
}
|
||||
}
|
||||
return resDepth;
|
||||
};
|
||||
```
|
||||
|
||||
> N叉树的最大深度
|
||||
|
||||
```typescript
|
||||
// 后续遍历(自下而上)
|
||||
function maxDepth(root: TreeNode | null): number {
|
||||
if (root === null) return 0;
|
||||
return Math.max(maxDepth(root.left), maxDepth(root.right)) + 1;
|
||||
};
|
||||
|
||||
// 前序遍历(自上而下)
|
||||
function maxDepth(root: TreeNode | null): number {
|
||||
function recur(node: TreeNode | null, count: number) {
|
||||
if (node === null) {
|
||||
resMax = resMax > count ? resMax : count;
|
||||
return;
|
||||
}
|
||||
recur(node.left, count + 1);
|
||||
recur(node.right, count + 1);
|
||||
}
|
||||
let resMax: number = 0;
|
||||
let count: number = 0;
|
||||
recur(root, count);
|
||||
return resMax;
|
||||
};
|
||||
|
||||
|
||||
```
|
||||
|
||||
## C
|
||||
|
||||
二叉树最大深度递归
|
||||
```c
|
||||
int maxDepth(struct TreeNode* root){
|
||||
|
||||
@@ -305,7 +305,7 @@ class Solution {
|
||||
## Python
|
||||
**递归**
|
||||
|
||||
```python3
|
||||
```python
|
||||
# Definition for a binary tree node.
|
||||
# class TreeNode:
|
||||
# def __init__(self, val=0, left=None, right=None):
|
||||
|
||||
@@ -497,7 +497,7 @@ class Solution {
|
||||
## Python
|
||||
|
||||
递归法:
|
||||
```python3
|
||||
```python
|
||||
# Definition for a binary tree node.
|
||||
# class TreeNode:
|
||||
# def __init__(self, val=0, left=None, right=None):
|
||||
@@ -604,7 +604,8 @@ func abs(a int)int{
|
||||
}
|
||||
```
|
||||
|
||||
## JavaScript
|
||||
## JavaScript
|
||||
递归法:
|
||||
```javascript
|
||||
var isBalanced = function(root) {
|
||||
//还是用递归三部曲 + 后序遍历 左右中 当前左子树右子树高度相差大于1就返回-1
|
||||
@@ -614,8 +615,10 @@ var isBalanced = function(root) {
|
||||
if(node === null) return 0;
|
||||
// 3. 确定单层递归逻辑
|
||||
let leftDepth = getDepth(node.left); //左子树高度
|
||||
let rightDepth = getDepth(node.right); //右子树高度
|
||||
// 当判定左子树不为平衡二叉树时,即可直接返回-1
|
||||
if(leftDepth === -1) return -1;
|
||||
let rightDepth = getDepth(node.right); //右子树高度
|
||||
// 当判定右子树不为平衡二叉树时,即可直接返回-1
|
||||
if(rightDepth === -1) return -1;
|
||||
if(Math.abs(leftDepth - rightDepth) > 1) {
|
||||
return -1;
|
||||
@@ -627,7 +630,68 @@ var isBalanced = function(root) {
|
||||
};
|
||||
```
|
||||
|
||||
迭代法:
|
||||
```javascript
|
||||
// 获取当前节点的高度
|
||||
var getHeight = function (curNode) {
|
||||
let queue = [];
|
||||
if (curNode !== null) queue.push(curNode); // 压入当前元素
|
||||
let depth = 0, res = 0;
|
||||
while (queue.length) {
|
||||
let node = queue[queue.length - 1]; // 取出栈顶
|
||||
if (node !== null) {
|
||||
queue.pop();
|
||||
queue.push(node); // 中
|
||||
queue.push(null);
|
||||
depth++;
|
||||
node.right && queue.push(node.right); // 右
|
||||
node.left && queue.push(node.left); // 左
|
||||
} else {
|
||||
queue.pop();
|
||||
node = queue[queue.length - 1];
|
||||
queue.pop();
|
||||
depth--;
|
||||
}
|
||||
res = res > depth ? res : depth;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
var isBalanced = function (root) {
|
||||
if (root === null) return true;
|
||||
let queue = [root];
|
||||
while (queue.length) {
|
||||
let node = queue[queue.length - 1]; // 取出栈顶
|
||||
queue.pop();
|
||||
if (Math.abs(getHeight(node.left) - getHeight(node.right)) > 1) {
|
||||
return false;
|
||||
}
|
||||
node.right && queue.push(node.right);
|
||||
node.left && queue.push(node.left);
|
||||
}
|
||||
return true;
|
||||
};
|
||||
```
|
||||
|
||||
## TypeScript
|
||||
|
||||
```typescript
|
||||
// 递归法
|
||||
function isBalanced(root: TreeNode | null): boolean {
|
||||
function getDepth(root: TreeNode | null): number {
|
||||
if (root === null) return 0;
|
||||
let leftDepth: number = getDepth(root.left);
|
||||
if (leftDepth === -1) return -1;
|
||||
let rightDepth: number = getDepth(root.right);
|
||||
if (rightDepth === -1) return -1;
|
||||
if (Math.abs(leftDepth - rightDepth) > 1) return -1;
|
||||
return 1 + Math.max(leftDepth, rightDepth);
|
||||
}
|
||||
return getDepth(root) !== -1;
|
||||
};
|
||||
```
|
||||
|
||||
## C
|
||||
|
||||
递归法:
|
||||
```c
|
||||
int getDepth(struct TreeNode* node) {
|
||||
|
||||
@@ -404,6 +404,44 @@ var minDepth = function(root) {
|
||||
};
|
||||
```
|
||||
|
||||
## TypeScript
|
||||
|
||||
> 递归法
|
||||
|
||||
```typescript
|
||||
function minDepth(root: TreeNode | null): number {
|
||||
if (root === null) return 0;
|
||||
if (root.left !== null && root.right === null) {
|
||||
return 1 + minDepth(root.left);
|
||||
}
|
||||
if (root.left === null && root.right !== null) {
|
||||
return 1 + minDepth(root.right);
|
||||
}
|
||||
return 1 + Math.min(minDepth(root.left), minDepth(root.right));
|
||||
}
|
||||
```
|
||||
|
||||
> 迭代法
|
||||
|
||||
```typescript
|
||||
function minDepth(root: TreeNode | null): number {
|
||||
let helperQueue: TreeNode[] = [];
|
||||
let resMin: number = 0;
|
||||
let tempNode: TreeNode;
|
||||
if (root !== null) helperQueue.push(root);
|
||||
while (helperQueue.length > 0) {
|
||||
resMin++;
|
||||
for (let i = 0, length = helperQueue.length; i < length; i++) {
|
||||
tempNode = helperQueue.shift()!;
|
||||
if (tempNode.left === null && tempNode.right === null) return resMin;
|
||||
if (tempNode.left !== null) helperQueue.push(tempNode.left);
|
||||
if (tempNode.right !== null) helperQueue.push(tempNode.right);
|
||||
}
|
||||
}
|
||||
return resMin;
|
||||
};
|
||||
```
|
||||
|
||||
## Swift
|
||||
|
||||
> 递归
|
||||
|
||||
@@ -531,82 +531,63 @@ class solution:
|
||||
```go
|
||||
//递归法
|
||||
/**
|
||||
* definition for a binary tree node.
|
||||
* type treenode struct {
|
||||
* val int
|
||||
* left *treenode
|
||||
* right *treenode
|
||||
* Definition for a binary tree node.
|
||||
* type TreeNode struct {
|
||||
* Val int
|
||||
* Left *TreeNode
|
||||
* Right *TreeNode
|
||||
* }
|
||||
*/
|
||||
func haspathsum(root *treenode, targetsum int) bool {
|
||||
var flage bool //找没找到的标志
|
||||
if root==nil{
|
||||
return flage
|
||||
func hasPathSum(root *TreeNode, targetSum int) bool {
|
||||
if root == nil {
|
||||
return false
|
||||
}
|
||||
pathsum(root,0,targetsum,&flage)
|
||||
return flage
|
||||
}
|
||||
func pathsum(root *treenode, sum int,targetsum int,flage *bool){
|
||||
sum+=root.val
|
||||
if root.left==nil&&root.right==nil&&sum==targetsum{
|
||||
*flage=true
|
||||
return
|
||||
}
|
||||
if root.left!=nil&&!(*flage){//左节点不为空且还没找到
|
||||
pathsum(root.left,sum,targetsum,flage)
|
||||
}
|
||||
if root.right!=nil&&!(*flage){//右节点不为空且没找到
|
||||
pathsum(root.right,sum,targetsum,flage)
|
||||
|
||||
targetSum -= root.Val // 将targetSum在遍历每层的时候都减去本层节点的值
|
||||
if root.Left == nil && root.Right == nil && targetSum == 0 { // 如果剩余的targetSum为0, 则正好就是符合的结果
|
||||
return true
|
||||
}
|
||||
return hasPathSum(root.Left, targetSum) || hasPathSum(root.Right, targetSum) // 否则递归找
|
||||
}
|
||||
```
|
||||
|
||||
113 递归法
|
||||
113. 路径总和 II
|
||||
|
||||
```go
|
||||
/**
|
||||
* definition for a binary tree node.
|
||||
* type treenode struct {
|
||||
* val int
|
||||
* left *treenode
|
||||
* right *treenode
|
||||
* Definition for a binary tree node.
|
||||
* type TreeNode struct {
|
||||
* Val int
|
||||
* Left *TreeNode
|
||||
* Right *TreeNode
|
||||
* }
|
||||
*/
|
||||
func pathsum(root *treenode, targetsum int) [][]int {
|
||||
var result [][]int//最终结果
|
||||
if root==nil{
|
||||
return result
|
||||
}
|
||||
var sumnodes []int//经过路径的节点集合
|
||||
haspathsum(root,&sumnodes,targetsum,&result)
|
||||
func pathSum(root *TreeNode, targetSum int) [][]int {
|
||||
result := make([][]int, 0)
|
||||
traverse(root, &result, new([]int), targetSum)
|
||||
return result
|
||||
}
|
||||
func haspathsum(root *treenode,sumnodes *[]int,targetsum int,result *[][]int){
|
||||
*sumnodes=append(*sumnodes,root.val)
|
||||
if root.left==nil&&root.right==nil{//叶子节点
|
||||
fmt.println(*sumnodes)
|
||||
var sum int
|
||||
var number int
|
||||
for k,v:=range *sumnodes{//求该路径节点的和
|
||||
sum+=v
|
||||
number=k
|
||||
}
|
||||
tempnodes:=make([]int,number+1)//新的nodes接受指针里的值,防止最终指针里的值发生变动,导致最后的结果都是最后一个sumnodes的值
|
||||
for k,v:=range *sumnodes{
|
||||
tempnodes[k]=v
|
||||
}
|
||||
if sum==targetsum{
|
||||
*result=append(*result,tempnodes)
|
||||
}
|
||||
|
||||
func traverse(node *TreeNode, result *[][]int, currPath *[]int, targetSum int) {
|
||||
if node == nil { // 这个判空也可以挪到递归遍历左右子树时去判断
|
||||
return
|
||||
}
|
||||
if root.left!=nil{
|
||||
haspathsum(root.left,sumnodes,targetsum,result)
|
||||
*sumnodes=(*sumnodes)[:len(*sumnodes)-1]//回溯
|
||||
}
|
||||
if root.right!=nil{
|
||||
haspathsum(root.right,sumnodes,targetsum,result)
|
||||
*sumnodes=(*sumnodes)[:len(*sumnodes)-1]//回溯
|
||||
|
||||
targetSum -= node.Val // 将targetSum在遍历每层的时候都减去本层节点的值
|
||||
*currPath = append(*currPath, node.Val) // 把当前节点放到路径记录里
|
||||
|
||||
if node.Left == nil && node.Right == nil && targetSum == 0 { // 如果剩余的targetSum为0, 则正好就是符合的结果
|
||||
// 不能直接将currPath放到result里面, 因为currPath是共享的, 每次遍历子树时都会被修改
|
||||
pathCopy := make([]int, len(*currPath))
|
||||
for i, element := range *currPath {
|
||||
pathCopy[i] = element
|
||||
}
|
||||
*result = append(*result, pathCopy) // 将副本放到结果集里
|
||||
}
|
||||
|
||||
traverse(node.Left, result, currPath, targetSum)
|
||||
traverse(node.Right, result, currPath, targetSum)
|
||||
*currPath = (*currPath)[:len(*currPath)-1] // 当前节点遍历完成, 从路径记录里删除掉
|
||||
}
|
||||
```
|
||||
|
||||
@@ -766,7 +747,245 @@ let pathSum = function(root, targetSum) {
|
||||
};
|
||||
```
|
||||
|
||||
## TypeScript
|
||||
|
||||
> 0112.路径总和
|
||||
|
||||
**递归法:**
|
||||
|
||||
```typescript
|
||||
function hasPathSum(root: TreeNode | null, targetSum: number): boolean {
|
||||
function recur(node: TreeNode, sum: number): boolean {
|
||||
console.log(sum);
|
||||
if (
|
||||
node.left === null &&
|
||||
node.right === null &&
|
||||
sum === 0
|
||||
) return true;
|
||||
if (node.left !== null) {
|
||||
sum -= node.left.val;
|
||||
if (recur(node.left, sum) === true) return true;
|
||||
sum += node.left.val;
|
||||
}
|
||||
if (node.right !== null) {
|
||||
sum -= node.right.val;
|
||||
if (recur(node.right, sum) === true) return true;
|
||||
sum += node.right.val;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (root === null) return false;
|
||||
return recur(root, targetSum - root.val);
|
||||
};
|
||||
```
|
||||
|
||||
**递归法(精简版):**
|
||||
|
||||
```typescript
|
||||
function hasPathSum(root: TreeNode | null, targetSum: number): boolean {
|
||||
if (root === null) return false;
|
||||
targetSum -= root.val;
|
||||
if (
|
||||
root.left === null &&
|
||||
root.right === null &&
|
||||
targetSum === 0
|
||||
) return true;
|
||||
return hasPathSum(root.left, targetSum) ||
|
||||
hasPathSum(root.right, targetSum);
|
||||
};
|
||||
```
|
||||
|
||||
**迭代法:**
|
||||
|
||||
```typescript
|
||||
function hasPathSum(root: TreeNode | null, targetSum: number): boolean {
|
||||
type Pair = {
|
||||
node: TreeNode, // 当前节点
|
||||
sum: number // 根节点到当前节点的路径数值总和
|
||||
}
|
||||
|
||||
const helperStack: Pair[] = [];
|
||||
if (root !== null) helperStack.push({ node: root, sum: root.val });
|
||||
let tempPair: Pair;
|
||||
while (helperStack.length > 0) {
|
||||
tempPair = helperStack.pop()!;
|
||||
if (
|
||||
tempPair.node.left === null &&
|
||||
tempPair.node.right === null &&
|
||||
tempPair.sum === targetSum
|
||||
) return true;
|
||||
if (tempPair.node.right !== null) {
|
||||
helperStack.push({
|
||||
node: tempPair.node.right,
|
||||
sum: tempPair.sum + tempPair.node.right.val
|
||||
});
|
||||
}
|
||||
if (tempPair.node.left !== null) {
|
||||
helperStack.push({
|
||||
node: tempPair.node.left,
|
||||
sum: tempPair.sum + tempPair.node.left.val
|
||||
});
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
```
|
||||
|
||||
> 0112.路径总和 ii
|
||||
|
||||
**递归法:**
|
||||
|
||||
```typescript
|
||||
function pathSum(root: TreeNode | null, targetSum: number): number[][] {
|
||||
function recur(node: TreeNode, sumGap: number, routeArr: number[]): void {
|
||||
if (
|
||||
node.left === null &&
|
||||
node.right === null &&
|
||||
sumGap === 0
|
||||
) resArr.push([...routeArr]);
|
||||
if (node.left !== null) {
|
||||
sumGap -= node.left.val;
|
||||
routeArr.push(node.left.val);
|
||||
recur(node.left, sumGap, routeArr);
|
||||
sumGap += node.left.val;
|
||||
routeArr.pop();
|
||||
}
|
||||
if (node.right !== null) {
|
||||
sumGap -= node.right.val;
|
||||
routeArr.push(node.right.val);
|
||||
recur(node.right, sumGap, routeArr);
|
||||
sumGap += node.right.val;
|
||||
routeArr.pop();
|
||||
}
|
||||
}
|
||||
const resArr: number[][] = [];
|
||||
if (root === null) return resArr;
|
||||
const routeArr: number[] = [];
|
||||
routeArr.push(root.val);
|
||||
recur(root, targetSum - root.val, routeArr);
|
||||
return resArr;
|
||||
};
|
||||
```
|
||||
|
||||
## Swift
|
||||
|
||||
0112.路径总和
|
||||
|
||||
**递归**
|
||||
|
||||
```swift
|
||||
func hasPathSum(_ root: TreeNode?, _ targetSum: Int) -> Bool {
|
||||
guard let root = root else {
|
||||
return false
|
||||
}
|
||||
|
||||
return traversal(root, targetSum - root.val)
|
||||
}
|
||||
|
||||
func traversal(_ cur: TreeNode?, _ count: Int) -> Bool {
|
||||
if cur?.left == nil && cur?.right == nil && count == 0 {
|
||||
return true
|
||||
}
|
||||
|
||||
if cur?.left == nil && cur?.right == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
if let leftNode = cur?.left {
|
||||
if traversal(leftNode, count - leftNode.val) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
if let rightNode = cur?.right {
|
||||
if traversal(rightNode, count - rightNode.val) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
```
|
||||
**迭代**
|
||||
```swift
|
||||
func hasPathSum(_ root: TreeNode?, _ targetSum: Int) -> Bool {
|
||||
guard let root = root else {
|
||||
return false
|
||||
}
|
||||
|
||||
var stack = Array<(TreeNode, Int)>()
|
||||
stack.append((root, root.val))
|
||||
|
||||
while !stack.isEmpty {
|
||||
let node = stack.removeLast()
|
||||
|
||||
if node.0.left == nil && node.0.right == nil && targetSum == node.1 {
|
||||
return true
|
||||
}
|
||||
|
||||
if let rightNode = node.0.right {
|
||||
stack.append((rightNode, node.1 + rightNode.val))
|
||||
}
|
||||
|
||||
if let leftNode = node.0.left {
|
||||
stack.append((leftNode, node.1 + leftNode.val))
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
```
|
||||
|
||||
0113.路径总和 II
|
||||
|
||||
**递归**
|
||||
|
||||
```swift
|
||||
var result = [[Int]]()
|
||||
var path = [Int]()
|
||||
func pathSum(_ root: TreeNode?, _ targetSum: Int) -> [[Int]] {
|
||||
result.removeAll()
|
||||
path.removeAll()
|
||||
guard let root = root else {
|
||||
return result
|
||||
}
|
||||
path.append(root.val)
|
||||
traversal(root, count: targetSum - root.val)
|
||||
return result
|
||||
|
||||
}
|
||||
|
||||
func traversal(_ cur: TreeNode?, count: Int) {
|
||||
var count = count
|
||||
// 遇到了叶子节点且找到了和为targetSum的路径
|
||||
if cur?.left == nil && cur?.right == nil && count == 0 {
|
||||
result.append(path)
|
||||
return
|
||||
}
|
||||
|
||||
// 遇到叶子节点而没有找到合适的边,直接返回
|
||||
if cur?.left == nil && cur?.right == nil{
|
||||
return
|
||||
}
|
||||
|
||||
if let leftNode = cur?.left {
|
||||
path.append(leftNode.val)
|
||||
count -= leftNode.val
|
||||
traversal(leftNode, count: count)// 递归
|
||||
count += leftNode.val// 回溯
|
||||
path.removeLast()// 回溯
|
||||
}
|
||||
|
||||
if let rightNode = cur?.right {
|
||||
path.append(rightNode.val)
|
||||
count -= rightNode.val
|
||||
traversal(rightNode, count: count)// 递归
|
||||
count += rightNode.val// 回溯
|
||||
path.removeLast()// 回溯
|
||||
}
|
||||
return
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -217,7 +217,7 @@ class Solution {
|
||||
```
|
||||
|
||||
Python:
|
||||
```python3
|
||||
```python
|
||||
class Solution:
|
||||
def sumNumbers(self, root: TreeNode) -> int:
|
||||
res = 0
|
||||
@@ -289,7 +289,33 @@ var sumNumbers = function(root) {
|
||||
};
|
||||
```
|
||||
|
||||
C:
|
||||
```c
|
||||
//sum记录总和
|
||||
int sum;
|
||||
void traverse(struct TreeNode *node, int val) {
|
||||
//更新val为根节点到当前节点的和
|
||||
val = val * 10 + node->val;
|
||||
//若当前节点为叶子节点,记录val
|
||||
if(!node->left && !node->right) {
|
||||
sum+=val;
|
||||
return;
|
||||
}
|
||||
//若有左/右节点,遍历左/右节点
|
||||
if(node->left)
|
||||
traverse(node->left, val);
|
||||
if(node->right)
|
||||
traverse(node->right, val);
|
||||
}
|
||||
|
||||
int sumNumbers(struct TreeNode* root){
|
||||
sum = 0;
|
||||
|
||||
traverse(root, 0);
|
||||
|
||||
return sum;
|
||||
}
|
||||
```
|
||||
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
||||
@@ -289,7 +289,7 @@ class Solution {
|
||||
|
||||
## Python
|
||||
**回溯+正反序判断回文串**
|
||||
```python3
|
||||
```python
|
||||
class Solution:
|
||||
def __init__(self):
|
||||
self.paths = []
|
||||
@@ -326,7 +326,7 @@ class Solution:
|
||||
continue
|
||||
```
|
||||
**回溯+函数判断回文串**
|
||||
```python3
|
||||
```python
|
||||
class Solution:
|
||||
def __init__(self):
|
||||
self.paths = []
|
||||
|
||||
@@ -248,6 +248,36 @@ class Solution {
|
||||
return valid[s.length()];
|
||||
}
|
||||
}
|
||||
|
||||
// 回溯法+记忆化
|
||||
class Solution {
|
||||
public boolean wordBreak(String s, List<String> wordDict) {
|
||||
Set<String> wordDictSet = new HashSet(wordDict);
|
||||
int[] memory = new int[s.length()];
|
||||
return backTrack(s, wordDictSet, 0, memory);
|
||||
}
|
||||
|
||||
public boolean backTrack(String s, Set<String> wordDictSet, int startIndex, int[] memory) {
|
||||
// 结束条件
|
||||
if (startIndex >= s.length()) {
|
||||
return true;
|
||||
}
|
||||
if (memory[startIndex] != 0) {
|
||||
// 此处认为:memory[i] = 1 表示可以拼出i 及以后的字符子串, memory[i] = -1 表示不能
|
||||
return memory[startIndex] == 1 ? true : false;
|
||||
}
|
||||
for (int i = startIndex; i < s.length(); ++i) {
|
||||
// 处理 递归 回溯 循环不变量:[startIndex, i + 1)
|
||||
String word = s.substring(startIndex, i + 1);
|
||||
if (wordDictSet.contains(word) && backTrack(s, wordDictSet, i + 1, memory)) {
|
||||
memory[startIndex] = 1;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
memory[startIndex] = -1;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Python:
|
||||
|
||||
@@ -439,7 +439,75 @@ var reorderList = function(head, s = [], tmp) {
|
||||
}
|
||||
```
|
||||
|
||||
### C
|
||||
方法三:反转链表
|
||||
```c
|
||||
//翻转链表
|
||||
struct ListNode *reverseList(struct ListNode *head) {
|
||||
if(!head)
|
||||
return NULL;
|
||||
struct ListNode *preNode = NULL, *curNode = head;
|
||||
while(curNode) {
|
||||
//创建tempNode记录curNode->next(即将被更新)
|
||||
struct ListNode* tempNode = curNode->next;
|
||||
//将curNode->next指向preNode
|
||||
curNode->next = preNode;
|
||||
//更新preNode为curNode
|
||||
preNode = curNode;
|
||||
//curNode更新为原链表中下一个元素
|
||||
curNode = tempNode;
|
||||
}
|
||||
return preNode;
|
||||
}
|
||||
|
||||
void reorderList(struct ListNode* head){
|
||||
//slow用来截取到链表的中间节点(第一个链表的最后节点),每次循环跳一个节点。fast用来辅助,每次循环跳两个节点
|
||||
struct ListNode *fast = head, *slow = head;
|
||||
while(fast && fast->next && fast->next->next) {
|
||||
//fast每次跳两个节点
|
||||
fast = fast->next->next;
|
||||
//slow每次跳一个节点
|
||||
slow = slow->next;
|
||||
}
|
||||
//将slow->next后的节点翻转
|
||||
struct ListNode *sndLst = reverseList(slow->next);
|
||||
//将第一个链表与第二个链表断开
|
||||
slow->next = NULL;
|
||||
//因为插入从curNode->next开始,curNode刚开始已经head。所以fstList要从head->next开始
|
||||
struct ListNode *fstLst = head->next;
|
||||
struct ListNode *curNode = head;
|
||||
|
||||
int count = 0;
|
||||
//当第一个链表和第二个链表中都有节点时循环
|
||||
while(sndLst && fstLst) {
|
||||
//count为奇数,插入fstLst中的节点
|
||||
if(count % 2) {
|
||||
curNode->next = fstLst;
|
||||
fstLst = fstLst->next;
|
||||
}
|
||||
//count为偶数,插入sndList的节点
|
||||
else {
|
||||
curNode->next = sndLst;
|
||||
sndLst = sndLst->next;
|
||||
}
|
||||
//设置下一个节点
|
||||
curNode = curNode->next;
|
||||
//更新count
|
||||
++count;
|
||||
}
|
||||
|
||||
//若两个链表fstList和sndLst中还有节点,将其放入链表
|
||||
if(fstLst) {
|
||||
curNode->next = fstLst;
|
||||
}
|
||||
if(sndLst) {
|
||||
curNode->next = sndLst;
|
||||
}
|
||||
|
||||
//返回链表
|
||||
return head;
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
-----------------------
|
||||
|
||||
@@ -210,6 +210,71 @@ var evalRPN = function(tokens) {
|
||||
};
|
||||
```
|
||||
|
||||
TypeScript:
|
||||
|
||||
普通版:
|
||||
|
||||
```typescript
|
||||
function evalRPN(tokens: string[]): number {
|
||||
let helperStack: number[] = [];
|
||||
let temp: number;
|
||||
let i: number = 0;
|
||||
while (i < tokens.length) {
|
||||
let t: string = tokens[i];
|
||||
switch (t) {
|
||||
case '+':
|
||||
temp = helperStack.pop()! + helperStack.pop()!;
|
||||
helperStack.push(temp);
|
||||
break;
|
||||
case '-':
|
||||
temp = helperStack.pop()!;
|
||||
temp = helperStack.pop()! - temp;
|
||||
helperStack.push(temp);
|
||||
break;
|
||||
case '*':
|
||||
temp = helperStack.pop()! * helperStack.pop()!;
|
||||
helperStack.push(temp);
|
||||
break;
|
||||
case '/':
|
||||
temp = helperStack.pop()!;
|
||||
temp = Math.trunc(helperStack.pop()! / temp);
|
||||
helperStack.push(temp);
|
||||
break;
|
||||
default:
|
||||
helperStack.push(Number(t));
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return helperStack.pop()!;
|
||||
};
|
||||
```
|
||||
|
||||
优化版:
|
||||
|
||||
```typescript
|
||||
function evalRPN(tokens: string[]): number {
|
||||
const helperStack: number[] = [];
|
||||
const operatorMap: Map<string, (a: number, b: number) => number> = new Map([
|
||||
['+', (a, b) => a + b],
|
||||
['-', (a, b) => a - b],
|
||||
['/', (a, b) => Math.trunc(a / b)],
|
||||
['*', (a, b) => a * b],
|
||||
]);
|
||||
let a: number, b: number;
|
||||
for (let t of tokens) {
|
||||
if (operatorMap.has(t)) {
|
||||
b = helperStack.pop()!;
|
||||
a = helperStack.pop()!;
|
||||
helperStack.push(operatorMap.get(t)!(a, b));
|
||||
} else {
|
||||
helperStack.push(Number(t));
|
||||
}
|
||||
}
|
||||
return helperStack.pop()!;
|
||||
};
|
||||
```
|
||||
|
||||
python3
|
||||
|
||||
```python
|
||||
|
||||
@@ -271,7 +271,7 @@ class Solution:
|
||||
return dp[-1][2*k]
|
||||
```
|
||||
版本二
|
||||
```python3
|
||||
```python
|
||||
class Solution:
|
||||
def maxProfit(self, k: int, prices: List[int]) -> int:
|
||||
if len(prices) == 0: return 0
|
||||
|
||||
@@ -330,5 +330,55 @@ def min_sub_array_len(target, nums)
|
||||
end
|
||||
```
|
||||
|
||||
C:
|
||||
暴力解法:
|
||||
```c
|
||||
int minSubArrayLen(int target, int* nums, int numsSize){
|
||||
//初始化最小长度为INT_MAX
|
||||
int minLength = INT_MAX;
|
||||
int sum;
|
||||
|
||||
int left, right;
|
||||
for(left = 0; left < numsSize; ++left) {
|
||||
//每次遍历都清零sum,计算当前位置后和>=target的子数组的长度
|
||||
sum = 0;
|
||||
//从left开始,sum中添加元素
|
||||
for(right = left; right < numsSize; ++right) {
|
||||
sum += nums[right];
|
||||
//若加入当前元素后,和大于target,则更新minLength
|
||||
if(sum >= target) {
|
||||
int subLength = right - left + 1;
|
||||
minLength = minLength < subLength ? minLength : subLength;
|
||||
}
|
||||
}
|
||||
}
|
||||
//若minLength不为INT_MAX,则返回minLnegth
|
||||
return minLength == INT_MAX ? 0 : minLength;
|
||||
}
|
||||
```
|
||||
|
||||
滑动窗口:
|
||||
```c
|
||||
int minSubArrayLen(int target, int* nums, int numsSize){
|
||||
//初始化最小长度为INT_MAX
|
||||
int minLength = INT_MAX;
|
||||
int sum = 0;
|
||||
|
||||
int left = 0, right = 0;
|
||||
//右边界向右扩展
|
||||
for(; right < numsSize; ++right) {
|
||||
sum += nums[right];
|
||||
//当sum的值大于等于target时,保存长度,并且收缩左边界
|
||||
while(sum >= target) {
|
||||
int subLength = right - left + 1;
|
||||
minLength = minLength < subLength ? minLength : subLength;
|
||||
sum -= nums[left++];
|
||||
}
|
||||
}
|
||||
//若minLength不为INT_MAX,则返回minLnegth
|
||||
return minLength == INT_MAX ? 0 : minLength;
|
||||
}
|
||||
```
|
||||
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
||||
@@ -447,7 +447,63 @@ var countNodes = function(root) {
|
||||
};
|
||||
```
|
||||
|
||||
## TypeScrpt:
|
||||
|
||||
> 递归法
|
||||
|
||||
```typescript
|
||||
function countNodes(root: TreeNode | null): number {
|
||||
if (root === null) return 0;
|
||||
return 1 + countNodes(root.left) + countNodes(root.right);
|
||||
};
|
||||
```
|
||||
|
||||
> 迭代法
|
||||
|
||||
```typescript
|
||||
function countNodes(root: TreeNode | null): number {
|
||||
let helperQueue: TreeNode[] = [];
|
||||
let resCount: number = 0;
|
||||
let tempNode: TreeNode;
|
||||
if (root !== null) helperQueue.push(root);
|
||||
while (helperQueue.length > 0) {
|
||||
for (let i = 0, length = helperQueue.length; i < length; i++) {
|
||||
tempNode = helperQueue.shift()!;
|
||||
resCount++;
|
||||
if (tempNode.left) helperQueue.push(tempNode.left);
|
||||
if (tempNode.right) helperQueue.push(tempNode.right);
|
||||
}
|
||||
}
|
||||
return resCount;
|
||||
};
|
||||
```
|
||||
|
||||
> 利用完全二叉树性质
|
||||
|
||||
```typescript
|
||||
function countNodes(root: TreeNode | null): number {
|
||||
if (root === null) return 0;
|
||||
let left: number = 0,
|
||||
right: number = 0;
|
||||
let curNode: TreeNode | null= root;
|
||||
while (curNode !== null) {
|
||||
left++;
|
||||
curNode = curNode.left;
|
||||
}
|
||||
curNode = root;
|
||||
while (curNode !== null) {
|
||||
right++;
|
||||
curNode = curNode.right;
|
||||
}
|
||||
if (left === right) {
|
||||
return 2 ** left - 1;
|
||||
}
|
||||
return 1 + countNodes(root.left) + countNodes(root.right);
|
||||
};
|
||||
```
|
||||
|
||||
## C:
|
||||
|
||||
递归法
|
||||
```c
|
||||
int countNodes(struct TreeNode* root) {
|
||||
@@ -538,7 +594,7 @@ func _countNodes(_ root: TreeNode?) -> Int {
|
||||
return 1 + leftCount + rightCount
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
> 层序遍历
|
||||
```Swift
|
||||
func countNodes(_ root: TreeNode?) -> Int {
|
||||
@@ -564,7 +620,7 @@ func countNodes(_ root: TreeNode?) -> Int {
|
||||
return res
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
> 利用完全二叉树性质
|
||||
```Swift
|
||||
func countNodes(_ root: TreeNode?) -> Int {
|
||||
|
||||
@@ -598,7 +598,80 @@ MyStack.prototype.empty = function() {
|
||||
|
||||
```
|
||||
|
||||
TypeScript:
|
||||
|
||||
版本一:使用两个队列模拟栈
|
||||
|
||||
```typescript
|
||||
class MyStack {
|
||||
private queue: number[];
|
||||
private tempQueue: number[];
|
||||
constructor() {
|
||||
this.queue = [];
|
||||
this.tempQueue = [];
|
||||
}
|
||||
|
||||
push(x: number): void {
|
||||
this.queue.push(x);
|
||||
}
|
||||
|
||||
pop(): number {
|
||||
for (let i = 0, length = this.queue.length - 1; i < length; i++) {
|
||||
this.tempQueue.push(this.queue.shift()!);
|
||||
}
|
||||
let res: number = this.queue.pop()!;
|
||||
let temp: number[] = this.queue;
|
||||
this.queue = this.tempQueue;
|
||||
this.tempQueue = temp;
|
||||
return res;
|
||||
}
|
||||
|
||||
top(): number {
|
||||
let res: number = this.pop();
|
||||
this.push(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
empty(): boolean {
|
||||
return this.queue.length === 0;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
版本二:使用一个队列模拟栈
|
||||
|
||||
```typescript
|
||||
class MyStack {
|
||||
private queue: number[];
|
||||
constructor() {
|
||||
this.queue = [];
|
||||
}
|
||||
|
||||
push(x: number): void {
|
||||
this.queue.push(x);
|
||||
}
|
||||
|
||||
pop(): number {
|
||||
for (let i = 0, length = this.queue.length - 1; i < length; i++) {
|
||||
this.queue.push(this.queue.shift()!);
|
||||
}
|
||||
return this.queue.shift()!;
|
||||
}
|
||||
|
||||
top(): number {
|
||||
let res: number = this.pop();
|
||||
this.push(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
empty(): boolean {
|
||||
return this.queue.length === 0;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Swift
|
||||
|
||||
```Swift
|
||||
// 定义一个队列数据结构
|
||||
class Queue {
|
||||
|
||||
@@ -563,7 +563,135 @@ var invertTree = function(root) {
|
||||
};
|
||||
```
|
||||
|
||||
### TypeScript:
|
||||
|
||||
递归法:
|
||||
|
||||
```typescript
|
||||
// 递归法(前序遍历)
|
||||
function invertTree(root: TreeNode | null): TreeNode | null {
|
||||
if (root === null) return root;
|
||||
let tempNode: TreeNode | null = root.left;
|
||||
root.left = root.right;
|
||||
root.right = tempNode;
|
||||
invertTree(root.left);
|
||||
invertTree(root.right);
|
||||
return root;
|
||||
};
|
||||
|
||||
// 递归法(后序遍历)
|
||||
function invertTree(root: TreeNode | null): TreeNode | null {
|
||||
if (root === null) return root;
|
||||
invertTree(root.left);
|
||||
invertTree(root.right);
|
||||
let tempNode: TreeNode | null = root.left;
|
||||
root.left = root.right;
|
||||
root.right = tempNode;
|
||||
return root;
|
||||
};
|
||||
|
||||
// 递归法(中序遍历)
|
||||
function invertTree(root: TreeNode | null): TreeNode | null {
|
||||
if (root === null) return root;
|
||||
invertTree(root.left);
|
||||
let tempNode: TreeNode | null = root.left;
|
||||
root.left = root.right;
|
||||
root.right = tempNode;
|
||||
// 因为左右节点已经进行交换,此时的root.left 是原先的root.right
|
||||
invertTree(root.left);
|
||||
return root;
|
||||
};
|
||||
```
|
||||
|
||||
迭代法:
|
||||
|
||||
```typescript
|
||||
// 迭代法(栈模拟前序遍历)
|
||||
function invertTree(root: TreeNode | null): TreeNode | null {
|
||||
let helperStack: TreeNode[] = [];
|
||||
let curNode: TreeNode,
|
||||
tempNode: TreeNode | null;
|
||||
if (root !== null) helperStack.push(root);
|
||||
while (helperStack.length > 0) {
|
||||
curNode = helperStack.pop()!;
|
||||
// 入栈操作最好在交换节点之前进行,便于理解
|
||||
if (curNode.right) helperStack.push(curNode.right);
|
||||
if (curNode.left) helperStack.push(curNode.left);
|
||||
tempNode = curNode.left;
|
||||
curNode.left = curNode.right;
|
||||
curNode.right = tempNode;
|
||||
}
|
||||
return root;
|
||||
};
|
||||
|
||||
// 迭代法(栈模拟中序遍历-统一写法形式)
|
||||
function invertTree(root: TreeNode | null): TreeNode | null {
|
||||
let helperStack: (TreeNode | null)[] = [];
|
||||
let curNode: TreeNode | null,
|
||||
tempNode: TreeNode | null;
|
||||
if (root !== null) helperStack.push(root);
|
||||
while (helperStack.length > 0) {
|
||||
curNode = helperStack.pop();
|
||||
if (curNode !== null) {
|
||||
if (curNode.right !== null) helperStack.push(curNode.right);
|
||||
helperStack.push(curNode);
|
||||
helperStack.push(null);
|
||||
if (curNode.left !== null) helperStack.push(curNode.left);
|
||||
} else {
|
||||
curNode = helperStack.pop()!;
|
||||
tempNode = curNode.left;
|
||||
curNode.left = curNode.right;
|
||||
curNode.right = tempNode;
|
||||
}
|
||||
}
|
||||
return root;
|
||||
};
|
||||
|
||||
// 迭代法(栈模拟后序遍历-统一写法形式)
|
||||
function invertTree(root: TreeNode | null): TreeNode | null {
|
||||
let helperStack: (TreeNode | null)[] = [];
|
||||
let curNode: TreeNode | null,
|
||||
tempNode: TreeNode | null;
|
||||
if (root !== null) helperStack.push(root);
|
||||
while (helperStack.length > 0) {
|
||||
curNode = helperStack.pop();
|
||||
if (curNode !== null) {
|
||||
helperStack.push(curNode);
|
||||
helperStack.push(null);
|
||||
if (curNode.right !== null) helperStack.push(curNode.right);
|
||||
if (curNode.left !== null) helperStack.push(curNode.left);
|
||||
} else {
|
||||
curNode = helperStack.pop()!;
|
||||
tempNode = curNode.left;
|
||||
curNode.left = curNode.right;
|
||||
curNode.right = tempNode;
|
||||
}
|
||||
}
|
||||
return root;
|
||||
};
|
||||
|
||||
// 迭代法(队列模拟层序遍历)
|
||||
function invertTree(root: TreeNode | null): TreeNode | null {
|
||||
const helperQueue: TreeNode[] = [];
|
||||
let curNode: TreeNode,
|
||||
tempNode: TreeNode | null;
|
||||
if (root !== null) helperQueue.push(root);
|
||||
while (helperQueue.length > 0) {
|
||||
for (let i = 0, length = helperQueue.length; i < length; i++) {
|
||||
curNode = helperQueue.shift()!;
|
||||
tempNode = curNode.left;
|
||||
curNode.left = curNode.right;
|
||||
curNode.right = tempNode;
|
||||
if (curNode.left !== null) helperQueue.push(curNode.left);
|
||||
if (curNode.right !== null) helperQueue.push(curNode.right);
|
||||
}
|
||||
}
|
||||
return root;
|
||||
};
|
||||
```
|
||||
|
||||
### C:
|
||||
|
||||
递归法
|
||||
```c
|
||||
struct TreeNode* invertTree(struct TreeNode* root){
|
||||
|
||||
@@ -348,7 +348,44 @@ MyQueue.prototype.empty = function() {
|
||||
};
|
||||
```
|
||||
|
||||
TypeScript:
|
||||
|
||||
```typescript
|
||||
class MyQueue {
|
||||
private stackIn: number[]
|
||||
private stackOut: number[]
|
||||
constructor() {
|
||||
this.stackIn = [];
|
||||
this.stackOut = [];
|
||||
}
|
||||
|
||||
push(x: number): void {
|
||||
this.stackIn.push(x);
|
||||
}
|
||||
|
||||
pop(): number {
|
||||
if (this.stackOut.length === 0) {
|
||||
while (this.stackIn.length > 0) {
|
||||
this.stackOut.push(this.stackIn.pop()!);
|
||||
}
|
||||
}
|
||||
return this.stackOut.pop()!;
|
||||
}
|
||||
|
||||
peek(): number {
|
||||
let temp: number = this.pop();
|
||||
this.stackOut.push(temp);
|
||||
return temp;
|
||||
}
|
||||
|
||||
empty(): boolean {
|
||||
return this.stackIn.length === 0 && this.stackOut.length === 0;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Swift:
|
||||
|
||||
```swift
|
||||
class MyQueue {
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
|
||||
这个队列应该长这个样子:
|
||||
|
||||
```
|
||||
```cpp
|
||||
class MyQueue {
|
||||
public:
|
||||
void pop(int value) {
|
||||
@@ -395,30 +395,102 @@ func maxSlidingWindow(nums []int, k int) []int {
|
||||
|
||||
Javascript:
|
||||
```javascript
|
||||
/**
|
||||
* @param {number[]} nums
|
||||
* @param {number} k
|
||||
* @return {number[]}
|
||||
*/
|
||||
var maxSlidingWindow = function (nums, k) {
|
||||
// 队列数组(存放的是元素下标,为了取值方便)
|
||||
const q = [];
|
||||
// 结果数组
|
||||
const ans = [];
|
||||
for (let i = 0; i < nums.length; i++) {
|
||||
// 若队列不为空,且当前元素大于等于队尾所存下标的元素,则弹出队尾
|
||||
while (q.length && nums[i] >= nums[q[q.length - 1]]) {
|
||||
q.pop();
|
||||
class MonoQueue {
|
||||
queue;
|
||||
constructor() {
|
||||
this.queue = [];
|
||||
}
|
||||
enqueue(value) {
|
||||
let back = this.queue[this.queue.length - 1];
|
||||
while (back !== undefined && back < value) {
|
||||
this.queue.pop();
|
||||
back = this.queue[this.queue.length - 1];
|
||||
}
|
||||
this.queue.push(value);
|
||||
}
|
||||
dequeue(value) {
|
||||
let front = this.front();
|
||||
if (front === value) {
|
||||
this.queue.shift();
|
||||
}
|
||||
}
|
||||
front() {
|
||||
return this.queue[0];
|
||||
}
|
||||
}
|
||||
// 入队当前元素下标
|
||||
q.push(i);
|
||||
// 判断当前最大值(即队首元素)是否在窗口中,若不在便将其出队
|
||||
if (q[0] <= i - k) {
|
||||
q.shift();
|
||||
let helperQueue = new MonoQueue();
|
||||
let i = 0, j = 0;
|
||||
let resArr = [];
|
||||
while (j < k) {
|
||||
helperQueue.enqueue(nums[j++]);
|
||||
}
|
||||
// 当达到窗口大小时便开始向结果中添加数据
|
||||
if (i >= k - 1) ans.push(nums[q[0]]);
|
||||
}
|
||||
return ans;
|
||||
resArr.push(helperQueue.front());
|
||||
while (j < nums.length) {
|
||||
helperQueue.enqueue(nums[j]);
|
||||
helperQueue.dequeue(nums[i]);
|
||||
resArr.push(helperQueue.front());
|
||||
i++, j++;
|
||||
}
|
||||
return resArr;
|
||||
};
|
||||
```
|
||||
|
||||
TypeScript:
|
||||
|
||||
```typescript
|
||||
function maxSlidingWindow(nums: number[], k: number): number[] {
|
||||
/** 单调递减队列 */
|
||||
class MonoQueue {
|
||||
private queue: number[];
|
||||
constructor() {
|
||||
this.queue = [];
|
||||
};
|
||||
/** 入队:value如果大于队尾元素,则将队尾元素删除,直至队尾元素大于value,或者队列为空 */
|
||||
public enqueue(value: number): void {
|
||||
let back: number | undefined = this.queue[this.queue.length - 1];
|
||||
while (back !== undefined && back < value) {
|
||||
this.queue.pop();
|
||||
back = this.queue[this.queue.length - 1];
|
||||
}
|
||||
this.queue.push(value);
|
||||
};
|
||||
/** 出队:只有当队头元素等于value,才出队 */
|
||||
public dequeue(value: number): void {
|
||||
let top: number | undefined = this.top();
|
||||
if (top !== undefined && top === value) {
|
||||
this.queue.shift();
|
||||
}
|
||||
}
|
||||
public top(): number | undefined {
|
||||
return this.queue[0];
|
||||
}
|
||||
}
|
||||
const helperQueue: MonoQueue = new MonoQueue();
|
||||
let i: number = 0,
|
||||
j: number = 0;
|
||||
let resArr: number[] = [];
|
||||
while (j < k) {
|
||||
helperQueue.enqueue(nums[j++]);
|
||||
}
|
||||
resArr.push(helperQueue.top()!);
|
||||
while (j < nums.length) {
|
||||
helperQueue.enqueue(nums[j]);
|
||||
helperQueue.dequeue(nums[i]);
|
||||
resArr.push(helperQueue.top()!);
|
||||
j++, i++;
|
||||
}
|
||||
return resArr;
|
||||
};
|
||||
```
|
||||
|
||||
Swift:
|
||||
|
||||
```Swift
|
||||
/// 双向链表
|
||||
class DoublyListNode {
|
||||
@@ -525,5 +597,39 @@ class Solution {
|
||||
}
|
||||
```
|
||||
|
||||
Swift解法二:
|
||||
|
||||
```swift
|
||||
func maxSlidingWindow(_ nums: [Int], _ k: Int) -> [Int] {
|
||||
var result = [Int]()
|
||||
var window = [Int]()
|
||||
var right = 0, left = right - k + 1
|
||||
|
||||
while right < nums.count {
|
||||
let value = nums[right]
|
||||
|
||||
// 因为窗口移动丢弃的左边数
|
||||
if left > 0, left - 1 == window.first {
|
||||
window.removeFirst()
|
||||
}
|
||||
|
||||
// 保证末尾的是最大的
|
||||
while !window.isEmpty, value > nums[window.last!] {
|
||||
window.removeLast()
|
||||
}
|
||||
window.append(right)
|
||||
|
||||
if left >= 0 { // 窗口形成
|
||||
result.append(nums[window.first!])
|
||||
}
|
||||
|
||||
right += 1
|
||||
left += 1
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
```
|
||||
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
||||
@@ -433,9 +433,9 @@ class Solution:
|
||||
if cur.right:
|
||||
self.traversal(cur.right, path + '->', result)
|
||||
```
|
||||
|
||||
|
||||
迭代法:
|
||||
|
||||
|
||||
```python3
|
||||
from collections import deque
|
||||
|
||||
@@ -463,13 +463,13 @@ class Solution:
|
||||
|
||||
return result
|
||||
```
|
||||
|
||||
|
||||
---
|
||||
|
||||
Go:
|
||||
|
||||
|
||||
递归法:
|
||||
|
||||
|
||||
```go
|
||||
func binaryTreePaths(root *TreeNode) []string {
|
||||
res := make([]string, 0)
|
||||
@@ -492,7 +492,7 @@ func binaryTreePaths(root *TreeNode) []string {
|
||||
return res
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
迭代法:
|
||||
|
||||
```go
|
||||
@@ -581,6 +581,60 @@ var binaryTreePaths = function(root) {
|
||||
};
|
||||
```
|
||||
|
||||
TypeScript:
|
||||
|
||||
> 递归法
|
||||
|
||||
```typescript
|
||||
function binaryTreePaths(root: TreeNode | null): string[] {
|
||||
function recur(node: TreeNode, route: string, resArr: string[]): void {
|
||||
route += String(node.val);
|
||||
if (node.left === null && node.right === null) {
|
||||
resArr.push(route);
|
||||
return;
|
||||
}
|
||||
if (node.left !== null) recur(node.left, route + '->', resArr);
|
||||
if (node.right !== null) recur(node.right, route + '->', resArr);
|
||||
}
|
||||
const resArr: string[] = [];
|
||||
if (root === null) return resArr;
|
||||
recur(root, '', resArr);
|
||||
return resArr;
|
||||
};
|
||||
```
|
||||
|
||||
> 迭代法
|
||||
|
||||
```typescript
|
||||
// 迭代法2
|
||||
function binaryTreePaths(root: TreeNode | null): string[] {
|
||||
let helperStack: TreeNode[] = [];
|
||||
let tempNode: TreeNode;
|
||||
let routeArr: string[] = [];
|
||||
let resArr: string[] = [];
|
||||
if (root !== null) {
|
||||
helperStack.push(root);
|
||||
routeArr.push(String(root.val));
|
||||
};
|
||||
while (helperStack.length > 0) {
|
||||
tempNode = helperStack.pop()!;
|
||||
let route: string = routeArr.pop()!; // tempNode 对应的路径
|
||||
if (tempNode.left === null && tempNode.right === null) {
|
||||
resArr.push(route);
|
||||
}
|
||||
if (tempNode.right !== null) {
|
||||
helperStack.push(tempNode.right);
|
||||
routeArr.push(route + '->' + tempNode.right.val); // tempNode.right 对应的路径
|
||||
}
|
||||
if (tempNode.left !== null) {
|
||||
helperStack.push(tempNode.left);
|
||||
routeArr.push(route + '->' + tempNode.left.val); // tempNode.left 对应的路径
|
||||
}
|
||||
}
|
||||
return resArr;
|
||||
};
|
||||
```
|
||||
|
||||
Swift:
|
||||
|
||||
> 递归/回溯
|
||||
|
||||
@@ -207,7 +207,7 @@ class Solution {
|
||||
|
||||
Python:
|
||||
|
||||
```python3
|
||||
```python
|
||||
class Solution:
|
||||
def numSquares(self, n: int) -> int:
|
||||
'''版本一,先遍历背包, 再遍历物品'''
|
||||
|
||||
@@ -207,7 +207,7 @@ class Solution {
|
||||
|
||||
Python:
|
||||
|
||||
```python3
|
||||
```python
|
||||
class Solution:
|
||||
def coinChange(self, coins: List[int], amount: int) -> int:
|
||||
'''版本一'''
|
||||
|
||||
@@ -288,7 +288,7 @@ Python:
|
||||
|
||||
> 暴力递归
|
||||
|
||||
```python3
|
||||
```python
|
||||
|
||||
# Definition for a binary tree node.
|
||||
# class TreeNode:
|
||||
@@ -315,7 +315,7 @@ class Solution:
|
||||
|
||||
> 记忆化递归
|
||||
|
||||
```python3
|
||||
```python
|
||||
|
||||
# Definition for a binary tree node.
|
||||
# class TreeNode:
|
||||
@@ -345,7 +345,7 @@ class Solution:
|
||||
```
|
||||
|
||||
> 动态规划
|
||||
```python3
|
||||
```python
|
||||
# Definition for a binary tree node.
|
||||
# class TreeNode:
|
||||
# def __init__(self, val=0, left=None, right=None):
|
||||
|
||||
@@ -4,23 +4,22 @@
|
||||
</a>
|
||||
<p align="center"><strong><a href="https://mp.weixin.qq.com/s/tqCxrMEU-ajQumL1i8im9A">参与本项目</a>,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!</strong></p>
|
||||
|
||||
## 343. 整数拆分
|
||||
# 343. 整数拆分
|
||||
|
||||
[力扣题目链接](https://leetcode-cn.com/problems/integer-break/)
|
||||
|
||||
给定一个正整数 n,将其拆分为至少两个正整数的和,并使这些整数的乘积最大化。 返回你可以获得的最大乘积。
|
||||
|
||||
示例 1:
|
||||
输入: 2
|
||||
输出: 1
|
||||
|
||||
\解释: 2 = 1 + 1, 1 × 1 = 1。
|
||||
* 输入: 2
|
||||
* 输出: 1
|
||||
* 解释: 2 = 1 + 1, 1 × 1 = 1。
|
||||
|
||||
示例 2:
|
||||
输入: 10
|
||||
输出: 36
|
||||
解释: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36。
|
||||
说明: 你可以假设 n 不小于 2 且不大于 58。
|
||||
* 输入: 10
|
||||
* 输出: 36
|
||||
* 解释: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36。
|
||||
* 说明: 你可以假设 n 不小于 2 且不大于 58。
|
||||
|
||||
## 思路
|
||||
|
||||
@@ -193,18 +192,21 @@ public:
|
||||
## 其他语言版本
|
||||
|
||||
|
||||
Java:
|
||||
### Java
|
||||
```Java
|
||||
class Solution {
|
||||
public int integerBreak(int n) {
|
||||
//dp[i]为正整数i拆分结果的最大乘积
|
||||
int[] dp = new int[n+1];
|
||||
dp[2] = 1;
|
||||
for (int i = 3; i <= n; ++i) {
|
||||
for (int j = 1; j < i - 1; ++j) {
|
||||
//j*(i-j)代表把i拆分为j和i-j两个数相乘
|
||||
//j*dp[i-j]代表把i拆分成j和继续把(i-j)这个数拆分,取(i-j)拆分结果中的最大乘积与j相乘
|
||||
dp[i] = Math.max(dp[i], Math.max(j * (i - j), j * dp[i - j]));
|
||||
//dp[i] 为正整数 i 拆分后的结果的最大乘积
|
||||
int[]dp=new int[n+1];
|
||||
dp[2]=1;
|
||||
for(int i=3;i<=n;i++){
|
||||
for(int j=1;j<=i-j;j++){
|
||||
// 这里的 j 其实最大值为 i-j,再大只不过是重复而已,
|
||||
//并且,在本题中,我们分析 dp[0], dp[1]都是无意义的,
|
||||
//j 最大到 i-j,就不会用到 dp[0]与dp[1]
|
||||
dp[i]=Math.max(dp[i],Math.max(j*(i-j),j*dp[i-j]));
|
||||
// j * (i - j) 是单纯的把整数 i 拆分为两个数 也就是 i,i-j ,再相乘
|
||||
//而j * dp[i - j]是将 i 拆分成两个以及两个以上的个数,再相乘。
|
||||
}
|
||||
}
|
||||
return dp[n];
|
||||
@@ -212,7 +214,7 @@ class Solution {
|
||||
}
|
||||
```
|
||||
|
||||
Python:
|
||||
### Python
|
||||
```python
|
||||
class Solution:
|
||||
def integerBreak(self, n: int) -> int:
|
||||
@@ -226,7 +228,8 @@ class Solution:
|
||||
dp[i] = max(dp[i], max(j * (i - j), j * dp[i - j]))
|
||||
return dp[n]
|
||||
```
|
||||
Go:
|
||||
|
||||
### Go
|
||||
```golang
|
||||
func integerBreak(n int) int {
|
||||
/**
|
||||
@@ -256,7 +259,7 @@ func max(a,b int) int{
|
||||
}
|
||||
```
|
||||
|
||||
Javascript:
|
||||
### Javascript
|
||||
```Javascript
|
||||
var integerBreak = function(n) {
|
||||
let dp = new Array(n + 1).fill(0)
|
||||
@@ -271,5 +274,40 @@ var integerBreak = function(n) {
|
||||
};
|
||||
```
|
||||
|
||||
C:
|
||||
```c
|
||||
//初始化DP数组
|
||||
int *initDP(int num) {
|
||||
int* dp = (int*)malloc(sizeof(int) * (num + 1));
|
||||
int i;
|
||||
for(i = 0; i < num + 1; ++i) {
|
||||
dp[i] = 0;
|
||||
}
|
||||
return dp;
|
||||
}
|
||||
|
||||
//取三数最大值
|
||||
int max(int num1, int num2, int num3) {
|
||||
int tempMax = num1 > num2 ? num1 : num2;
|
||||
return tempMax > num3 ? tempMax : num3;
|
||||
}
|
||||
|
||||
int integerBreak(int n){
|
||||
int *dp = initDP(n);
|
||||
//初始化dp[2]为1
|
||||
dp[2] = 1;
|
||||
|
||||
int i;
|
||||
for(i = 3; i <= n; ++i) {
|
||||
int j;
|
||||
for(j = 1; j < i - 1; ++j) {
|
||||
//取得上次循环:dp[i],原数相乘,或j*dp[]i-j] 三数中的最大值
|
||||
dp[i] = max(dp[i], j * (i - j), j * dp[i - j]);
|
||||
}
|
||||
}
|
||||
return dp[n];
|
||||
}
|
||||
```
|
||||
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
||||
@@ -358,6 +358,22 @@ PriorityQueue.prototype.compare = function(index1, index2) {
|
||||
}
|
||||
```
|
||||
|
||||
TypeScript:
|
||||
|
||||
```typescript
|
||||
function topKFrequent(nums: number[], k: number): number[] {
|
||||
const countMap: Map<number, number> = new Map();
|
||||
for (let num of nums) {
|
||||
countMap.set(num, (countMap.get(num) || 0) + 1);
|
||||
}
|
||||
// tS没有最小堆的数据结构,所以直接对整个数组进行排序,取前k个元素
|
||||
return [...countMap.entries()]
|
||||
.sort((a, b) => b[1] - a[1])
|
||||
.slice(0, k)
|
||||
.map(i => i[0]);
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
|
||||
-----------------------
|
||||
|
||||
@@ -174,7 +174,7 @@ public:
|
||||
```Java
|
||||
class Solution {
|
||||
public int wiggleMaxLength(int[] nums) {
|
||||
if (nums == null || nums.length <= 1) {
|
||||
if (nums.length <= 1) {
|
||||
return nums.length;
|
||||
}
|
||||
//当前差值
|
||||
@@ -228,7 +228,7 @@ class Solution {
|
||||
|
||||
### Python
|
||||
|
||||
```python3
|
||||
```python
|
||||
class Solution:
|
||||
def wiggleMaxLength(self, nums: List[int]) -> int:
|
||||
preC,curC,res = 0,0,1 #题目里nums长度大于等于1,当长度为1时,其实到不了for循环里去,所以不用考虑nums长度
|
||||
|
||||
@@ -209,7 +209,7 @@ class Solution(object):
|
||||
|
||||
Python写法四:
|
||||
|
||||
```python3
|
||||
```python
|
||||
class Solution:
|
||||
def canConstruct(self, ransomNote: str, magazine: str) -> bool:
|
||||
c1 = collections.Counter(ransomNote)
|
||||
|
||||
@@ -77,7 +77,7 @@ if (s[i - 1] != t[j - 1]),此时相当于t要删除元素,t如果把当前
|
||||
|
||||
如果要是定义的dp[i][j]是以下标i为结尾的字符串s和以下标j为结尾的字符串t,初始化就比较麻烦了。
|
||||
|
||||
这里dp[i][0]和dp[0][j]是没有含义的,仅仅是为了给递推公式做前期铺垫,所以初始化为0。
|
||||
dp[i][0] 表示以下标i-1为结尾的字符串,与空字符串的相同子序列长度,所以为0. dp[0][j]同理。
|
||||
|
||||
**其实这里只初始化dp[i][0]就够了,但一起初始化也方便,所以就一起操作了**,代码如下:
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
**首先要注意是判断左叶子,不是二叉树左侧节点,所以不要上来想着层序遍历。**
|
||||
|
||||
因为题目中其实没有说清楚左叶子究竟是什么节点,那么我来给出左叶子的明确定义:**如果左节点不为空,且左节点没有左右孩子,那么这个节点就是左叶子**
|
||||
因为题目中其实没有说清楚左叶子究竟是什么节点,那么我来给出左叶子的明确定义:**如果左节点不为空,且左节点没有左右孩子,那么这个节点的左节点就是左叶子**
|
||||
|
||||
大家思考一下如下图中二叉树,左叶子之和究竟是多少?
|
||||
|
||||
@@ -229,7 +229,7 @@ class Solution {
|
||||
## Python
|
||||
|
||||
**递归后序遍历**
|
||||
```python3
|
||||
```python
|
||||
class Solution:
|
||||
def sumOfLeftLeaves(self, root: TreeNode) -> int:
|
||||
if not root:
|
||||
@@ -246,7 +246,7 @@ class Solution:
|
||||
```
|
||||
|
||||
**迭代**
|
||||
```python3
|
||||
```python
|
||||
class Solution:
|
||||
def sumOfLeftLeaves(self, root: TreeNode) -> int:
|
||||
"""
|
||||
@@ -372,7 +372,99 @@ var sumOfLeftLeaves = function(root) {
|
||||
};
|
||||
```
|
||||
|
||||
## TypeScript
|
||||
|
||||
> 递归法
|
||||
|
||||
```typescript
|
||||
function sumOfLeftLeaves(root: TreeNode | null): number {
|
||||
if (root === null) return 0;
|
||||
let midVal: number = 0;
|
||||
if (
|
||||
root.left !== null &&
|
||||
root.left.left === null &&
|
||||
root.left.right === null
|
||||
) {
|
||||
midVal = root.left.val;
|
||||
}
|
||||
let leftVal: number = sumOfLeftLeaves(root.left);
|
||||
let rightVal: number = sumOfLeftLeaves(root.right);
|
||||
return midVal + leftVal + rightVal;
|
||||
};
|
||||
```
|
||||
|
||||
> 迭代法
|
||||
|
||||
```typescript
|
||||
function sumOfLeftLeaves(root: TreeNode | null): number {
|
||||
let helperStack: TreeNode[] = [];
|
||||
let tempNode: TreeNode;
|
||||
let sum: number = 0;
|
||||
if (root !== null) helperStack.push(root);
|
||||
while (helperStack.length > 0) {
|
||||
tempNode = helperStack.pop()!;
|
||||
if (
|
||||
tempNode.left !== null &&
|
||||
tempNode.left.left === null &&
|
||||
tempNode.left.right === null
|
||||
) {
|
||||
sum += tempNode.left.val;
|
||||
}
|
||||
if (tempNode.right !== null) helperStack.push(tempNode.right);
|
||||
if (tempNode.left !== null) helperStack.push(tempNode.left);
|
||||
}
|
||||
return sum;
|
||||
};
|
||||
```
|
||||
|
||||
## Swift
|
||||
|
||||
**递归法**
|
||||
```swift
|
||||
func sumOfLeftLeaves(_ root: TreeNode?) -> Int {
|
||||
guard let root = root else {
|
||||
return 0
|
||||
}
|
||||
|
||||
let leftValue = sumOfLeftLeaves(root.left)
|
||||
let rightValue = sumOfLeftLeaves(root.right)
|
||||
|
||||
var midValue: Int = 0
|
||||
if root.left != nil && root.left?.left == nil && root.left?.right == nil {
|
||||
midValue = root.left!.val
|
||||
}
|
||||
|
||||
let sum = midValue + leftValue + rightValue
|
||||
return sum
|
||||
}
|
||||
```
|
||||
**迭代法**
|
||||
```swift
|
||||
func sumOfLeftLeaves(_ root: TreeNode?) -> Int {
|
||||
guard let root = root else {
|
||||
return 0
|
||||
}
|
||||
|
||||
var stack = Array<TreeNode>()
|
||||
stack.append(root)
|
||||
var sum = 0
|
||||
|
||||
while !stack.isEmpty {
|
||||
let lastNode = stack.removeLast()
|
||||
|
||||
if lastNode.left != nil && lastNode.left?.left == nil && lastNode.left?.right == nil {
|
||||
sum += lastNode.left!.val
|
||||
}
|
||||
if let right = lastNode.right {
|
||||
stack.append(right)
|
||||
}
|
||||
if let left = lastNode.left {
|
||||
stack.append(left)
|
||||
}
|
||||
}
|
||||
return sum
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -183,28 +183,22 @@ public:
|
||||
```java
|
||||
class Solution {
|
||||
public int eraseOverlapIntervals(int[][] intervals) {
|
||||
if (intervals.length < 2) return 0;
|
||||
|
||||
Arrays.sort(intervals, new Comparator<int[]>() {
|
||||
@Override
|
||||
public int compare(int[] o1, int[] o2) {
|
||||
if (o1[1] != o2[1]) {
|
||||
return Integer.compare(o1[1],o2[1]);
|
||||
} else {
|
||||
return Integer.compare(o1[0],o2[0]);
|
||||
}
|
||||
}
|
||||
Arrays.sort(intervals, (a, b) -> {
|
||||
if (a[0] == a[0]) return a[1] - b[1];
|
||||
return a[0] - b[0];
|
||||
});
|
||||
|
||||
int count = 1;
|
||||
int edge = intervals[0][1];
|
||||
for (int i = 1; i < intervals.length; i++) {
|
||||
if (edge <= intervals[i][0]){
|
||||
count ++; //non overlap + 1
|
||||
int count = 0;
|
||||
int edge = Integer.MIN_VALUE;
|
||||
for (int i = 0; i < intervals.length; i++) {
|
||||
if (edge <= intervals[i][0]) {
|
||||
edge = intervals[i][1];
|
||||
} else {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return intervals.length - count;
|
||||
|
||||
return count;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -146,7 +146,7 @@ class Solution {
|
||||
```
|
||||
|
||||
### Python
|
||||
```python3
|
||||
```python
|
||||
class Solution:
|
||||
# 思路1:优先考虑胃饼干
|
||||
def findContentChildren(self, g: List[int], s: List[int]) -> int:
|
||||
|
||||
@@ -361,7 +361,65 @@ var repeatedSubstringPattern = function (s) {
|
||||
};
|
||||
```
|
||||
|
||||
TypeScript:
|
||||
|
||||
> 前缀表统一减一
|
||||
|
||||
```typescript
|
||||
function repeatedSubstringPattern(s: string): boolean {
|
||||
function getNext(str: string): number[] {
|
||||
let next: number[] = [];
|
||||
let j: number = -1;
|
||||
next[0] = j;
|
||||
for (let i = 1, length = str.length; i < length; i++) {
|
||||
while (j >= 0 && str[i] !== str[j + 1]) {
|
||||
j = next[j];
|
||||
}
|
||||
if (str[i] === str[j + 1]) {
|
||||
j++;
|
||||
}
|
||||
next[i] = j;
|
||||
}
|
||||
return next;
|
||||
}
|
||||
|
||||
let next: number[] = getNext(s);
|
||||
let sLength: number = s.length;
|
||||
let nextLength: number = next.length;
|
||||
let suffixLength: number = next[nextLength - 1] + 1;
|
||||
if (suffixLength > 0 && sLength % (sLength - suffixLength) === 0) return true;
|
||||
return false;
|
||||
};
|
||||
```
|
||||
|
||||
> 前缀表不减一
|
||||
|
||||
```typescript
|
||||
function repeatedSubstringPattern(s: string): boolean {
|
||||
function getNext(str: string): number[] {
|
||||
let next: number[] = [];
|
||||
let j: number = 0;
|
||||
next[0] = j;
|
||||
for (let i = 1, length = str.length; i < length; i++) {
|
||||
while (j > 0 && str[i] !== str[j]) {
|
||||
j = next[j - 1];
|
||||
}
|
||||
if (str[i] === str[j]) {
|
||||
j++;
|
||||
}
|
||||
next[i] = j;
|
||||
}
|
||||
return next;
|
||||
}
|
||||
|
||||
let next: number[] = getNext(s);
|
||||
let sLength: number = s.length;
|
||||
let nextLength: number = next.length;
|
||||
let suffixLength: number = next[nextLength - 1];
|
||||
if (suffixLength > 0 && sLength % (sLength - suffixLength) === 0) return true;
|
||||
return false;
|
||||
};
|
||||
```
|
||||
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
||||
@@ -124,7 +124,7 @@ Python:
|
||||
### 解法1:
|
||||
扫描每个cell,如果当前位置为岛屿 grid[i][j] == 1, 从当前位置判断四边方向,如果边界或者是水域,证明有边界存在,res矩阵的对应cell加一。
|
||||
|
||||
```python3
|
||||
```python
|
||||
class Solution:
|
||||
def islandPerimeter(self, grid: List[List[int]]) -> int:
|
||||
|
||||
|
||||
@@ -193,7 +193,7 @@ class Solution {
|
||||
```
|
||||
|
||||
Python:
|
||||
```python3
|
||||
```python
|
||||
class Solution:
|
||||
def findMaxForm(self, strs: List[str], m: int, n: int) -> int:
|
||||
dp = [[0] * (n + 1) for _ in range(m + 1)] # 默认初始化0
|
||||
|
||||
@@ -233,7 +233,7 @@ class Solution {
|
||||
|
||||
python3
|
||||
**回溯**
|
||||
```python3
|
||||
```python
|
||||
class Solution:
|
||||
def __init__(self):
|
||||
self.paths = []
|
||||
@@ -270,7 +270,7 @@ class Solution:
|
||||
self.path.pop()
|
||||
```
|
||||
**回溯+哈希表去重**
|
||||
```python3
|
||||
```python
|
||||
class Solution:
|
||||
def __init__(self):
|
||||
self.paths = []
|
||||
|
||||
@@ -160,11 +160,16 @@ dp[j] 表示:填满j(包括j)这么大容积的包,有dp[j]种方法
|
||||
|
||||
那么只要搞到nums[i]的话,凑成dp[j]就有dp[j - nums[i]] 种方法。
|
||||
|
||||
举一个例子,nums[i] = 2: dp[3],填满背包容量为3的话,有dp[3]种方法。
|
||||
|
||||
那么只需要搞到一个2(nums[i]),有dp[3]方法可以凑齐容量为3的背包,相应的就有多少种方法可以凑齐容量为5的背包。
|
||||
例如:dp[j],j 为5,
|
||||
|
||||
那么需要把 这些方法累加起来就可以了,dp[j] += dp[j - nums[i]]
|
||||
* 已经有一个1(nums[i]) 的话,有 dp[4]种方法 凑成 dp[5]。
|
||||
* 已经有一个2(nums[i]) 的话,有 dp[3]种方法 凑成 dp[5]。
|
||||
* 已经有一个3(nums[i]) 的话,有 dp[2]中方法 凑成 dp[5]
|
||||
* 已经有一个4(nums[i]) 的话,有 dp[1]中方法 凑成 dp[5]
|
||||
* 已经有一个5 (nums[i])的话,有 dp[0]中方法 凑成 dp[5]
|
||||
|
||||
那么凑整dp[5]有多少方法呢,也就是把 所有的 dp[j - nums[i]] 累加起来。
|
||||
|
||||
所以求组合类问题的公式,都是类似这种:
|
||||
|
||||
@@ -272,7 +277,8 @@ Python:
|
||||
class Solution:
|
||||
def findTargetSumWays(self, nums: List[int], target: int) -> int:
|
||||
sumValue = sum(nums)
|
||||
if target > sumValue or (sumValue + target) % 2 == 1: return 0
|
||||
#注意边界条件为 target>sumValue or target<-sumValue or (sumValue + target) % 2 == 1
|
||||
if abs(target) > sumValue or (sumValue + target) % 2 == 1: return 0
|
||||
bagSize = (sumValue + target) // 2
|
||||
dp = [0] * (bagSize + 1)
|
||||
dp[0] = 1
|
||||
|
||||
@@ -222,8 +222,8 @@ class Solution {
|
||||
}
|
||||
}
|
||||
```
|
||||
Python:
|
||||
```python3
|
||||
Python3:
|
||||
```python
|
||||
class Solution:
|
||||
def nextGreaterElement(self, nums1: List[int], nums2: List[int]) -> List[int]:
|
||||
result = [-1]*len(nums1)
|
||||
|
||||
@@ -470,7 +470,7 @@ class Solution {
|
||||
|
||||
> 递归法
|
||||
|
||||
```python3
|
||||
```python
|
||||
# Definition for a binary tree node.
|
||||
# class TreeNode:
|
||||
# def __init__(self, val=0, left=None, right=None):
|
||||
@@ -515,7 +515,7 @@ class Solution:
|
||||
|
||||
|
||||
> 迭代法-中序遍历-不使用额外空间,利用二叉搜索树特性
|
||||
```python3
|
||||
```python
|
||||
class Solution:
|
||||
def findMode(self, root: TreeNode) -> List[int]:
|
||||
stack = []
|
||||
|
||||
@@ -124,7 +124,7 @@ class Solution {
|
||||
```
|
||||
|
||||
Python:
|
||||
```python3
|
||||
```python
|
||||
class Solution:
|
||||
def nextGreaterElements(self, nums: List[int]) -> List[int]:
|
||||
dp = [-1] * len(nums)
|
||||
|
||||
@@ -433,6 +433,119 @@ var findBottomLeftValue = function(root) {
|
||||
};
|
||||
```
|
||||
|
||||
## TypeScript
|
||||
|
||||
> 递归法:
|
||||
|
||||
```typescript
|
||||
function findBottomLeftValue(root: TreeNode | null): number {
|
||||
function recur(root: TreeNode, depth: number): void {
|
||||
if (root.left === null && root.right === null) {
|
||||
if (depth > maxDepth) {
|
||||
maxDepth = depth;
|
||||
resVal = root.val;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (root.left !== null) recur(root.left, depth + 1);
|
||||
if (root.right !== null) recur(root.right, depth + 1);
|
||||
}
|
||||
let maxDepth: number = 0;
|
||||
let resVal: number = 0;
|
||||
if (root === null) return resVal;
|
||||
recur(root, 1);
|
||||
return resVal;
|
||||
};
|
||||
```
|
||||
|
||||
> 迭代法:
|
||||
|
||||
```typescript
|
||||
function findBottomLeftValue(root: TreeNode | null): number {
|
||||
let helperQueue: TreeNode[] = [];
|
||||
if (root !== null) helperQueue.push(root);
|
||||
let resVal: number = 0;
|
||||
let tempNode: TreeNode;
|
||||
while (helperQueue.length > 0) {
|
||||
resVal = helperQueue[0].val;
|
||||
for (let i = 0, length = helperQueue.length; i < length; i++) {
|
||||
tempNode = helperQueue.shift()!;
|
||||
if (tempNode.left !== null) helperQueue.push(tempNode.left);
|
||||
if (tempNode.right !== null) helperQueue.push(tempNode.right);
|
||||
}
|
||||
}
|
||||
return resVal;
|
||||
};
|
||||
```
|
||||
|
||||
## Swift
|
||||
|
||||
递归版本:
|
||||
|
||||
```swift
|
||||
var maxLen = -1
|
||||
var maxLeftValue = 0
|
||||
func findBottomLeftValue_2(_ root: TreeNode?) -> Int {
|
||||
traversal(root, 0)
|
||||
return maxLeftValue
|
||||
}
|
||||
|
||||
func traversal(_ root: TreeNode?, _ deep: Int) {
|
||||
guard let root = root else {
|
||||
return
|
||||
}
|
||||
|
||||
if root.left == nil && root.right == nil {
|
||||
if deep > maxLen {
|
||||
maxLen = deep
|
||||
maxLeftValue = root.val
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if root.left != nil {
|
||||
traversal(root.left, deep + 1)
|
||||
}
|
||||
|
||||
if root.right != nil {
|
||||
traversal(root.right, deep + 1)
|
||||
}
|
||||
return
|
||||
}
|
||||
```
|
||||
层序遍历:
|
||||
|
||||
```swift
|
||||
func findBottomLeftValue(_ root: TreeNode?) -> Int {
|
||||
guard let root = root else {
|
||||
return 0
|
||||
}
|
||||
|
||||
var queue = [root]
|
||||
var result = 0
|
||||
|
||||
while !queue.isEmpty {
|
||||
let size = queue.count
|
||||
for i in 0..<size {
|
||||
let firstNode = queue.removeFirst()
|
||||
|
||||
if i == 0 {
|
||||
result = firstNode.val
|
||||
}
|
||||
|
||||
if let leftNode = firstNode.left {
|
||||
queue.append(leftNode)
|
||||
}
|
||||
|
||||
if let rightNode = firstNode.right {
|
||||
queue.append(rightNode)
|
||||
}
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
-----------------------
|
||||
|
||||
@@ -207,7 +207,7 @@ class Solution {
|
||||
Python:
|
||||
|
||||
|
||||
```python3
|
||||
```python
|
||||
class Solution:
|
||||
def change(self, amount: int, coins: List[int]) -> int:
|
||||
dp = [0]*(amount + 1)
|
||||
|
||||
@@ -196,7 +196,7 @@ class Solution {
|
||||
## Python
|
||||
**递归**
|
||||
|
||||
```python3
|
||||
```python
|
||||
# Definition for a binary tree node.
|
||||
# class TreeNode:
|
||||
# def __init__(self, val=0, left=None, right=None):
|
||||
|
||||
@@ -401,6 +401,33 @@ struct TreeNode* constructMaximumBinaryTree(int* nums, int numsSize){
|
||||
}
|
||||
```
|
||||
|
||||
## Swift
|
||||
```swift
|
||||
func constructMaximumBinaryTree(_ nums: inout [Int]) -> TreeNode? {
|
||||
return traversal(&nums, 0, nums.count)
|
||||
}
|
||||
|
||||
func traversal(_ nums: inout [Int], _ left: Int, _ right: Int) -> TreeNode? {
|
||||
if left >= right {
|
||||
return nil
|
||||
}
|
||||
|
||||
var maxValueIndex = left
|
||||
for i in (left + 1)..<right {
|
||||
if nums[i] > nums[maxValueIndex] {
|
||||
maxValueIndex = i
|
||||
}
|
||||
}
|
||||
|
||||
let root = TreeNode(nums[maxValueIndex])
|
||||
|
||||
root.left = traversal(&nums, left, maxValueIndex)
|
||||
root.right = traversal(&nums, maxValueIndex + 1, right)
|
||||
return root
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
||||
@@ -264,7 +264,7 @@ class Solution {
|
||||
|
||||
## Python
|
||||
**递归**
|
||||
```python3
|
||||
```python
|
||||
# Definition for a binary tree node.
|
||||
# class TreeNode:
|
||||
# def __init__(self, val=0, left=None, right=None):
|
||||
|
||||
@@ -310,6 +310,26 @@ class Solution:
|
||||
return root
|
||||
```
|
||||
|
||||
**递归法** - 无返回值 - another easier way
|
||||
```python
|
||||
class Solution:
|
||||
def insertIntoBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]:
|
||||
newNode = TreeNode(val)
|
||||
if not root: return newNode
|
||||
|
||||
if not root.left and val < root.val:
|
||||
root.left = newNode
|
||||
if not root.right and val > root.val:
|
||||
root.right = newNode
|
||||
|
||||
if val < root.val:
|
||||
self.insertIntoBST(root.left, val)
|
||||
if val > root.val:
|
||||
self.insertIntoBST(root.right, val)
|
||||
|
||||
return root
|
||||
```
|
||||
|
||||
**迭代法**
|
||||
与无返回值的递归函数的思路大体一致
|
||||
```python
|
||||
|
||||
@@ -152,7 +152,6 @@ class Solution {
|
||||
|
||||
|
||||
|
||||
Python:
|
||||
|
||||
python3
|
||||
|
||||
|
||||
@@ -194,7 +194,7 @@ class Solution {
|
||||
```
|
||||
|
||||
Python:
|
||||
```python3
|
||||
```python
|
||||
# 方法一,使用栈,推荐!
|
||||
class Solution:
|
||||
def removeDuplicates(self, s: str) -> str:
|
||||
@@ -207,7 +207,7 @@ class Solution:
|
||||
return "".join(res) # 字符串拼接
|
||||
```
|
||||
|
||||
```python3
|
||||
```python
|
||||
# 方法二,使用双指针模拟栈,如果不让用栈可以作为备选方法。
|
||||
class Solution:
|
||||
def removeDuplicates(self, s: str) -> str:
|
||||
@@ -267,8 +267,32 @@ var removeDuplicates = function(s) {
|
||||
};
|
||||
```
|
||||
|
||||
TypeScript:
|
||||
|
||||
```typescript
|
||||
function removeDuplicates(s: string): string {
|
||||
const helperStack: string[] = [];
|
||||
let i: number = 0;
|
||||
while (i < s.length) {
|
||||
let top: string = helperStack[helperStack.length - 1];
|
||||
if (top === s[i]) {
|
||||
helperStack.pop();
|
||||
} else {
|
||||
helperStack.push(s[i]);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
let res: string = '';
|
||||
while (helperStack.length > 0) {
|
||||
res = helperStack.pop() + res;
|
||||
}
|
||||
return res;
|
||||
};
|
||||
```
|
||||
|
||||
C:
|
||||
方法一:使用栈
|
||||
|
||||
```c
|
||||
char * removeDuplicates(char * s){
|
||||
//求出字符串长度
|
||||
@@ -322,14 +346,12 @@ char * removeDuplicates(char * s){
|
||||
Swift:
|
||||
```swift
|
||||
func removeDuplicates(_ s: String) -> String {
|
||||
let array = Array(s)
|
||||
var stack = [Character]()
|
||||
for c in array {
|
||||
let last: Character? = stack.last
|
||||
if stack.isEmpty || last != c {
|
||||
stack.append(c)
|
||||
} else {
|
||||
for c in s {
|
||||
if stack.last == c {
|
||||
stack.removeLast()
|
||||
} else {
|
||||
stack.append(c)
|
||||
}
|
||||
}
|
||||
return String(stack)
|
||||
|
||||
@@ -171,7 +171,7 @@ if (cur->right) {
|
||||
## 其他语言版本
|
||||
|
||||
|
||||
Java:
|
||||
### Java:
|
||||
100. 相同的树:递归代码
|
||||
```java
|
||||
class Solution {
|
||||
@@ -252,7 +252,7 @@ Java:
|
||||
}
|
||||
```
|
||||
|
||||
Python:
|
||||
### Python:
|
||||
|
||||
100.相同的树
|
||||
> 递归法
|
||||
@@ -332,7 +332,7 @@ class Solution:
|
||||
self.traversal(cur.right, path+"->", result) #右 回溯就隐藏在这里
|
||||
```
|
||||
|
||||
Go:
|
||||
### Go:
|
||||
|
||||
100.相同的树
|
||||
```go
|
||||
@@ -436,7 +436,7 @@ func traversal(root *TreeNode,result *[]string,path *[]int){
|
||||
}
|
||||
```
|
||||
|
||||
JavaScript:
|
||||
### JavaScript:
|
||||
|
||||
100.相同的树
|
||||
```javascript
|
||||
@@ -516,5 +516,107 @@ var binaryTreePaths = function(root) {
|
||||
```
|
||||
|
||||
|
||||
### TypeScript:
|
||||
|
||||
> 相同的树
|
||||
|
||||
```typescript
|
||||
function isSameTree(p: TreeNode | null, q: TreeNode | null): boolean {
|
||||
if (p === null && q === null) return true;
|
||||
if (p === null || q === null) return false;
|
||||
if (p.val !== q.val) return false;
|
||||
let bool1: boolean, bool2: boolean;
|
||||
bool1 = isSameTree(p.left, q.left);
|
||||
bool2 = isSameTree(p.right, q.right);
|
||||
return bool1 && bool2;
|
||||
};
|
||||
```
|
||||
|
||||
> 二叉树的不同路径
|
||||
|
||||
```typescript
|
||||
function binaryTreePaths(root: TreeNode | null): string[] {
|
||||
function recur(node: TreeNode, nodeSeqArr: number[], resArr: string[]): void {
|
||||
nodeSeqArr.push(node.val);
|
||||
if (node.left === null && node.right === null) {
|
||||
resArr.push(nodeSeqArr.join('->'));
|
||||
}
|
||||
if (node.left !== null) {
|
||||
recur(node.left, nodeSeqArr, resArr);
|
||||
nodeSeqArr.pop();
|
||||
}
|
||||
if (node.right !== null) {
|
||||
recur(node.right, nodeSeqArr, resArr);
|
||||
nodeSeqArr.pop();
|
||||
}
|
||||
}
|
||||
let nodeSeqArr: number[] = [];
|
||||
let resArr: string[] = [];
|
||||
if (root === null) return resArr;
|
||||
recur(root, nodeSeqArr, resArr);
|
||||
return resArr;
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### Swift:
|
||||
> 100.相同的树
|
||||
```swift
|
||||
// 递归
|
||||
func isSameTree(_ p: TreeNode?, _ q: TreeNode?) -> Bool {
|
||||
return _isSameTree3(p, q)
|
||||
}
|
||||
func _isSameTree3(_ p: TreeNode?, _ q: TreeNode?) -> Bool {
|
||||
if p == nil && q == nil {
|
||||
return true
|
||||
} else if p == nil && q != nil {
|
||||
return false
|
||||
} else if p != nil && q == nil {
|
||||
return false
|
||||
} else if p!.val != q!.val {
|
||||
return false
|
||||
}
|
||||
let leftSide = _isSameTree3(p!.left, q!.left)
|
||||
let rightSide = _isSameTree3(p!.right, q!.right)
|
||||
return leftSide && rightSide
|
||||
}
|
||||
```
|
||||
|
||||
> 257.二叉树的不同路径
|
||||
```swift
|
||||
// 递归/回溯
|
||||
func binaryTreePaths(_ root: TreeNode?) -> [String] {
|
||||
var res = [String]()
|
||||
guard let root = root else {
|
||||
return res
|
||||
}
|
||||
var paths = [Int]()
|
||||
_binaryTreePaths3(root, res: &res, paths: &paths)
|
||||
return res
|
||||
}
|
||||
func _binaryTreePaths3(_ root: TreeNode, res: inout [String], paths: inout [Int]) {
|
||||
paths.append(root.val)
|
||||
if root.left == nil && root.right == nil {
|
||||
var str = ""
|
||||
for i in 0 ..< (paths.count - 1) {
|
||||
str.append("\(paths[i])->")
|
||||
}
|
||||
str.append("\(paths.last!)")
|
||||
res.append(str)
|
||||
}
|
||||
if let left = root.left {
|
||||
_binaryTreePaths3(left, res: &res, paths: &paths)
|
||||
paths.removeLast()
|
||||
}
|
||||
if let right = root.right {
|
||||
_binaryTreePaths3(right, res: &res, paths: &paths)
|
||||
paths.removeLast()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
||||
@@ -152,7 +152,7 @@
|
||||
|
||||

|
||||
|
||||
这个图是 [代码随想录知识星球](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ) 成员:[青](https://wx.zsxq.com/dweb2/index/footprint/185251215558842),所画,总结的非常好,分享给大家。
|
||||
这个图是 [代码随想录知识星球](https://programmercarl.com/other/kstar.html) 成员:[青](https://wx.zsxq.com/dweb2/index/footprint/185251215558842),所画,总结的非常好,分享给大家。
|
||||
|
||||
|
||||
**最后,二叉树系列就这么完美结束了,估计这应该是最长的系列了,感谢大家33天的坚持与陪伴,接下来我们又要开始新的系列了「回溯算法」!**
|
||||
|
||||
@@ -154,7 +154,7 @@
|
||||
|
||||
C++代码如下:
|
||||
|
||||
```
|
||||
```cpp
|
||||
struct TreeNode {
|
||||
int val;
|
||||
TreeNode *left;
|
||||
@@ -163,7 +163,7 @@ struct TreeNode {
|
||||
};
|
||||
```
|
||||
|
||||
大家会发现二叉树的定义 和链表是差不多的,相对于链表 ,二叉树的节点里多了一个指针, 有两个指针,指向左右孩子.
|
||||
大家会发现二叉树的定义 和链表是差不多的,相对于链表 ,二叉树的节点里多了一个指针, 有两个指针,指向左右孩子。
|
||||
|
||||
这里要提醒大家要注意二叉树节点定义的书写方式。
|
||||
|
||||
@@ -177,7 +177,7 @@ struct TreeNode {
|
||||
|
||||
本篇我们介绍了二叉树的种类、存储方式、遍历方式以及定义,比较全面的介绍了二叉树各个方面的重点,帮助大家扫一遍基础。
|
||||
|
||||
**说道二叉树,就不得不说递归,很多同学对递归都是又熟悉又陌生,递归的代码一般很简短,但每次都是一看就会,一写就废。**
|
||||
**说到二叉树,就不得不说递归,很多同学对递归都是又熟悉又陌生,递归的代码一般很简短,但每次都是一看就会,一写就废。**
|
||||
|
||||
## 其他语言版本
|
||||
|
||||
@@ -227,7 +227,23 @@ function TreeNode(val, left, right) {
|
||||
}
|
||||
```
|
||||
|
||||
TypeScript:
|
||||
|
||||
```typescript
|
||||
class TreeNode {
|
||||
public val: number;
|
||||
public left: TreeNode | null;
|
||||
public right: TreeNode | null;
|
||||
constructor(val?: number, left?: TreeNode, right?: TreeNode) {
|
||||
this.val = val === undefined ? 0 : val;
|
||||
this.left = left === undefined ? null : left;
|
||||
this.right = right === undefined ? null : right;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Swift:
|
||||
|
||||
```Swift
|
||||
class TreeNode<T> {
|
||||
var value: T
|
||||
|
||||
@@ -522,7 +522,75 @@ var postorderTraversal = function(root, res = []) {
|
||||
|
||||
```
|
||||
|
||||
TypeScript:
|
||||
|
||||
```typescript
|
||||
// 前序遍历(迭代法)
|
||||
function preorderTraversal(root: TreeNode | null): number[] {
|
||||
let helperStack: (TreeNode | null)[] = [];
|
||||
let res: number[] = [];
|
||||
let curNode: TreeNode | null;
|
||||
if (root === null) return res;
|
||||
helperStack.push(root);
|
||||
while (helperStack.length > 0) {
|
||||
curNode = helperStack.pop()!;
|
||||
if (curNode !== null) {
|
||||
if (curNode.right !== null) helperStack.push(curNode.right);
|
||||
helperStack.push(curNode);
|
||||
helperStack.push(null);
|
||||
if (curNode.left !== null) helperStack.push(curNode.left);
|
||||
} else {
|
||||
curNode = helperStack.pop()!;
|
||||
res.push(curNode.val);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
};
|
||||
|
||||
// 中序遍历(迭代法)
|
||||
function inorderTraversal(root: TreeNode | null): number[] {
|
||||
let helperStack: (TreeNode | null)[] = [];
|
||||
let res: number[] = [];
|
||||
let curNode: TreeNode | null;
|
||||
if (root === null) return res;
|
||||
helperStack.push(root);
|
||||
while (helperStack.length > 0) {
|
||||
curNode = helperStack.pop()!;
|
||||
if (curNode !== null) {
|
||||
if (curNode.right !== null) helperStack.push(curNode.right);
|
||||
helperStack.push(curNode);
|
||||
helperStack.push(null);
|
||||
if (curNode.left !== null) helperStack.push(curNode.left);
|
||||
} else {
|
||||
curNode = helperStack.pop()!;
|
||||
res.push(curNode.val);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
};
|
||||
|
||||
// 后序遍历(迭代法)
|
||||
function postorderTraversal(root: TreeNode | null): number[] {
|
||||
let helperStack: (TreeNode | null)[] = [];
|
||||
let res: number[] = [];
|
||||
let curNode: TreeNode | null;
|
||||
if (root === null) return res;
|
||||
helperStack.push(root);
|
||||
while (helperStack.length > 0) {
|
||||
curNode = helperStack.pop()!;
|
||||
if (curNode !== null) {
|
||||
if (curNode.right !== null) helperStack.push(curNode.right);
|
||||
helperStack.push(curNode);
|
||||
helperStack.push(null);
|
||||
if (curNode.left !== null) helperStack.push(curNode.left);
|
||||
} else {
|
||||
curNode = helperStack.pop()!;
|
||||
res.push(curNode.val);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
};
|
||||
```
|
||||
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
||||
@@ -454,6 +454,61 @@ var postorderTraversal = function(root, res = []) {
|
||||
};
|
||||
```
|
||||
|
||||
TypeScript:
|
||||
|
||||
```typescript
|
||||
// 前序遍历(迭代法)
|
||||
function preorderTraversal(root: TreeNode | null): number[] {
|
||||
if (root === null) return [];
|
||||
let res: number[] = [];
|
||||
let helperStack: TreeNode[] = [];
|
||||
let curNode: TreeNode = root;
|
||||
helperStack.push(curNode);
|
||||
while (helperStack.length > 0) {
|
||||
curNode = helperStack.pop()!;
|
||||
res.push(curNode.val);
|
||||
if (curNode.right !== null) helperStack.push(curNode.right);
|
||||
if (curNode.left !== null) helperStack.push(curNode.left);
|
||||
}
|
||||
return res;
|
||||
};
|
||||
|
||||
// 中序遍历(迭代法)
|
||||
function inorderTraversal(root: TreeNode | null): number[] {
|
||||
let helperStack: TreeNode[] = [];
|
||||
let res: number[] = [];
|
||||
if (root === null) return res;
|
||||
let curNode: TreeNode | null = root;
|
||||
while (curNode !== null || helperStack.length > 0) {
|
||||
if (curNode !== null) {
|
||||
helperStack.push(curNode);
|
||||
curNode = curNode.left;
|
||||
} else {
|
||||
curNode = helperStack.pop()!;
|
||||
res.push(curNode.val);
|
||||
curNode = curNode.right;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
};
|
||||
|
||||
// 后序遍历(迭代法)
|
||||
function postorderTraversal(root: TreeNode | null): number[] {
|
||||
let helperStack: TreeNode[] = [];
|
||||
let res: number[] = [];
|
||||
let curNode: TreeNode;
|
||||
if (root === null) return res;
|
||||
helperStack.push(root);
|
||||
while (helperStack.length > 0) {
|
||||
curNode = helperStack.pop()!;
|
||||
res.push(curNode.val);
|
||||
if (curNode.left !== null) helperStack.push(curNode.left);
|
||||
if (curNode.right !== null) helperStack.push(curNode.right);
|
||||
}
|
||||
return res.reverse();
|
||||
};
|
||||
```
|
||||
|
||||
Swift:
|
||||
|
||||
> 迭代法前序遍历
|
||||
|
||||
@@ -168,7 +168,7 @@ class Solution {
|
||||
```
|
||||
|
||||
Python:
|
||||
```python3
|
||||
```python
|
||||
# 前序遍历-递归-LC144_二叉树的前序遍历
|
||||
class Solution:
|
||||
def preorderTraversal(self, root: TreeNode) -> List[int]:
|
||||
@@ -270,40 +270,6 @@ func postorderTraversal(root *TreeNode) (res []int) {
|
||||
}
|
||||
```
|
||||
|
||||
javaScript:
|
||||
|
||||
```js
|
||||
|
||||
前序遍历:
|
||||
|
||||
var preorderTraversal = function(root, res = []) {
|
||||
if (!root) return res;
|
||||
res.push(root.val);
|
||||
preorderTraversal(root.left, res)
|
||||
preorderTraversal(root.right, res)
|
||||
return res;
|
||||
};
|
||||
|
||||
中序遍历:
|
||||
|
||||
var inorderTraversal = function(root, res = []) {
|
||||
if (!root) return res;
|
||||
inorderTraversal(root.left, res);
|
||||
res.push(root.val);
|
||||
inorderTraversal(root.right, res);
|
||||
return res;
|
||||
};
|
||||
|
||||
后序遍历:
|
||||
|
||||
var postorderTraversal = function(root, res = []) {
|
||||
if (!root) return res;
|
||||
postorderTraversal(root.left, res);
|
||||
postorderTraversal(root.right, res);
|
||||
res.push(root.val);
|
||||
return res;
|
||||
};
|
||||
```
|
||||
Javascript版本:
|
||||
|
||||
前序遍历:
|
||||
@@ -358,7 +324,51 @@ var postorderTraversal = function(root) {
|
||||
};
|
||||
```
|
||||
|
||||
TypeScript:
|
||||
|
||||
```typescript
|
||||
// 前序遍历
|
||||
function preorderTraversal(node: TreeNode | null): number[] {
|
||||
function traverse(node: TreeNode | null, res: number[]): void {
|
||||
if (node === null) return;
|
||||
res.push(node.val);
|
||||
traverse(node.left, res);
|
||||
traverse(node.right, res);
|
||||
}
|
||||
const res: number[] = [];
|
||||
traverse(node, res);
|
||||
return res;
|
||||
}
|
||||
|
||||
// 中序遍历
|
||||
function inorderTraversal(node: TreeNode | null): number[] {
|
||||
function traverse(node: TreeNode | null, res: number[]): void {
|
||||
if (node === null) return;
|
||||
traverse(node.left, res);
|
||||
res.push(node.val);
|
||||
traverse(node.right, res);
|
||||
}
|
||||
const res: number[] = [];
|
||||
traverse(node, res);
|
||||
return res;
|
||||
}
|
||||
|
||||
// 后序遍历
|
||||
function postorderTraversal(node: TreeNode | null): number[] {
|
||||
function traverse(node: TreeNode | null, res: number[]): void {
|
||||
if (node === null) return;
|
||||
traverse(node.left, res);
|
||||
traverse(node.right, res);
|
||||
res.push(node.val);
|
||||
}
|
||||
const res: number[] = [];
|
||||
traverse(node, res);
|
||||
return res;
|
||||
}
|
||||
```
|
||||
|
||||
C:
|
||||
|
||||
```c
|
||||
//前序遍历:
|
||||
void preOrderTraversal(struct TreeNode* root, int* ret, int* returnSize) {
|
||||
|
||||
@@ -45,21 +45,7 @@
|
||||
|
||||

|
||||
|
||||
那么此时大家是不是应该知道了,数组如何转化成 二叉树了。**如果父节点的数组下标是i,那么它的左孩子下标就是i * 2 + 1,右孩子下标就是 i * 2 + 2**。计算过程为:
|
||||
|
||||
如果父节点在第$k$层,第$m,m \in [0,2^k]$个节点,则其左孩子所在的位置必然为$k+1$层,第$2*(m-1)+1$个节点。
|
||||
|
||||
- 计算父节点在数组中的索引:
|
||||
$$
|
||||
index_{father}=(\sum_{i=0}^{i=k-1}2^i)+m-1=2^k-1+m-1
|
||||
$$
|
||||
|
||||
- 计算左子节点在数组的索引:
|
||||
$$
|
||||
index_{left}=(\sum_{i=0}^{i=k}2^i)+2*m-1-1=2^{k+1}+2m-3
|
||||
$$
|
||||
|
||||
- 故左孩子的下表为$index_{left}=index_{father}\times2+1$,同理可得到右子孩子的索引关系。也可以直接在左子孩子的基础上`+1`。
|
||||
那么此时大家是不是应该知道了,数组如何转化成 二叉树了。**如果父节点的数组下标是i,那么它的左孩子下标就是i * 2 + 1,右孩子下标就是 i * 2 + 2**。
|
||||
|
||||
那么这里又有同学疑惑了,这些我都懂了,但我还是不知道 应该 怎么构造。
|
||||
|
||||
@@ -251,7 +237,4 @@ int main() {
|
||||
```
|
||||
|
||||
-----------------------
|
||||
* 作者微信:[程序员Carl](https://mp.weixin.qq.com/s/b66DFkOp8OOxdZC_xLZxfw)
|
||||
* B站视频:[代码随想录](https://space.bilibili.com/525438321)
|
||||
* 知识星球:[代码随想录](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ)
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码.jpg width=450> </img></div>
|
||||
|
||||
@@ -218,7 +218,4 @@ leetcode是专门针对算法练习的题库,leetcode现在也推出了中文
|
||||
|
||||
|
||||
-----------------------
|
||||
* 作者微信:[程序员Carl](https://mp.weixin.qq.com/s/b66DFkOp8OOxdZC_xLZxfw)
|
||||
* B站视频:[代码随想录](https://space.bilibili.com/525438321)
|
||||
* 知识星球:[代码随想录](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ)
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码.jpg width=450> </img></div>
|
||||
|
||||
@@ -280,7 +280,4 @@ public class TimeComplexity {
|
||||
|
||||
|
||||
-----------------------
|
||||
* 作者微信:[程序员Carl](https://mp.weixin.qq.com/s/b66DFkOp8OOxdZC_xLZxfw)
|
||||
* B站视频:[代码随想录](https://space.bilibili.com/525438321)
|
||||
* 知识星球:[代码随想录](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ)
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码.jpg width=450> </img></div>
|
||||
|
||||
@@ -130,7 +130,4 @@
|
||||
|
||||
|
||||
-----------------------
|
||||
* 作者微信:[程序员Carl](https://mp.weixin.qq.com/s/b66DFkOp8OOxdZC_xLZxfw)
|
||||
* B站视频:[代码随想录](https://space.bilibili.com/525438321)
|
||||
* 知识星球:[代码随想录](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ)
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码.jpg width=450> </img></div>
|
||||
|
||||
@@ -119,7 +119,4 @@ int main() {
|
||||
|
||||
|
||||
-----------------------
|
||||
* 作者微信:[程序员Carl](https://mp.weixin.qq.com/s/b66DFkOp8OOxdZC_xLZxfw)
|
||||
* B站视频:[代码随想录](https://space.bilibili.com/525438321)
|
||||
* 知识星球:[代码随想录](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ)
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码.jpg width=450> </img></div>
|
||||
|
||||
@@ -170,7 +170,4 @@ $O(2 × n^2 + 10 × n + 1000) < O(3 × n^2)$,所以说最后省略掉常数项
|
||||
|
||||
|
||||
-----------------------
|
||||
* 作者微信:[程序员Carl](https://mp.weixin.qq.com/s/b66DFkOp8OOxdZC_xLZxfw)
|
||||
* B站视频:[代码随想录](https://space.bilibili.com/525438321)
|
||||
* 知识星球:[代码随想录](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ)
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码.jpg width=450> </img></div>
|
||||
|
||||
@@ -73,7 +73,4 @@ for (int i = 0; i < n; i++) {
|
||||
|
||||
|
||||
-----------------------
|
||||
* 作者微信:[程序员Carl](https://mp.weixin.qq.com/s/b66DFkOp8OOxdZC_xLZxfw)
|
||||
* B站视频:[代码随想录](https://space.bilibili.com/525438321)
|
||||
* 知识星球:[代码随想录](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ)
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码.jpg width=450> </img></div>
|
||||
|
||||
@@ -150,7 +150,4 @@ char型的数据和int型的数据挨在一起,该int数据从地址1开始,
|
||||
|
||||
|
||||
-----------------------
|
||||
* 作者微信:[程序员Carl](https://mp.weixin.qq.com/s/b66DFkOp8OOxdZC_xLZxfw)
|
||||
* B站视频:[代码随想录](https://space.bilibili.com/525438321)
|
||||
* 知识星球:[代码随想录](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ)
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码.jpg width=450> </img></div>
|
||||
|
||||
@@ -67,7 +67,4 @@ int main() {
|
||||
|
||||
|
||||
-----------------------
|
||||
* 作者微信:[程序员Carl](https://mp.weixin.qq.com/s/b66DFkOp8OOxdZC_xLZxfw)
|
||||
* B站视频:[代码随想录](https://space.bilibili.com/525438321)
|
||||
* 知识星球:[代码随想录](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ)
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码.jpg width=450> </img></div>
|
||||
|
||||
@@ -116,7 +116,4 @@
|
||||
|
||||
|
||||
-----------------------
|
||||
* 作者微信:[程序员Carl](https://mp.weixin.qq.com/s/b66DFkOp8OOxdZC_xLZxfw)
|
||||
* B站视频:[代码随想录](https://space.bilibili.com/525438321)
|
||||
* 知识星球:[代码随想录](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ)
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码.jpg width=450> </img></div>
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
## 一线互联网
|
||||
|
||||
* 微信(总部) 有点难进!
|
||||
* 字节跳动(广州)
|
||||
|
||||
## 二线
|
||||
* 网易(总部)主要是游戏
|
||||
@@ -79,7 +80,4 @@
|
||||
|
||||
|
||||
-----------------------
|
||||
* 作者微信:[程序员Carl](https://mp.weixin.qq.com/s/b66DFkOp8OOxdZC_xLZxfw)
|
||||
* B站视频:[代码随想录](https://space.bilibili.com/525438321)
|
||||
* 知识星球:[代码随想录](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ)
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码.jpg width=450> </img></div>
|
||||
|
||||
@@ -77,7 +77,4 @@
|
||||
|
||||
|
||||
-----------------------
|
||||
* 作者微信:[程序员Carl](https://mp.weixin.qq.com/s/b66DFkOp8OOxdZC_xLZxfw)
|
||||
* B站视频:[代码随想录](https://space.bilibili.com/525438321)
|
||||
* 知识星球:[代码随想录](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ)
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码.jpg width=450> </img></div>
|
||||
|
||||
@@ -87,7 +87,4 @@
|
||||
|
||||
|
||||
-----------------------
|
||||
* 作者微信:[程序员Carl](https://mp.weixin.qq.com/s/b66DFkOp8OOxdZC_xLZxfw)
|
||||
* B站视频:[代码随想录](https://space.bilibili.com/525438321)
|
||||
* 知识星球:[代码随想录](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ)
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码.jpg width=450> </img></div>
|
||||
|
||||
@@ -82,7 +82,4 @@
|
||||
|
||||
|
||||
-----------------------
|
||||
* 作者微信:[程序员Carl](https://mp.weixin.qq.com/s/b66DFkOp8OOxdZC_xLZxfw)
|
||||
* B站视频:[代码随想录](https://space.bilibili.com/525438321)
|
||||
* 知识星球:[代码随想录](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ)
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码.jpg width=450> </img></div>
|
||||
|
||||
@@ -135,9 +135,5 @@ Markdown支持部分html,例如这样
|
||||
|
||||
|
||||
|
||||
|
||||
-----------------------
|
||||
* 作者微信:[程序员Carl](https://mp.weixin.qq.com/s/b66DFkOp8OOxdZC_xLZxfw)
|
||||
* B站视频:[代码随想录](https://space.bilibili.com/525438321)
|
||||
* 知识星球:[代码随想录](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ)
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码.jpg width=450> </img></div>
|
||||
|
||||
@@ -133,7 +133,4 @@ Carl校招社招都拿过大厂的offer,同时也看过很多应聘者的简
|
||||
|
||||
|
||||
-----------------------
|
||||
* 作者微信:[程序员Carl](https://mp.weixin.qq.com/s/b66DFkOp8OOxdZC_xLZxfw)
|
||||
* B站视频:[代码随想录](https://space.bilibili.com/525438321)
|
||||
* 知识星球:[代码随想录](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ)
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码.jpg width=450> </img></div>
|
||||
|
||||
@@ -269,7 +269,4 @@ int binary_search( int arr[], int l, int r, int x) {
|
||||
|
||||
|
||||
-----------------------
|
||||
* 作者微信:[程序员Carl](https://mp.weixin.qq.com/s/b66DFkOp8OOxdZC_xLZxfw)
|
||||
* B站视频:[代码随想录](https://space.bilibili.com/525438321)
|
||||
* 知识星球:[代码随想录](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ)
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码.jpg width=450> </img></div>
|
||||
|
||||
@@ -152,7 +152,4 @@ int function3(int x, int n) {
|
||||
|
||||
|
||||
-----------------------
|
||||
* 作者微信:[程序员Carl](https://mp.weixin.qq.com/s/b66DFkOp8OOxdZC_xLZxfw)
|
||||
* B站视频:[代码随想录](https://space.bilibili.com/525438321)
|
||||
* 知识星球:[代码随想录](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ)
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码.jpg width=450> </img></div>
|
||||
|
||||
@@ -118,7 +118,7 @@
|
||||
|
||||

|
||||
|
||||
这个图是 [代码随想录知识星球](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ) 成员:[青](https://wx.zsxq.com/dweb2/index/footprint/185251215558842),所画,总结的非常好,分享给大家。
|
||||
这个图是 [代码随想录知识星球](https://programmercarl.com/other/kstar.html) 成员:[青](https://wx.zsxq.com/dweb2/index/footprint/185251215558842),所画,总结的非常好,分享给大家。
|
||||
|
||||
这已经是全网对动规最深刻的讲解系列了。
|
||||
|
||||
|
||||
@@ -34,8 +34,8 @@ public:
|
||||
|
||||
// 此时就是:左右节点都不为空,且数值相同的情况
|
||||
// 此时才做递归,做下一层的判断
|
||||
bool outside = compare(left->left, right->right); // 左子树:左、 右子树:左 (相对于求对称二叉树,只需改一下这里的顺序)
|
||||
bool inside = compare(left->right, right->left); // 左子树:右、 右子树:右
|
||||
bool outside = compare(left->left, right->left); // 左子树:左、 右子树:左 (相对于求对称二叉树,只需改一下这里的顺序)
|
||||
bool inside = compare(left->right, right->right); // 左子树:右、 右子树:右
|
||||
bool isSame = outside && inside; // 左子树:中、 右子树:中 (逻辑处理)
|
||||
return isSame;
|
||||
|
||||
|
||||
@@ -432,7 +432,7 @@ N皇后问题分析:
|
||||
|
||||

|
||||
|
||||
这个图是 [代码随想录知识星球](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ) 成员:[莫非毛](https://wx.zsxq.com/dweb2/index/footprint/828844212542),所画,总结的非常好,分享给大家。
|
||||
这个图是 [代码随想录知识星球](https://programmercarl.com/other/kstar.html) 成员:[莫非毛](https://wx.zsxq.com/dweb2/index/footprint/828844212542),所画,总结的非常好,分享给大家。
|
||||
|
||||
**回溯算法系列正式结束,新的系列终将开始,录友们准备开启新的征程!**
|
||||
|
||||
|
||||
@@ -158,22 +158,5 @@ cd a/b/c/../../
|
||||
好了,栈与队列我们就总结到这里了,接下来Carl就要带大家开启新的篇章了,大家加油!
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## 其他语言版本
|
||||
|
||||
|
||||
Java:
|
||||
|
||||
|
||||
Python:
|
||||
|
||||
|
||||
Go:
|
||||
|
||||
|
||||
|
||||
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
||||
265
problems/算法模板.md
265
problems/算法模板.md
@@ -394,7 +394,7 @@ var postorder = function (root, list) {
|
||||
```javascript
|
||||
var preorderTraversal = function (root) {
|
||||
let res = [];
|
||||
if (root === null) return rs;
|
||||
if (root === null) return res;
|
||||
let stack = [root],
|
||||
cur = null;
|
||||
while (stack.length) {
|
||||
@@ -536,6 +536,269 @@ function backtracking(参数) {
|
||||
}
|
||||
```
|
||||
|
||||
TypeScript:
|
||||
|
||||
## 二分查找法
|
||||
|
||||
使用左闭右闭区间
|
||||
|
||||
```typescript
|
||||
var search = function (nums: number[], target: number): number {
|
||||
let left: number = 0, right: number = nums.length - 1;
|
||||
// 使用左闭右闭区间
|
||||
while (left <= right) {
|
||||
let mid: number = left + Math.floor((right - left)/2);
|
||||
if (nums[mid] > target) {
|
||||
right = mid - 1; // 去左面闭区间寻找
|
||||
} else if (nums[mid] < target) {
|
||||
left = mid + 1; // 去右面闭区间寻找
|
||||
} else {
|
||||
return mid;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
};
|
||||
```
|
||||
|
||||
使用左闭右开区间
|
||||
|
||||
```typescript
|
||||
var search = function (nums: number[], target: number): number {
|
||||
let left: number = 0, right: number = nums.length;
|
||||
// 使用左闭右开区间 [left, right)
|
||||
while (left < right) {
|
||||
let mid: number = left + Math.floor((right - left)/2);
|
||||
if (nums[mid] > target) {
|
||||
right = mid; // 去左面闭区间寻找
|
||||
} else if (nums[mid] < target) {
|
||||
left = mid + 1; // 去右面闭区间寻找
|
||||
} else {
|
||||
return mid;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
};
|
||||
```
|
||||
|
||||
## KMP
|
||||
|
||||
```typescript
|
||||
var kmp = function (next: number[], s: number): void {
|
||||
next[0] = -1;
|
||||
let j: number = -1;
|
||||
for(let i: number = 1; i < s.length; i++){
|
||||
while (j >= 0 && s[i] !== s[j + 1]) {
|
||||
j = next[j];
|
||||
}
|
||||
if (s[i] === s[j + 1]) {
|
||||
j++;
|
||||
}
|
||||
next[i] = j;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 二叉树
|
||||
|
||||
### 深度优先遍历(递归)
|
||||
|
||||
二叉树节点定义:
|
||||
|
||||
```typescript
|
||||
class TreeNode {
|
||||
val: number
|
||||
left: TreeNode | null
|
||||
right: TreeNode | null
|
||||
constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) {
|
||||
this.val = (val===undefined ? 0 : val)
|
||||
this.left = (left===undefined ? null : left)
|
||||
this.right = (right===undefined ? null : right)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
前序遍历(中左右):
|
||||
|
||||
```typescript
|
||||
var preorder = function (root: TreeNode | null, list: number[]): void {
|
||||
if (root === null) return;
|
||||
list.push(root.val); // 中
|
||||
preorder(root.left, list); // 左
|
||||
preorder(root.right, list); // 右
|
||||
}
|
||||
```
|
||||
|
||||
中序遍历(左中右):
|
||||
|
||||
```typescript
|
||||
var inorder = function (root: TreeNode | null, list: number[]): void {
|
||||
if (root === null) return;
|
||||
inorder(root.left, list); // 左
|
||||
list.push(root.val); // 中
|
||||
inorder(root.right, list); // 右
|
||||
}
|
||||
```
|
||||
|
||||
后序遍历(左右中):
|
||||
|
||||
```typescript
|
||||
var postorder = function (root: TreeNode | null, list: number[]): void {
|
||||
if (root === null) return;
|
||||
postorder(root.left, list); // 左
|
||||
postorder(root.right, list); // 右
|
||||
list.push(root.val); // 中
|
||||
}
|
||||
```
|
||||
|
||||
### 深度优先遍历(迭代)
|
||||
|
||||
前序遍历(中左右):
|
||||
|
||||
```typescript
|
||||
var preorderTraversal = function (root: TreeNode | null): number[] {
|
||||
let res: number[] = [];
|
||||
if (root === null) return res;
|
||||
let stack: TreeNode[] = [root],
|
||||
cur: TreeNode | null = null;
|
||||
while (stack.length) {
|
||||
cur = stack.pop();
|
||||
res.push(cur.val);
|
||||
cur.right && stack.push(cur.right);
|
||||
cur.left && stack.push(cur.left);
|
||||
}
|
||||
return res;
|
||||
};
|
||||
```
|
||||
|
||||
中序遍历(左中右):
|
||||
|
||||
```typescript
|
||||
var inorderTraversal = function (root: TreeNode | null): number[] {
|
||||
let res: number[] = [];
|
||||
if (root === null) return res;
|
||||
let stack: TreeNode[] = [];
|
||||
let cur: TreeNode | null = root;
|
||||
while (stack.length !== 0 || cur !== null) {
|
||||
if (cur !== null) {
|
||||
stack.push(cur);
|
||||
cur = cur.left;
|
||||
} else {
|
||||
cur = stack.pop();
|
||||
res.push(cur.val);
|
||||
cur = cur.right;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
};
|
||||
```
|
||||
|
||||
后序遍历(左右中):
|
||||
|
||||
```typescript
|
||||
var postorderTraversal = function (root: TreeNode | null): number[] {
|
||||
let res: number[] = [];
|
||||
if (root === null) return res;
|
||||
let stack: TreeNode[] = [root];
|
||||
let cur: TreeNode | null = null;
|
||||
while (stack.length) {
|
||||
cur = stack.pop();
|
||||
res.push(cur.val);
|
||||
cur.left && stack.push(cur.left);
|
||||
cur.right && stack.push(cur.right);
|
||||
}
|
||||
return res.reverse()
|
||||
};
|
||||
```
|
||||
|
||||
### 广度优先遍历(队列)
|
||||
|
||||
```typescript
|
||||
var levelOrder = function (root: TreeNode | null): number[] {
|
||||
let res: number[] = [];
|
||||
if (root === null) return res;
|
||||
let queue: TreeNode[] = [root];
|
||||
while (queue.length) {
|
||||
let n: number = queue.length;
|
||||
let temp: number[] = [];
|
||||
for (let i: number = 0; i < n; i++) {
|
||||
let node: TreeNode = queue.shift();
|
||||
temp.push(node.val);
|
||||
node.left && queue.push(node.left);
|
||||
node.right && queue.push(node.right);
|
||||
}
|
||||
res.push(temp);
|
||||
}
|
||||
return res;
|
||||
};
|
||||
```
|
||||
|
||||
### 二叉树深度
|
||||
|
||||
```typescript
|
||||
var getDepth = function (node: TreNode | null): number {
|
||||
if (node === null) return 0;
|
||||
return 1 + Math.max(getDepth(node.left), getDepth(node.right));
|
||||
}
|
||||
```
|
||||
|
||||
### 二叉树节点数量
|
||||
|
||||
```typescript
|
||||
var countNodes = function (root: TreeNode | null): number {
|
||||
if (root === null) return 0;
|
||||
return 1 + countNodes(root.left) + countNodes(root.right);
|
||||
}
|
||||
```
|
||||
|
||||
## 回溯算法
|
||||
|
||||
```typescript
|
||||
function backtracking(参数) {
|
||||
if (终止条件) {
|
||||
存放结果;
|
||||
return;
|
||||
}
|
||||
|
||||
for (选择:本层集合中元素(树中节点孩子的数量就是集合的大小)) {
|
||||
处理节点;
|
||||
backtracking(路径,选择列表); // 递归
|
||||
回溯,撤销处理结果
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## 并查集
|
||||
|
||||
```typescript
|
||||
let n: number = 1005; // 根据题意而定
|
||||
let father: number[] = new Array(n).fill(0);
|
||||
|
||||
// 并查集初始化
|
||||
function init () {
|
||||
for (int i: number = 0; i < n; ++i) {
|
||||
father[i] = i;
|
||||
}
|
||||
}
|
||||
// 并查集里寻根的过程
|
||||
function find (u: number): number {
|
||||
return u === father[u] ? u : father[u] = find(father[u]);
|
||||
}
|
||||
// 将v->u 这条边加入并查集
|
||||
function join(u: number, v: number) {
|
||||
u = find(u);
|
||||
v = find(v);
|
||||
if (u === v) return ;
|
||||
father[v] = u;
|
||||
}
|
||||
// 判断 u 和 v是否找到同一个根
|
||||
function same(u: number, v: number): boolean {
|
||||
u = find(u);
|
||||
v = find(v);
|
||||
return u === v;
|
||||
}
|
||||
```
|
||||
|
||||
Java:
|
||||
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user