mirror of
https://github.com/youngyangyang04/leetcode-master.git
synced 2025-07-09 11:34:46 +08:00
Merge branch 'master' of github.com:youngyangyang04/leetcode-master
This commit is contained in:
@ -349,6 +349,7 @@ function twoSum(nums: number[], target: number): number[] {
|
|||||||
index = helperMap.get(target - nums[i]);
|
index = helperMap.get(target - nums[i]);
|
||||||
if (index !== undefined) {
|
if (index !== undefined) {
|
||||||
resArr = [i, index];
|
resArr = [i, index];
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
helperMap.set(nums[i], i);
|
helperMap.set(nums[i], i);
|
||||||
}
|
}
|
||||||
|
@ -260,7 +260,7 @@ class Solution {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//每次迭代获取一个字符串,所以会设计大量的字符串拼接,所以这里选择更为高效的 StringBuilder
|
//每次迭代获取一个字符串,所以会涉及大量的字符串拼接,所以这里选择更为高效的 StringBuilder
|
||||||
StringBuilder temp = new StringBuilder();
|
StringBuilder temp = new StringBuilder();
|
||||||
|
|
||||||
//比如digits如果为"23",num 为0,则str表示2对应的 abc
|
//比如digits如果为"23",num 为0,则str表示2对应的 abc
|
||||||
@ -274,7 +274,7 @@ class Solution {
|
|||||||
String str = numString[digits.charAt(num) - '0'];
|
String str = numString[digits.charAt(num) - '0'];
|
||||||
for (int i = 0; i < str.length(); i++) {
|
for (int i = 0; i < str.length(); i++) {
|
||||||
temp.append(str.charAt(i));
|
temp.append(str.charAt(i));
|
||||||
//c
|
//递归,处理下一层
|
||||||
backTracking(digits, numString, num + 1);
|
backTracking(digits, numString, num + 1);
|
||||||
//剔除末尾的继续尝试
|
//剔除末尾的继续尝试
|
||||||
temp.deleteCharAt(temp.length() - 1);
|
temp.deleteCharAt(temp.length() - 1);
|
||||||
|
@ -22,10 +22,12 @@
|
|||||||
|
|
||||||
输入:head = [1,2,3,4,5], n = 2
|
输入:head = [1,2,3,4,5], n = 2
|
||||||
输出:[1,2,3,5]
|
输出:[1,2,3,5]
|
||||||
|
|
||||||
示例 2:
|
示例 2:
|
||||||
|
|
||||||
输入:head = [1], n = 1
|
输入:head = [1], n = 1
|
||||||
输出:[]
|
输出:[]
|
||||||
|
|
||||||
示例 3:
|
示例 3:
|
||||||
|
|
||||||
输入:head = [1,2], n = 1
|
输入:head = [1,2], n = 1
|
||||||
@ -111,7 +113,6 @@ class Solution {
|
|||||||
for (int i = 0; i <= n; i++) {
|
for (int i = 0; i <= n; i++) {
|
||||||
fastIndex = fastIndex.next;
|
fastIndex = fastIndex.next;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (fastIndex != null) {
|
while (fastIndex != null) {
|
||||||
fastIndex = fastIndex.next;
|
fastIndex = fastIndex.next;
|
||||||
slowIndex = slowIndex.next;
|
slowIndex = slowIndex.next;
|
||||||
@ -193,16 +194,18 @@ func removeNthFromEnd(head *ListNode, n int) *ListNode {
|
|||||||
* @param {number} n
|
* @param {number} n
|
||||||
* @return {ListNode}
|
* @return {ListNode}
|
||||||
*/
|
*/
|
||||||
var removeNthFromEnd = function(head, n) {
|
var removeNthFromEnd = function (head, n) {
|
||||||
let ret = new ListNode(0, head),
|
// 创建哨兵节点,简化解题逻辑
|
||||||
slow = fast = ret;
|
let dummyHead = new ListNode(0, head);
|
||||||
while(n--) fast = fast.next;
|
let fast = dummyHead;
|
||||||
while (fast.next !== null) {
|
let slow = dummyHead;
|
||||||
fast = fast.next;
|
while (n--) fast = fast.next;
|
||||||
slow = slow.next
|
while (fast.next !== null) {
|
||||||
};
|
slow = slow.next;
|
||||||
slow.next = slow.next.next;
|
fast = fast.next;
|
||||||
return ret.next;
|
}
|
||||||
|
slow.next = slow.next.next;
|
||||||
|
return dummyHead.next;
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
### TypeScript:
|
### TypeScript:
|
||||||
|
@ -476,6 +476,32 @@ public class Solution {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
###Dart:
|
||||||
|
```dart
|
||||||
|
int removeElement(List<int> nums, int val) {
|
||||||
|
//相向双指针法
|
||||||
|
var left = 0;
|
||||||
|
var right = nums.length - 1;
|
||||||
|
while (left <= right) {
|
||||||
|
//寻找左侧的val,将其被右侧非val覆盖
|
||||||
|
if (nums[left] == val) {
|
||||||
|
while (nums[right] == val&&left<=right) {
|
||||||
|
right--;
|
||||||
|
if (right < 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nums[left] = nums[right--];
|
||||||
|
} else {
|
||||||
|
left++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//覆盖后可以将0至left部分视为所需部分
|
||||||
|
return left;
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
|
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
|
||||||
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
|
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
|
||||||
|
@ -313,18 +313,18 @@ func searchInsert(nums []int, target int) int {
|
|||||||
|
|
||||||
```rust
|
```rust
|
||||||
impl Solution {
|
impl Solution {
|
||||||
pub fn search_insert(nums: Vec<i32>, target: i32) -> i32 {
|
pub fn search_insert(nums: Vec<i32>, target: i32) -> i32 {
|
||||||
let mut left = 0;
|
use std::cmp::Ordering::{Equal, Greater, Less};
|
||||||
let mut right = nums.len();
|
let (mut left, mut right) = (0, nums.len() as i32 - 1);
|
||||||
while left < right {
|
while left <= right {
|
||||||
let mid = (left + right) / 2;
|
let mid = (left + right) / 2;
|
||||||
match nums[mid].cmp(&target) {
|
match nums[mid as usize].cmp(&target) {
|
||||||
Ordering::Less => left = mid + 1,
|
Less => left = mid + 1,
|
||||||
Ordering::Equal => return ((left + right) / 2) as i32,
|
Equal => return mid,
|
||||||
Ordering::Greater => right = mid,
|
Greater => right = mid - 1,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
((left + right) / 2) as i32
|
right + 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -224,7 +224,7 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
### Java
|
### Java
|
||||||
|
解法一:
|
||||||
```java
|
```java
|
||||||
class Solution {
|
class Solution {
|
||||||
public void solveSudoku(char[][] board) {
|
public void solveSudoku(char[][] board) {
|
||||||
@ -291,7 +291,73 @@ class Solution {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
解法二(bitmap标记)
|
||||||
|
```
|
||||||
|
class Solution{
|
||||||
|
int[] rowBit = new int[9];
|
||||||
|
int[] colBit = new int[9];
|
||||||
|
int[] square9Bit = new int[9];
|
||||||
|
|
||||||
|
public void solveSudoku(char[][] board) {
|
||||||
|
// 1 10 11
|
||||||
|
for (int y = 0; y < board.length; y++) {
|
||||||
|
for (int x = 0; x < board[y].length; x++) {
|
||||||
|
int numBit = 1 << (board[y][x] - '1');
|
||||||
|
rowBit[y] ^= numBit;
|
||||||
|
colBit[x] ^= numBit;
|
||||||
|
square9Bit[(y / 3) * 3 + x / 3] ^= numBit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
backtrack(board, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean backtrack(char[][] board, int n) {
|
||||||
|
if (n >= 81) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 快速算出行列编号 n/9 n%9
|
||||||
|
int row = n / 9;
|
||||||
|
int col = n % 9;
|
||||||
|
|
||||||
|
if (board[row][col] != '.') {
|
||||||
|
return backtrack(board, n + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (char c = '1'; c <= '9'; c++) {
|
||||||
|
int numBit = 1 << (c - '1');
|
||||||
|
if (!isValid(numBit, row, col)) continue;
|
||||||
|
{
|
||||||
|
board[row][col] = c; // 当前的数字放入到数组之中,
|
||||||
|
rowBit[row] ^= numBit; // 第一行rowBit[0],第一个元素eg: 1 , 0^1=1,第一个元素:4, 100^1=101,...
|
||||||
|
colBit[col] ^= numBit;
|
||||||
|
square9Bit[(row / 3) * 3 + col / 3] ^= numBit;
|
||||||
|
}
|
||||||
|
if (backtrack(board, n + 1)) return true;
|
||||||
|
{
|
||||||
|
board[row][col] = '.'; // 不满足条件,回退成'.'
|
||||||
|
rowBit[row] &= ~numBit; // 第一行rowBit[0],第一个元素eg: 1 , 101&=~1==>101&111111110==>100
|
||||||
|
colBit[col] &= ~numBit;
|
||||||
|
square9Bit[(row / 3) * 3 + col / 3] &= ~numBit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
boolean isValid(int numBit, int row, int col) {
|
||||||
|
// 左右
|
||||||
|
if ((rowBit[row] & numBit) > 0) return false;
|
||||||
|
// 上下
|
||||||
|
if ((colBit[col] & numBit) > 0) return false;
|
||||||
|
// 9宫格: 快速算出第n个九宫格,编号[0,8] , 编号=(row / 3) * 3 + col / 3
|
||||||
|
if ((square9Bit[(row / 3) * 3 + col / 3] & numBit) > 0) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
### Python
|
### Python
|
||||||
|
|
||||||
```python
|
```python
|
||||||
|
@ -311,7 +311,7 @@ class Solution:
|
|||||||
|
|
||||||
for i in range(startIndex, len(candidates)):
|
for i in range(startIndex, len(candidates)):
|
||||||
if total + candidates[i] > target:
|
if total + candidates[i] > target:
|
||||||
continue
|
break
|
||||||
total += candidates[i]
|
total += candidates[i]
|
||||||
path.append(candidates[i])
|
path.append(candidates[i])
|
||||||
self.backtracking(candidates, target, total, i, path, result)
|
self.backtracking(candidates, target, total, i, path, result)
|
||||||
|
@ -145,7 +145,7 @@ public:
|
|||||||
int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
|
int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
|
||||||
int m = obstacleGrid.size();
|
int m = obstacleGrid.size();
|
||||||
int n = obstacleGrid[0].size();
|
int n = obstacleGrid[0].size();
|
||||||
if (obstacleGrid[m - 1][n - 1] == 1 || obstacleGrid[0][0] == 1) //如果在起点或终点出现了障碍,直接返回0
|
if (obstacleGrid[m - 1][n - 1] == 1 || obstacleGrid[0][0] == 1) //如果在起点或终点出现了障碍,直接返回0
|
||||||
return 0;
|
return 0;
|
||||||
vector<vector<int>> dp(m, vector<int>(n, 0));
|
vector<vector<int>> dp(m, vector<int>(n, 0));
|
||||||
for (int i = 0; i < m && obstacleGrid[i][0] == 0; i++) dp[i][0] = 1;
|
for (int i = 0; i < m && obstacleGrid[i][0] == 0; i++) dp[i][0] = 1;
|
||||||
|
@ -211,10 +211,33 @@ func main() {
|
|||||||
```
|
```
|
||||||
|
|
||||||
### JavaScript:
|
### JavaScript:
|
||||||
|
```javaScript
|
||||||
|
var climbStairs = function (n) {
|
||||||
|
let dp = new Array(n + 1).fill(0);
|
||||||
|
dp[0] = 1;
|
||||||
|
// 排列题,注意循环顺序,背包在外物品在内
|
||||||
|
for (let j = 1; j <= n; j++) {//遍历背包
|
||||||
|
for (let i = 1; i <= 2; i++) {//遍历物品
|
||||||
|
if (j - i >= 0) dp[j] = dp[j] + dp[j - i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dp[n];
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### TypeScript:
|
### TypeScript:
|
||||||
|
```typescript
|
||||||
|
var climbStairs = function (n: number): number {
|
||||||
|
let dp: number[] = new Array(n + 1).fill(0);
|
||||||
|
dp[0] = 1;
|
||||||
|
for (let j = 1; j <= n; j++) {//遍历背包
|
||||||
|
for (let i = 1; i <= 2; i++) {//遍历物品
|
||||||
|
if (j - i >= 0) dp[j] = dp[j] + dp[j - i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dp[n];
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### Rust:
|
### Rust:
|
||||||
|
|
||||||
|
@ -469,28 +469,58 @@ func dfs(n int, k int, start int) {
|
|||||||
```
|
```
|
||||||
|
|
||||||
### Javascript
|
### Javascript
|
||||||
|
未剪枝:
|
||||||
|
|
||||||
|
```js
|
||||||
|
var combine = function (n, k) {
|
||||||
|
// 回溯法
|
||||||
|
let result = [],
|
||||||
|
path = [];
|
||||||
|
let backtracking = (_n, _k, startIndex) => {
|
||||||
|
// 终止条件
|
||||||
|
if (path.length === _k) {
|
||||||
|
result.push(path.slice());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 循环本层集合元素
|
||||||
|
for (let i = startIndex; i <= _n; i++) {
|
||||||
|
path.push(i);
|
||||||
|
// 递归
|
||||||
|
backtracking(_n, _k, i + 1);
|
||||||
|
// 回溯操作
|
||||||
|
path.pop();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
backtracking(n, k, 1);
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
剪枝:
|
剪枝:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
let result = []
|
var combine = function (n, k) {
|
||||||
let path = []
|
// 回溯法
|
||||||
var combine = function(n, k) {
|
let result = [],
|
||||||
result = []
|
path = [];
|
||||||
combineHelper(n, k, 1)
|
let backtracking = (_n, _k, startIndex) => {
|
||||||
return result
|
// 终止条件
|
||||||
|
if (path.length === _k) {
|
||||||
|
result.push(path.slice());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 循环本层集合元素
|
||||||
|
for (let i = startIndex; i <= _n - (_k - path.length) + 1; i++) {
|
||||||
|
path.push(i);
|
||||||
|
// 递归
|
||||||
|
backtracking(_n, _k, i + 1);
|
||||||
|
// 回溯操作
|
||||||
|
path.pop();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
backtracking(n, k, 1);
|
||||||
|
return result;
|
||||||
};
|
};
|
||||||
const combineHelper = (n, k, startIndex) => {
|
|
||||||
if (path.length === k) {
|
|
||||||
result.push([...path])
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for (let i = startIndex; i <= n - (k - path.length) + 1; ++i) {
|
|
||||||
path.push(i)
|
|
||||||
combineHelper(n, k, i + 1)
|
|
||||||
path.pop()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### TypeScript
|
### TypeScript
|
||||||
|
@ -129,7 +129,7 @@ class Solution {
|
|||||||
return resList;
|
return resList;
|
||||||
}
|
}
|
||||||
|
|
||||||
//DFS--递归方式
|
//BFS--递归方式
|
||||||
public void checkFun01(TreeNode node, Integer deep) {
|
public void checkFun01(TreeNode node, Integer deep) {
|
||||||
if (node == null) return;
|
if (node == null) return;
|
||||||
deep++;
|
deep++;
|
||||||
@ -692,27 +692,29 @@ func levelOrderBottom(root *TreeNode) [][]int {
|
|||||||
#### Javascript:
|
#### Javascript:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var levelOrderBottom = function(root) {
|
var levelOrderBottom = function (root) {
|
||||||
let res = [], queue = [];
|
let res = [],
|
||||||
queue.push(root);
|
queue = [];
|
||||||
while(queue.length && root!==null) {
|
queue.push(root);
|
||||||
// 存放当前层级节点数组
|
while (queue.length && root !== null) {
|
||||||
let curLevel = [];
|
// 存放当前层级节点数组
|
||||||
// 计算当前层级节点数量
|
let curLevel = [];
|
||||||
let length = queue.length;
|
// 计算当前层级节点数量
|
||||||
while(length--) {
|
let length = queue.length;
|
||||||
let node = queue.shift();
|
while (length--) {
|
||||||
// 把当前层节点存入curLevel数组
|
let node = queue.shift();
|
||||||
curLevel.push(node.val);
|
// 把当前层节点存入curLevel数组
|
||||||
// 把下一层级的左右节点存入queue队列
|
curLevel.push(node.val);
|
||||||
node.left && queue.push(node.left);
|
// 把下一层级的左右节点存入queue队列
|
||||||
node.right && queue.push(node.right);
|
node.left && queue.push(node.left);
|
||||||
}
|
node.right && queue.push(node.right);
|
||||||
// 从数组前头插入值,避免最后反转数组,减少运算时间
|
|
||||||
res.unshift(curLevel);
|
|
||||||
}
|
}
|
||||||
return res;
|
// 从数组前头插入值,避免最后反转数组,减少运算时间
|
||||||
|
res.unshift(curLevel);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
};
|
};
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
#### TypeScript:
|
#### TypeScript:
|
||||||
@ -1140,7 +1142,7 @@ impl Solution {
|
|||||||
|
|
||||||
### 思路
|
### 思路
|
||||||
|
|
||||||
本题就是层序遍历的时候把一层求个总和在取一个均值。
|
本题就是层序遍历的时候把一层求个总和再取一个均值。
|
||||||
|
|
||||||
C++代码:
|
C++代码:
|
||||||
|
|
||||||
@ -1295,26 +1297,26 @@ func averageOfLevels(root *TreeNode) []float64 {
|
|||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var averageOfLevels = function(root) {
|
var averageOfLevels = function(root) {
|
||||||
//层级平均值
|
let res = [],
|
||||||
let res = [], queue = [];
|
queue = [];
|
||||||
queue.push(root);
|
queue.push(root);
|
||||||
|
while (queue.length) {
|
||||||
while(queue.length && root!==null) {
|
// 每一层节点个数;
|
||||||
//每一层节点个数
|
let lengthLevel = queue.length,
|
||||||
let length = queue.length;
|
len = queue.length,
|
||||||
//sum记录每一层的和
|
// sum记录每一层的和;
|
||||||
let sum = 0;
|
sum = 0;
|
||||||
for(let i=0; i < length; i++) {
|
while (lengthLevel--) {
|
||||||
let node = queue.shift();
|
const node = queue.shift();
|
||||||
sum += node.val;
|
sum += node.val;
|
||||||
node.left && queue.push(node.left);
|
// 队列存放下一层节点
|
||||||
node.right && queue.push(node.right);
|
node.left && queue.push(node.left);
|
||||||
}
|
node.right && queue.push(node.right);
|
||||||
//每一层的平均值存入数组res
|
|
||||||
res.push(sum/length);
|
|
||||||
}
|
}
|
||||||
|
// 求平均值
|
||||||
return res;
|
res.push(sum / len);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -1925,26 +1927,28 @@ func max(x, y int) int {
|
|||||||
#### Javascript:
|
#### Javascript:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var largestValues = function(root) {
|
var largestValues = function (root) {
|
||||||
//使用层序遍历
|
let res = [],
|
||||||
let res = [], queue = [];
|
queue = [];
|
||||||
queue.push(root);
|
queue.push(root);
|
||||||
|
if (root === null) {
|
||||||
while(root !== null && queue.length) {
|
|
||||||
//设置max初始值就是队列的第一个元素
|
|
||||||
let max = queue[0].val;
|
|
||||||
let length = queue.length;
|
|
||||||
while(length--) {
|
|
||||||
let node = queue.shift();
|
|
||||||
max = max > node.val ? max : node.val;
|
|
||||||
node.left && queue.push(node.left);
|
|
||||||
node.right && queue.push(node.right);
|
|
||||||
}
|
|
||||||
//把每一层的最大值放到res数组
|
|
||||||
res.push(max);
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
}
|
||||||
|
while (queue.length) {
|
||||||
|
let lengthLevel = queue.length,
|
||||||
|
// 初始值设为负无穷大
|
||||||
|
max = -Infinity;
|
||||||
|
while (lengthLevel--) {
|
||||||
|
const node = queue.shift();
|
||||||
|
// 在当前层中找到最大值
|
||||||
|
max = Math.max(max, node.val);
|
||||||
|
// 找到下一层的节点
|
||||||
|
node.left && queue.push(node.left);
|
||||||
|
node.right && queue.push(node.right);
|
||||||
|
}
|
||||||
|
res.push(max);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -2805,21 +2809,23 @@ func maxDepth(root *TreeNode) int {
|
|||||||
* @param {TreeNode} root
|
* @param {TreeNode} root
|
||||||
* @return {number}
|
* @return {number}
|
||||||
*/
|
*/
|
||||||
var maxDepth = function(root) {
|
var maxDepth = function (root) {
|
||||||
// 最大的深度就是二叉树的层数
|
// 二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。
|
||||||
if (root === null) return 0;
|
let max = 0,
|
||||||
let queue = [root];
|
queue = [root];
|
||||||
let height = 0;
|
if (root === null) {
|
||||||
while (queue.length) {
|
return max;
|
||||||
let n = queue.length;
|
}
|
||||||
height++;
|
while (queue.length) {
|
||||||
for (let i=0; i<n; i++) {
|
max++;
|
||||||
let node = queue.shift();
|
let length = queue.length;
|
||||||
node.left && queue.push(node.left);
|
while (length--) {
|
||||||
node.right && queue.push(node.right);
|
let node = queue.shift();
|
||||||
}
|
node.left && queue.push(node.left);
|
||||||
|
node.right && queue.push(node.right);
|
||||||
}
|
}
|
||||||
return height;
|
}
|
||||||
|
return max;
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -64,7 +64,7 @@
|
|||||||
|
|
||||||
代码如下:
|
代码如下:
|
||||||
|
|
||||||
```
|
```CPP
|
||||||
int getDepth(TreeNode* node)
|
int getDepth(TreeNode* node)
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -74,14 +74,14 @@ int getDepth(TreeNode* node)
|
|||||||
|
|
||||||
代码如下:
|
代码如下:
|
||||||
|
|
||||||
```
|
```CPP
|
||||||
if (node == NULL) return 0;
|
if (node == NULL) return 0;
|
||||||
```
|
```
|
||||||
|
|
||||||
3. 确定单层递归的逻辑
|
3. 确定单层递归的逻辑
|
||||||
|
|
||||||
这块和求最大深度可就不一样了,一些同学可能会写如下代码:
|
这块和求最大深度可就不一样了,一些同学可能会写如下代码:
|
||||||
```
|
```CPP
|
||||||
int leftDepth = getDepth(node->left);
|
int leftDepth = getDepth(node->left);
|
||||||
int rightDepth = getDepth(node->right);
|
int rightDepth = getDepth(node->right);
|
||||||
int result = 1 + min(leftDepth, rightDepth);
|
int result = 1 + min(leftDepth, rightDepth);
|
||||||
|
@ -394,7 +394,28 @@ class Solution:
|
|||||||
dp[j] = dp[j] or (dp[j - len(word)] and word == s[j - len(word):j])
|
dp[j] = dp[j] or (dp[j - len(word)] and word == s[j - len(word):j])
|
||||||
return dp[len(s)]
|
return dp[len(s)]
|
||||||
```
|
```
|
||||||
|
DP(剪枝)
|
||||||
|
|
||||||
|
```python
|
||||||
|
class Solution(object):
|
||||||
|
def wordBreak(self, s, wordDict):
|
||||||
|
|
||||||
|
# 先对单词按长度排序
|
||||||
|
wordDict.sort(key=lambda x: len(x))
|
||||||
|
n = len(s)
|
||||||
|
dp = [False] * (n + 1)
|
||||||
|
dp[0] = True
|
||||||
|
# 遍历背包
|
||||||
|
for i in range(1, n + 1):
|
||||||
|
# 遍历单词
|
||||||
|
for word in wordDict:
|
||||||
|
# 简单的 “剪枝”
|
||||||
|
if len(word) > i:
|
||||||
|
break
|
||||||
|
dp[i] = dp[i] or (dp[i - len(word)] and s[i - len(word): i] == word)
|
||||||
|
return dp[-1]
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
### Go:
|
### Go:
|
||||||
|
@ -169,8 +169,12 @@ class Solution {
|
|||||||
```python
|
```python
|
||||||
from operator import add, sub, mul
|
from operator import add, sub, mul
|
||||||
|
|
||||||
class Solution:
|
def div(x, y):
|
||||||
op_map = {'+': add, '-': sub, '*': mul, '/': lambda x, y: int(x / y)}
|
# 使用整数除法的向零取整方式
|
||||||
|
return int(x / y) if x * y > 0 else -(abs(x) // abs(y))
|
||||||
|
|
||||||
|
class Solution(object):
|
||||||
|
op_map = {'+': add, '-': sub, '*': mul, '/': div}
|
||||||
|
|
||||||
def evalRPN(self, tokens: List[str]) -> int:
|
def evalRPN(self, tokens: List[str]) -> int:
|
||||||
stack = []
|
stack = []
|
||||||
@ -186,18 +190,31 @@ class Solution:
|
|||||||
|
|
||||||
另一种可行,但因为使用eval相对较慢的方法:
|
另一种可行,但因为使用eval相对较慢的方法:
|
||||||
```python
|
```python
|
||||||
class Solution:
|
from operator import add, sub, mul
|
||||||
def evalRPN(self, tokens: List[str]) -> int:
|
|
||||||
|
def div(x, y):
|
||||||
|
# 使用整数除法的向零取整方式
|
||||||
|
return int(x / y) if x * y > 0 else -(abs(x) // abs(y))
|
||||||
|
|
||||||
|
class Solution(object):
|
||||||
|
op_map = {'+': add, '-': sub, '*': mul, '/': div}
|
||||||
|
|
||||||
|
def evalRPN(self, tokens):
|
||||||
|
"""
|
||||||
|
:type tokens: List[str]
|
||||||
|
:rtype: int
|
||||||
|
"""
|
||||||
stack = []
|
stack = []
|
||||||
for item in tokens:
|
for token in tokens:
|
||||||
if item not in {"+", "-", "*", "/"}:
|
if token in self.op_map:
|
||||||
stack.append(item)
|
op1 = stack.pop()
|
||||||
|
op2 = stack.pop()
|
||||||
|
operation = self.op_map[token]
|
||||||
|
stack.append(operation(op2, op1))
|
||||||
else:
|
else:
|
||||||
first_num, second_num = stack.pop(), stack.pop()
|
stack.append(int(token))
|
||||||
stack.append(
|
return stack.pop()
|
||||||
int(eval(f'{second_num} {item} {first_num}')) # 第一个出来的在运算符后面
|
|
||||||
)
|
|
||||||
return int(stack.pop()) # 如果一开始只有一个数,那么会是字符串形式的
|
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -585,7 +585,7 @@ impl Solution {
|
|||||||
let mut dummyHead = Box::new(ListNode::new(0));
|
let mut dummyHead = Box::new(ListNode::new(0));
|
||||||
dummyHead.next = head;
|
dummyHead.next = head;
|
||||||
let mut cur = dummyHead.as_mut();
|
let mut cur = dummyHead.as_mut();
|
||||||
// 使用take()替换std::men::replace(&mut node.next, None)达到相同的效果,并且更普遍易读
|
// 使用take()替换std::mem::replace(&mut node.next, None)达到相同的效果,并且更普遍易读
|
||||||
while let Some(nxt) = cur.next.take() {
|
while let Some(nxt) = cur.next.take() {
|
||||||
if nxt.val == val {
|
if nxt.val == val {
|
||||||
cur.next = nxt.next;
|
cur.next = nxt.next;
|
||||||
|
@ -270,22 +270,21 @@ var minSubArrayLen = function(target, nums) {
|
|||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
function minSubArrayLen(target: number, nums: number[]): number {
|
function minSubArrayLen(target: number, nums: number[]): number {
|
||||||
let left: number = 0, right: number = 0;
|
let left: number = 0,
|
||||||
let res: number = nums.length + 1;
|
res: number = Infinity,
|
||||||
let sum: number = 0;
|
subLen: number = 0,
|
||||||
while (right < nums.length) {
|
sum: number = 0;
|
||||||
sum += nums[right];
|
for (let right: number = 0; right < nums.length; right++) {
|
||||||
if (sum >= target) {
|
sum += nums[right];
|
||||||
// 不断移动左指针,直到不能再缩小为止
|
while (sum >= target) {
|
||||||
while (sum - nums[left] >= target) {
|
subLen = right - left + 1;
|
||||||
sum -= nums[left++];
|
res = Math.min(res, subLen);
|
||||||
}
|
sum -= nums[left];
|
||||||
res = Math.min(res, right - left + 1);
|
left++;
|
||||||
}
|
|
||||||
right++;
|
|
||||||
}
|
}
|
||||||
return res === nums.length + 1 ? 0 : res;
|
}
|
||||||
};
|
return res === Infinity ? 0 : res;
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Swift:
|
### Swift:
|
||||||
|
@ -417,6 +417,7 @@ func dfs(k, n int, start int, sum int) {
|
|||||||
```
|
```
|
||||||
|
|
||||||
### JavaScript
|
### JavaScript
|
||||||
|
- 未剪枝:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
/**
|
/**
|
||||||
@ -424,32 +425,74 @@ func dfs(k, n int, start int, sum int) {
|
|||||||
* @param {number} n
|
* @param {number} n
|
||||||
* @return {number[][]}
|
* @return {number[][]}
|
||||||
*/
|
*/
|
||||||
var combinationSum3 = function(k, n) {
|
var combinationSum3 = function (k, n) {
|
||||||
let res = [];
|
// 回溯法
|
||||||
let path = [];
|
let result = [],
|
||||||
let sum = 0;
|
path = [];
|
||||||
const dfs = (path,index) => {
|
const backtracking = (_k, targetSum, sum, startIndex) => {
|
||||||
// 剪枝操作
|
// 终止条件
|
||||||
if (sum > n){
|
if (path.length === _k) {
|
||||||
return
|
if (sum === targetSum) {
|
||||||
}
|
result.push(path.slice());
|
||||||
if (path.length == k) {
|
}
|
||||||
if(sum == n){
|
// 如果总和不相等,就直接返回
|
||||||
res.push([...path]);
|
return;
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (let i = index; i <= 9 - (k-path.length) + 1;i++) {
|
|
||||||
path.push(i);
|
|
||||||
sum = sum + i;
|
|
||||||
index += 1;
|
|
||||||
dfs(path,index);
|
|
||||||
sum -= i
|
|
||||||
path.pop()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
dfs(path,1);
|
|
||||||
return res
|
// 循环当前节点,因为只使用数字1到9,所以最大是9
|
||||||
|
for (let i = startIndex; i <= 9; i++) {
|
||||||
|
path.push(i);
|
||||||
|
sum += i;
|
||||||
|
// 回调函数
|
||||||
|
backtracking(_k, targetSum, sum, i + 1);
|
||||||
|
// 回溯
|
||||||
|
sum -= i;
|
||||||
|
path.pop();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
backtracking(k, n, 0, 1);
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
- 剪枝:
|
||||||
|
|
||||||
|
```js
|
||||||
|
/**
|
||||||
|
* @param {number} k
|
||||||
|
* @param {number} n
|
||||||
|
* @return {number[][]}
|
||||||
|
*/
|
||||||
|
var combinationSum3 = function (k, n) {
|
||||||
|
// 回溯法
|
||||||
|
let result = [],
|
||||||
|
path = [];
|
||||||
|
const backtracking = (_k, targetSum, sum, startIndex) => {
|
||||||
|
if (sum > targetSum) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 终止条件
|
||||||
|
if (path.length === _k) {
|
||||||
|
if (sum === targetSum) {
|
||||||
|
result.push(path.slice());
|
||||||
|
}
|
||||||
|
// 如果总和不相等,就直接返回
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 循环当前节点,因为只使用数字1到9,所以最大是9
|
||||||
|
for (let i = startIndex; i <= 9 - (_k - path.length) + 1; i++) {
|
||||||
|
path.push(i);
|
||||||
|
sum += i;
|
||||||
|
// 回调函数
|
||||||
|
backtracking(_k, targetSum, sum, i + 1);
|
||||||
|
// 回溯
|
||||||
|
sum -= i;
|
||||||
|
path.pop();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
backtracking(k, n, 0, 1);
|
||||||
|
return result;
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@
|
|||||||
1. 确定递归函数的参数和返回值:参数就是传入树的根节点,返回就返回以该节点为根节点二叉树的节点数量,所以返回值为int类型。
|
1. 确定递归函数的参数和返回值:参数就是传入树的根节点,返回就返回以该节点为根节点二叉树的节点数量,所以返回值为int类型。
|
||||||
|
|
||||||
代码如下:
|
代码如下:
|
||||||
```
|
```CPP
|
||||||
int getNodesNum(TreeNode* cur) {
|
int getNodesNum(TreeNode* cur) {
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -62,7 +62,7 @@ int getNodesNum(TreeNode* cur) {
|
|||||||
|
|
||||||
代码如下:
|
代码如下:
|
||||||
|
|
||||||
```
|
```CPP
|
||||||
if (cur == NULL) return 0;
|
if (cur == NULL) return 0;
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -70,7 +70,7 @@ if (cur == NULL) return 0;
|
|||||||
|
|
||||||
代码如下:
|
代码如下:
|
||||||
|
|
||||||
```
|
```CPP
|
||||||
int leftNum = getNodesNum(cur->left); // 左
|
int leftNum = getNodesNum(cur->left); // 左
|
||||||
int rightNum = getNodesNum(cur->right); // 右
|
int rightNum = getNodesNum(cur->right); // 右
|
||||||
int treeNum = leftNum + rightNum + 1; // 中
|
int treeNum = leftNum + rightNum + 1; // 中
|
||||||
|
@ -247,7 +247,7 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
### Java
|
### Java
|
||||||
|
递归
|
||||||
```Java
|
```Java
|
||||||
class Solution {
|
class Solution {
|
||||||
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
|
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
|
||||||
@ -271,6 +271,47 @@ class Solution {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
迭代
|
||||||
|
```Java
|
||||||
|
class Solution {
|
||||||
|
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
|
||||||
|
int max = Integer.MAX_VALUE;
|
||||||
|
Stack<TreeNode> st = new Stack<>();
|
||||||
|
TreeNode cur = root, pre = null;
|
||||||
|
while (cur != null || !st.isEmpty()) {
|
||||||
|
while (cur != null) {
|
||||||
|
st.push(cur);
|
||||||
|
cur = cur.left;
|
||||||
|
}
|
||||||
|
cur = st.pop();
|
||||||
|
if (cur.right == null || cur.right == pre) {
|
||||||
|
// p/q是 中/左 或者 中/右 , 返回中
|
||||||
|
if (cur == p || cur == q) {
|
||||||
|
if ((cur.left != null && cur.left.val == max) || (cur.right != null && cur.right.val == max)) {
|
||||||
|
return cur;
|
||||||
|
}
|
||||||
|
cur.val = max;
|
||||||
|
}
|
||||||
|
// p/q是 左/右 , 返回中
|
||||||
|
if (cur.left != null && cur.left.val == max && cur.right != null && cur.right.val == max) {
|
||||||
|
return cur;
|
||||||
|
}
|
||||||
|
// MAX_VALUE 往上传递
|
||||||
|
if ((cur.left != null && cur.left.val == max) || (cur.right != null && cur.right.val == max)) {
|
||||||
|
cur.val = max;
|
||||||
|
}
|
||||||
|
pre = cur;
|
||||||
|
cur = null;
|
||||||
|
} else {
|
||||||
|
st.push(cur);
|
||||||
|
cur = cur.right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Python
|
### Python
|
||||||
|
@ -271,6 +271,26 @@ class Solution:
|
|||||||
# 返回结果
|
# 返回结果
|
||||||
return dp[n]
|
return dp[n]
|
||||||
|
|
||||||
|
```
|
||||||
|
```python
|
||||||
|
class Solution(object):
|
||||||
|
def numSquares(self, n):
|
||||||
|
# 先把可以选的数准备好,更好理解
|
||||||
|
nums, num = [], 1
|
||||||
|
while num ** 2 <= n:
|
||||||
|
nums.append(num ** 2)
|
||||||
|
num += 1
|
||||||
|
# dp数组初始化
|
||||||
|
dp = [float('inf')] * (n + 1)
|
||||||
|
dp[0] = 0
|
||||||
|
|
||||||
|
# 遍历准备好的完全平方数
|
||||||
|
for i in range(len(nums)):
|
||||||
|
# 遍历背包容量
|
||||||
|
for j in range(nums[i], n+1):
|
||||||
|
dp[j] = min(dp[j], dp[j-nums[i]]+1)
|
||||||
|
# 返回结果
|
||||||
|
return dp[-1]
|
||||||
|
|
||||||
|
|
||||||
```
|
```
|
||||||
|
@ -129,6 +129,7 @@ public:
|
|||||||
```Java
|
```Java
|
||||||
class Solution {
|
class Solution {
|
||||||
public int lengthOfLIS(int[] nums) {
|
public int lengthOfLIS(int[] nums) {
|
||||||
|
if (nums.length <= 1) return nums.length;
|
||||||
int[] dp = new int[nums.length];
|
int[] dp = new int[nums.length];
|
||||||
int res = 1;
|
int res = 1;
|
||||||
Arrays.fill(dp, 1);
|
Arrays.fill(dp, 1);
|
||||||
@ -137,8 +138,8 @@ class Solution {
|
|||||||
if (nums[i] > nums[j]) {
|
if (nums[i] > nums[j]) {
|
||||||
dp[i] = Math.max(dp[i], dp[j] + 1);
|
dp[i] = Math.max(dp[i], dp[j] + 1);
|
||||||
}
|
}
|
||||||
res = Math.max(res, dp[i]);
|
|
||||||
}
|
}
|
||||||
|
res = Math.max(res, dp[i]);
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
@ -133,7 +133,7 @@ class Solution {
|
|||||||
record[c - 'a'] -= 1;
|
record[c - 'a'] -= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果数组中存在负数,说明ransomNote字符串总存在magazine中没有的字符
|
// 如果数组中存在负数,说明ransomNote字符串中存在magazine中没有的字符
|
||||||
for(int i : record){
|
for(int i : record){
|
||||||
if(i < 0){
|
if(i < 0){
|
||||||
return false;
|
return false;
|
||||||
|
@ -101,7 +101,7 @@ public:
|
|||||||
int sum = 0;
|
int sum = 0;
|
||||||
for (int i = 0; i < nums.size(); i++) sum += nums[i];
|
for (int i = 0; i < nums.size(); i++) sum += nums[i];
|
||||||
if (S > sum) return 0; // 此时没有方案
|
if (S > sum) return 0; // 此时没有方案
|
||||||
if ((S + sum) % 2) return 0; // 此时没有方案,两个int相加的时候要各位小心数值溢出的问题
|
if ((S + sum) % 2) return 0; // 此时没有方案,两个int相加的时候要格外小心数值溢出的问题
|
||||||
int bagSize = (S + sum) / 2; // 转变为组合总和问题,bagsize就是要求的和
|
int bagSize = (S + sum) / 2; // 转变为组合总和问题,bagsize就是要求的和
|
||||||
|
|
||||||
// 以下为回溯法代码
|
// 以下为回溯法代码
|
||||||
|
@ -234,6 +234,25 @@ class Solution:
|
|||||||
return dp[-1][-1]
|
return dp[-1][-1]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
> 版本 2
|
||||||
|
|
||||||
|
```python
|
||||||
|
class Solution(object):
|
||||||
|
def minDistance(self, word1, word2):
|
||||||
|
m, n = len(word1), len(word2)
|
||||||
|
|
||||||
|
# dp 求解两字符串最长公共子序列
|
||||||
|
dp = [[0] * (n+1) for _ in range(m+1)]
|
||||||
|
for i in range(1, m+1):
|
||||||
|
for j in range(1, n+1):
|
||||||
|
if word1[i-1] == word2[j-1]:
|
||||||
|
dp[i][j] = dp[i-1][j-1] + 1
|
||||||
|
else:
|
||||||
|
dp[i][j] = max(dp[i-1][j], dp[i][j-1])
|
||||||
|
|
||||||
|
# 删去最长公共子序列以外元素
|
||||||
|
return m + n - 2 * dp[-1][-1]
|
||||||
|
```
|
||||||
### Go:
|
### Go:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
|
@ -501,19 +501,19 @@ func search(nums: [Int], target: Int) -> Int {
|
|||||||
|
|
||||||
### **Rust:**
|
### **Rust:**
|
||||||
|
|
||||||
(版本一)左闭右开区间
|
(版本一)左闭右闭区间
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
impl Solution {
|
impl Solution {
|
||||||
pub fn search(nums: Vec<i32>, target: i32) -> i32 {
|
pub fn search(nums: Vec<i32>, target: i32) -> i32 {
|
||||||
let (mut left, mut right) = (0, nums.len());
|
let (mut left, mut right) = (0_i32, nums.len() as i32 - 1);
|
||||||
while left < right {
|
while left <= right {
|
||||||
let mid = (right + left) / 2;
|
let mid = (right + left) / 2;
|
||||||
match nums[mid].cmp(&target) {
|
match nums[mid as usize].cmp(&target) {
|
||||||
Ordering::Less => left = mid + 1,
|
Ordering::Less => left = mid + 1,
|
||||||
Ordering::Greater => right = mid,
|
Ordering::Greater => right = mid - 1,
|
||||||
Ordering::Equal => return mid as i32,
|
Ordering::Equal => return mid,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
-1
|
-1
|
||||||
@ -521,19 +521,19 @@ impl Solution {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
//(版本二)左闭右闭区间
|
//(版本二)左闭右开区间
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
impl Solution {
|
impl Solution {
|
||||||
pub fn search(nums: Vec<i32>, target: i32) -> i32 {
|
pub fn search(nums: Vec<i32>, target: i32) -> i32 {
|
||||||
let (mut left, mut right) = (0, nums.len());
|
let (mut left, mut right) = (0_i32, nums.len() as i32);
|
||||||
while left <= right {
|
while left < right {
|
||||||
let mid = (right + left) / 2;
|
let mid = (right + left) / 2;
|
||||||
match nums[mid].cmp(&target) {
|
match nums[mid as usize].cmp(&target) {
|
||||||
Ordering::Less => left = mid + 1,
|
Ordering::Less => left = mid + 1,
|
||||||
Ordering::Greater => right = mid - 1,
|
Ordering::Greater => right = mid,
|
||||||
Ordering::Equal => return mid as i32,
|
Ordering::Equal => return mid,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
-1
|
-1
|
||||||
|
@ -181,6 +181,17 @@ class Solution:
|
|||||||
### Go:
|
### Go:
|
||||||
|
|
||||||
```Go
|
```Go
|
||||||
|
// 排序法
|
||||||
|
func sortedSquares(nums []int) []int {
|
||||||
|
for i, val := range nums {
|
||||||
|
nums[i] *= val
|
||||||
|
}
|
||||||
|
sort.Ints(nums)
|
||||||
|
return nums
|
||||||
|
}
|
||||||
|
```
|
||||||
|
```Go
|
||||||
|
// 双指针法
|
||||||
func sortedSquares(nums []int) []int {
|
func sortedSquares(nums []int) []int {
|
||||||
n := len(nums)
|
n := len(nums)
|
||||||
i, j, k := 0, n-1, n-1
|
i, j, k := 0, n-1, n-1
|
||||||
|
@ -71,7 +71,7 @@
|
|||||||
|
|
||||||
有递归的地方就有回溯,那么回溯在哪里呢?
|
有递归的地方就有回溯,那么回溯在哪里呢?
|
||||||
|
|
||||||
就地递归函数的下面,例如如下代码:
|
就递归函数的下面,例如如下代码:
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
void dfs(参数) {
|
void dfs(参数) {
|
||||||
|
@ -48,7 +48,7 @@ void traversal(TreeNode* cur, vector<int>& vec)
|
|||||||
if (cur == NULL) return;
|
if (cur == NULL) return;
|
||||||
```
|
```
|
||||||
|
|
||||||
3. **确定单层递归的逻辑**:前序遍历是中左右的循序,所以在单层递归的逻辑,是要先取中节点的数值,代码如下:
|
3. **确定单层递归的逻辑**:前序遍历是中左右的顺序,所以在单层递归的逻辑,是要先取中节点的数值,代码如下:
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
vec.push_back(cur->val); // 中
|
vec.push_back(cur->val); // 中
|
||||||
@ -189,7 +189,7 @@ class Solution:
|
|||||||
res.append(node.val)
|
res.append(node.val)
|
||||||
dfs(node.left)
|
dfs(node.left)
|
||||||
dfs(node.right)
|
dfs(node.right)
|
||||||
|
dfs(root)
|
||||||
return res
|
return res
|
||||||
|
|
||||||
```
|
```
|
||||||
@ -206,7 +206,7 @@ class Solution:
|
|||||||
dfs(node.left)
|
dfs(node.left)
|
||||||
res.append(node.val)
|
res.append(node.val)
|
||||||
dfs(node.right)
|
dfs(node.right)
|
||||||
|
dfs(root)
|
||||||
return res
|
return res
|
||||||
```
|
```
|
||||||
```python
|
```python
|
||||||
@ -225,6 +225,7 @@ class Solution:
|
|||||||
dfs(node.right)
|
dfs(node.right)
|
||||||
res.append(node.val)
|
res.append(node.val)
|
||||||
|
|
||||||
|
dfs(root)
|
||||||
return res
|
return res
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -287,52 +288,91 @@ func postorderTraversal(root *TreeNode) (res []int) {
|
|||||||
前序遍历:
|
前序遍历:
|
||||||
```Javascript
|
```Javascript
|
||||||
var preorderTraversal = function(root) {
|
var preorderTraversal = function(root) {
|
||||||
let res=[];
|
// 第一种
|
||||||
const dfs=function(root){
|
// let res=[];
|
||||||
if(root===null)return ;
|
// const dfs=function(root){
|
||||||
//先序遍历所以从父节点开始
|
// if(root===null)return ;
|
||||||
res.push(root.val);
|
// //先序遍历所以从父节点开始
|
||||||
//递归左子树
|
// res.push(root.val);
|
||||||
dfs(root.left);
|
// //递归左子树
|
||||||
//递归右子树
|
// dfs(root.left);
|
||||||
dfs(root.right);
|
// //递归右子树
|
||||||
}
|
// dfs(root.right);
|
||||||
//只使用一个参数 使用闭包进行存储结果
|
// }
|
||||||
dfs(root);
|
// //只使用一个参数 使用闭包进行存储结果
|
||||||
return res;
|
// dfs(root);
|
||||||
|
// return res;
|
||||||
|
// 第二种
|
||||||
|
return root
|
||||||
|
? [
|
||||||
|
// 前序遍历:中左右
|
||||||
|
root.val,
|
||||||
|
// 递归左子树
|
||||||
|
...preorderTraversal(root.left),
|
||||||
|
// 递归右子树
|
||||||
|
...preorderTraversal(root.right),
|
||||||
|
]
|
||||||
|
: [];
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
中序遍历
|
中序遍历
|
||||||
```javascript
|
```javascript
|
||||||
var inorderTraversal = function(root) {
|
var inorderTraversal = function(root) {
|
||||||
let res=[];
|
// 第一种
|
||||||
const dfs=function(root){
|
|
||||||
if(root===null){
|
// let res=[];
|
||||||
return ;
|
// const dfs=function(root){
|
||||||
}
|
// if(root===null){
|
||||||
dfs(root.left);
|
// return ;
|
||||||
res.push(root.val);
|
// }
|
||||||
dfs(root.right);
|
// dfs(root.left);
|
||||||
}
|
// res.push(root.val);
|
||||||
dfs(root);
|
// dfs(root.right);
|
||||||
return res;
|
// }
|
||||||
|
// dfs(root);
|
||||||
|
// return res;
|
||||||
|
|
||||||
|
// 第二种
|
||||||
|
return root
|
||||||
|
? [
|
||||||
|
// 中序遍历:左中右
|
||||||
|
// 递归左子树
|
||||||
|
...inorderTraversal(root.left),
|
||||||
|
root.val,
|
||||||
|
// 递归右子树
|
||||||
|
...inorderTraversal(root.right),
|
||||||
|
]
|
||||||
|
: [];
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
后序遍历
|
后序遍历
|
||||||
```javascript
|
```javascript
|
||||||
var postorderTraversal = function(root) {
|
var postorderTraversal = function(root) {
|
||||||
let res=[];
|
// 第一种
|
||||||
const dfs=function(root){
|
// let res=[];
|
||||||
if(root===null){
|
// const dfs=function(root){
|
||||||
return ;
|
// if(root===null){
|
||||||
}
|
// return ;
|
||||||
dfs(root.left);
|
// }
|
||||||
dfs(root.right);
|
// dfs(root.left);
|
||||||
res.push(root.val);
|
// dfs(root.right);
|
||||||
}
|
// res.push(root.val);
|
||||||
dfs(root);
|
// }
|
||||||
return res;
|
// dfs(root);
|
||||||
|
// return res;
|
||||||
|
|
||||||
|
// 第二种
|
||||||
|
// 后续遍历:左右中
|
||||||
|
return root
|
||||||
|
? [
|
||||||
|
// 递归左子树
|
||||||
|
...postorderTraversal(root.left),
|
||||||
|
// 递归右子树
|
||||||
|
...postorderTraversal(root.right),
|
||||||
|
root.val,
|
||||||
|
]
|
||||||
|
: [];
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
**时间复杂度是一个函数,它定性描述该算法的运行时间**。
|
**时间复杂度是一个函数,它定性描述该算法的运行时间**。
|
||||||
|
|
||||||
我们在软件开发中,时间复杂度就是用来方便开发者估算出程序运行的答题时间。
|
我们在软件开发中,时间复杂度就是用来方便开发者估算出程序运行的大体时间。
|
||||||
|
|
||||||
那么该如何估计程序运行时间呢,通常会估算算法的操作单元数量来代表程序消耗的时间,这里默认CPU的每个单元运行消耗的时间都是相同的。
|
那么该如何估计程序运行时间呢,通常会估算算法的操作单元数量来代表程序消耗的时间,这里默认CPU的每个单元运行消耗的时间都是相同的。
|
||||||
|
|
||||||
@ -42,7 +42,7 @@
|
|||||||
|
|
||||||
我们主要关心的还是一般情况下的数据形式。
|
我们主要关心的还是一般情况下的数据形式。
|
||||||
|
|
||||||
**面试中说道算法的时间复杂度是多少指的都是一般情况**。但是如果面试官和我们深入探讨一个算法的实现以及性能的时候,就要时刻想着数据用例的不一样,时间复杂度也是不同的,这一点是一定要注意的。
|
**面试中说的算法的时间复杂度是多少指的都是一般情况**。但是如果面试官和我们深入探讨一个算法的实现以及性能的时候,就要时刻想着数据用例的不一样,时间复杂度也是不同的,这一点是一定要注意的。
|
||||||
|
|
||||||
|
|
||||||
## 不同数据规模的差异
|
## 不同数据规模的差异
|
||||||
@ -61,7 +61,7 @@
|
|||||||
|
|
||||||
例如上图中20就是那个点,n只要大于20 常数项系数已经不起决定性作用了。
|
例如上图中20就是那个点,n只要大于20 常数项系数已经不起决定性作用了。
|
||||||
|
|
||||||
**所以我们说的时间复杂度都是省略常数项系数的,是因为一般情况下都是默认数据规模足够的大,基于这样的事实,给出的算法时间复杂的的一个排行如下所示**:
|
**所以我们说的时间复杂度都是省略常数项系数的,是因为一般情况下都是默认数据规模足够的大,基于这样的事实,给出的算法时间复杂度的一个排行如下所示**:
|
||||||
|
|
||||||
O(1)常数阶 < O(logn)对数阶 < O(n)线性阶 < O(nlogn)线性对数阶 < O(n^2)平方阶 < O(n^3)立方阶 < O(2^n)指数阶
|
O(1)常数阶 < O(logn)对数阶 < O(n)线性阶 < O(nlogn)线性对数阶 < O(n^2)平方阶 < O(n^3)立方阶 < O(2^n)指数阶
|
||||||
|
|
||||||
|
@ -12,11 +12,11 @@
|
|||||||
|
|
||||||
## 哈希表
|
## 哈希表
|
||||||
|
|
||||||
首先什么是 哈希表,哈希表(英文名字为Hash table,国内也有一些算法书籍翻译为散列表,大家看到这两个名称知道都是指hash table就可以了)。
|
首先什么是哈希表,哈希表(英文名字为Hash table,国内也有一些算法书籍翻译为散列表,大家看到这两个名称知道都是指hash table就可以了)。
|
||||||
|
|
||||||
> 哈希表是根据关键码的值而直接进行访问的数据结构。
|
> 哈希表是根据关键码的值而直接进行访问的数据结构。
|
||||||
|
|
||||||
这么这官方的解释可能有点懵,其实直白来讲其实数组就是一张哈希表。
|
这么官方的解释可能有点懵,其实直白来讲其实数组就是一张哈希表。
|
||||||
|
|
||||||
哈希表中关键码就是数组的索引下标,然后通过下标直接访问数组中的元素,如下图所示:
|
哈希表中关键码就是数组的索引下标,然后通过下标直接访问数组中的元素,如下图所示:
|
||||||
|
|
||||||
@ -113,7 +113,7 @@ std::unordered_map 底层实现为哈希表,std::map 和std::multimap 的底
|
|||||||
|
|
||||||
其他语言例如:java里的HashMap ,TreeMap 都是一样的原理。可以灵活贯通。
|
其他语言例如:java里的HashMap ,TreeMap 都是一样的原理。可以灵活贯通。
|
||||||
|
|
||||||
虽然std::set、std::multiset 的底层实现是红黑树,不是哈希表,std::set、std::multiset 使用红黑树来索引和存储,不过给我们的使用方式,还是哈希法的使用方式,即key和value。所以使用这些数据结构来解决映射问题的方法,我们依然称之为哈希法。 map也是一样的道理。
|
虽然std::set和std::multiset 的底层实现基于红黑树而非哈希表,它们通过红黑树来索引和存储数据。不过给我们的使用方式,还是哈希法的使用方式,即依靠键(key)来访问值(value)。所以使用这些数据结构来解决映射问题的方法,我们依然称之为哈希法。std::map也是一样的道理。
|
||||||
|
|
||||||
这里在说一下,一些C++的经典书籍上 例如STL源码剖析,说到了hash_set hash_map,这个与unordered_set,unordered_map又有什么关系呢?
|
这里在说一下,一些C++的经典书籍上 例如STL源码剖析,说到了hash_set hash_map,这个与unordered_set,unordered_map又有什么关系呢?
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
**数组是存放在连续内存空间上的相同类型数据的集合。**
|
**数组是存放在连续内存空间上的相同类型数据的集合。**
|
||||||
|
|
||||||
数组可以方便的通过下标索引的方式获取到下标下对应的数据。
|
数组可以方便的通过下标索引的方式获取到下标对应的数据。
|
||||||
|
|
||||||
举一个字符数组的例子,如图所示:
|
举一个字符数组的例子,如图所示:
|
||||||
|
|
||||||
@ -27,7 +27,7 @@
|
|||||||
* **数组下标都是从0开始的。**
|
* **数组下标都是从0开始的。**
|
||||||
* **数组内存空间的地址是连续的**
|
* **数组内存空间的地址是连续的**
|
||||||
|
|
||||||
正是**因为数组的在内存空间的地址是连续的,所以我们在删除或者增添元素的时候,就难免要移动其他元素的地址。**
|
正是**因为数组在内存空间的地址是连续的,所以我们在删除或者增添元素的时候,就难免要移动其他元素的地址。**
|
||||||
|
|
||||||
例如删除下标为3的元素,需要对下标为3的元素后面的所有元素都要做移动操作,如图所示:
|
例如删除下标为3的元素,需要对下标为3的元素后面的所有元素都要做移动操作,如图所示:
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
**数组是存放在连续内存空间上的相同类型数据的集合。**
|
**数组是存放在连续内存空间上的相同类型数据的集合。**
|
||||||
|
|
||||||
数组可以方便的通过下标索引的方式获取到下标下对应的数据。
|
数组可以方便的通过下标索引的方式获取到下标对应的数据。
|
||||||
|
|
||||||
举一个字符数组的例子,如图所示:
|
举一个字符数组的例子,如图所示:
|
||||||
|
|
||||||
@ -29,7 +29,7 @@
|
|||||||
* **数组下标都是从0开始的。**
|
* **数组下标都是从0开始的。**
|
||||||
* **数组内存空间的地址是连续的**
|
* **数组内存空间的地址是连续的**
|
||||||
|
|
||||||
正是**因为数组的在内存空间的地址是连续的,所以我们在删除或者增添元素的时候,就难免要移动其他元素的地址。**
|
正是**因为数组在内存空间的地址是连续的,所以我们在删除或者增添元素的时候,就难免要移动其他元素的地址。**
|
||||||
|
|
||||||
例如删除下标为3的元素,需要对下标为3的元素后面的所有元素都要做移动操作,如图所示:
|
例如删除下标为3的元素,需要对下标为3的元素后面的所有元素都要做移动操作,如图所示:
|
||||||
|
|
||||||
|
@ -204,6 +204,29 @@ class multi_pack{
|
|||||||
```
|
```
|
||||||
### Python:
|
### Python:
|
||||||
|
|
||||||
|
```python
|
||||||
|
|
||||||
|
C, N = input().split(" ")
|
||||||
|
C, N = int(C), int(N)
|
||||||
|
|
||||||
|
# value数组需要判断一下非空不然过不了
|
||||||
|
weights = [int(x) for x in input().split(" ")]
|
||||||
|
values = [int(x) for x in input().split(" ") if x]
|
||||||
|
nums = [int(x) for x in input().split(" ")]
|
||||||
|
|
||||||
|
dp = [0] * (C + 1)
|
||||||
|
# 遍历背包容量
|
||||||
|
for i in range(N):
|
||||||
|
for j in range(C, weights[i] - 1, -1):
|
||||||
|
for k in range(1, nums[i] + 1):
|
||||||
|
# 遍历 k,如果已经大于背包容量直接跳出循环
|
||||||
|
if k * weights[i] > j:
|
||||||
|
break
|
||||||
|
dp[j] = max(dp[j], dp[j - weights[i] * k] + values[i] * k)
|
||||||
|
print(dp[-1])
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
### Go:
|
### Go:
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user