Merge branch 'master' of github.com:youngyangyang04/leetcode-master

This commit is contained in:
programmercarl
2024-01-02 12:07:28 +08:00
50 changed files with 1527 additions and 233 deletions

View File

@ -260,7 +260,7 @@ class Solution {
}
//每次迭代获取一个字符串,所以会设计大量的字符串拼接,所以这里选择更为高效的 StringBuild
//每次迭代获取一个字符串,所以会设计大量的字符串拼接,所以这里选择更为高效的 StringBuilder
StringBuilder temp = new StringBuilder();
//比如digits如果为"23",num 为0则str表示2对应的 abc
@ -732,6 +732,38 @@ def backtracking(result, letter_map, digits, path, index)
end
end
```
### C#
```C#
public class Solution
{
public IList<string> res = new List<string>();
public string s;
public string[] letterMap = new string[10] { "", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz" };
public IList<string> LetterCombinations(string digits)
{
if (digits.Length == 0)
return res;
BackTracking(digits, 0);
return res;
}
public void BackTracking(string digits, int index)
{
if (index == digits.Length)
{
res.Add(s);
return;
}
int digit = digits[index] - '0';
string letters = letterMap[digit];
for (int i = 0; i < letters.Length; i++)
{
s += letters[i];
BackTracking(digits, index + 1);
s = s.Substring(0, s.Length - 1);
}
}
}
```
<p align="center">
<a href="https://programmercarl.com/other/kstar.html" target="_blank">

View File

@ -106,7 +106,7 @@ public ListNode removeNthFromEnd(ListNode head, int n){
ListNode slowIndex = dummyNode;
// 只要快慢指针相差 n 个结点即可
for (int i = 0; i <= n ; i++){
for (int i = 0; i < n ; i++){
fastIndex = fastIndex.next;
}

View File

@ -218,23 +218,41 @@ class Solution:
### Go
```Go
// 思路: 使用栈来进行括号的匹配
// 时间复杂度 O(n)
// 空间复杂度 O(n)
func isValid(s string) bool {
hash := map[byte]byte{')':'(', ']':'[', '}':'{'}
stack := make([]byte, 0)
if s == "" {
return true
}
// 使用切片模拟栈的行为
stack := make([]rune, 0)
for i := 0; i < len(s); i++ {
if s[i] == '(' || s[i] == '[' || s[i] == '{' {
stack = append(stack, s[i])
} else if len(stack) > 0 && stack[len(stack)-1] == hash[s[i]] {
stack = stack[:len(stack)-1]
} else {
return false
}
}
return len(stack) == 0
// m 用于记录某个右括号对应的左括号
m := make(map[rune]rune)
m[')'] = '('
m[']'] = '['
m['}'] = '{'
// 遍历字符串中的 rune
for _, c := range s {
// 左括号直接入栈
if c == '(' || c == '[' || c == '{' {
stack = append(stack, c)
} else {
// 如果是右括号,先判断栈内是否还有元素
if len(stack) == 0 {
return false
}
// 再判断栈顶元素是否能够匹配
peek := stack[len(stack)-1]
if peek != m[c] {
return false
}
// 模拟栈顶弹出
stack = stack[:len(stack)-1]
}
}
// 若栈中不再包含元素,则能完全匹配
return len(stack) == 0
}
```

View File

@ -63,7 +63,9 @@ public:
cur = cur->next->next; // cur移动两位准备下一轮交换
}
return dummyHead->next;
ListNode* result = dummyHead->next;
delete dummyHead;
return result;
}
};
```

View File

@ -256,17 +256,24 @@ class Solution:
### Go
```go
// 快慢指针法
// 时间复杂度 O(n)
// 空间复杂度 O(1)
func removeElement(nums []int, val int) int {
length:=len(nums)
res:=0
for i:=0;i<length;i++{
if nums[i]!=val {
nums[res]=nums[i]
res++
}
}
nums=nums[:res]
return res
// 初始化慢指针 slow
slow := 0
// 通过 for 循环移动快指针 fast
// 当 fast 指向的元素等于 val 时,跳过
// 否则,将该元素写入 slow 指向的位置,并将 slow 后移一位
for fast := 0; fast < len(nums); fast++ {
if nums[fast] == val {
continue
}
nums[slow] = nums[fast]
slow++
}
return slow
}
```
```go

View File

@ -756,6 +756,59 @@ object Solution {
}
}
```
### C#
```csharp
public class Solution
{
public void SolveSudoku(char[][] board)
{
BackTracking(board);
}
public bool BackTracking(char[][] board)
{
for (int i = 0; i < board.Length; i++)
{
for (int j = 0; j < board[0].Length; j++)
{
if (board[i][j] != '.') continue;
for (char k = '1'; k <= '9'; k++)
{
if (IsValid(board, i, j, k))
{
board[i][j] = k;
if (BackTracking(board)) return true;
board[i][j] = '.';
}
}
return false;
}
}
return true;
}
public bool IsValid(char[][] board, int row, int col, char val)
{
for (int i = 0; i < 9; i++)
{
if (board[i][col] == val) return false;
}
for (int i = 0; i < 9; i++)
{
if (board[row][i] == val) return false;
}
int startRow = (row / 3) * 3;
int startCol = (col / 3) * 3;
for (int i = startRow; i < startRow + 3; i++)
{
for (int j = startCol; j < startCol + 3; j++)
{
if (board[i][j] == val) return false;
}
}
return true;
}
}
```
<p align="center">
<a href="https://programmercarl.com/other/kstar.html" target="_blank">

View File

@ -598,6 +598,66 @@ object Solution {
}
}
```
### C#
```csharp
public class Solution
{
public IList<IList<int>> res = new List<IList<int>>();
public IList<int> path = new List<int>();
public IList<IList<int>> CombinationSum(int[] candidates, int target)
{
BackTracking(candidates, target, 0, 0);
return res;
}
public void BackTracking(int[] candidates, int target, int start, int sum)
{
if (sum > target) return;
if (sum == target)
{
res.Add(new List<int>(path));
return;
}
for (int i = start; i < candidates.Length; i++)
{
sum += candidates[i];
path.Add(candidates[i]);
BackTracking(candidates, target, i, sum);
sum -= candidates[i];
path.RemoveAt(path.Count - 1);
}
}
}
// 剪枝优化
public class Solution
{
public IList<IList<int>> res = new List<IList<int>>();
public IList<int> path = new List<int>();
public IList<IList<int>> CombinationSum(int[] candidates, int target)
{
Array.Sort(candidates);
BackTracking(candidates, target, 0, 0);
return res;
}
public void BackTracking(int[] candidates, int target, int start, int sum)
{
if (sum > target) return;
if (sum == target)
{
res.Add(new List<int>(path));
return;
}
for (int i = start; i < candidates.Length && sum + candidates[i] <= target; i++)
{
sum += candidates[i];
path.Add(candidates[i]);
BackTracking(candidates, target, i, sum);
sum -= candidates[i];
path.RemoveAt(path.Count - 1);
}
}
}
```
<p align="center">

View File

@ -773,7 +773,39 @@ object Solution {
}
}
```
### C#
```csharp
public class Solution
{
public List<IList<int>> res = new List<IList<int>>();
public List<int> path = new List<int>();
public IList<IList<int>> CombinationSum2(int[] candidates, int target)
{
Array.Sort(candidates);
BackTracking(candidates, target, 0, 0);
return res;
}
public void BackTracking(int[] candidates, int target, int start, int sum)
{
if (sum > target) return;
if (sum == target)
{
res.Add(new List<int>(path));
return;
}
for (int i = start; i < candidates.Length && sum + candidates[i] <= target; i++)
{
if (i > start && candidates[i] == candidates[i - 1]) continue;
sum += candidates[i];
path.Add(candidates[i]);
BackTracking(candidates, target, i + 1, sum);
sum -= candidates[i];
path.RemoveAt(path.Count - 1);
}
}
}
```
<p align="center">
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>

View File

@ -486,6 +486,37 @@ object Solution {
}
}
```
### C#
```csharp
public class Solution
{
public IList<IList<int>> res = new List<IList<int>>();
public IList<int> path = new List<int>();
public IList<IList<int>> Permute(int[] nums)
{
var used = new bool[nums.Length];
BackTracking(nums, used);
return res;
}
public void BackTracking(int[] nums, bool[] used)
{
if (path.Count == nums.Length)
{
res.Add(new List<int>(path));
return;
}
for (int i = 0; i < nums.Length; i++)
{
if (used[i]) continue;
used[i] = true;
path.Add(nums[i]);
BackTracking(nums, used);
used[i] = false;
path.RemoveAt(path.Count - 1);
}
}
}
```
<p align="center">
<a href="https://programmercarl.com/other/kstar.html" target="_blank">

View File

@ -521,6 +521,38 @@ object Solution {
}
}
```
### C#
```csharp
public class Solution
{
public List<IList<int>> res = new List<IList<int>>();
public List<int> path = new List<int>();
public IList<IList<int>> PermuteUnique(int[] nums)
{
Array.Sort(nums);
BackTracking(nums, new bool[nums.Length]);
return res;
}
public void BackTracking(int[] nums, bool[] used)
{
if (nums.Length == path.Count)
{
res.Add(new List<int>(path));
return;
}
for (int i = 0; i < nums.Length; i++)
{
if (i > 0 && nums[i] == nums[i - 1] && used[i - 1] == false) continue;
if (used[i]) continue;
path.Add(nums[i]);
used[i] = true;
BackTracking(nums, used);
path.RemoveAt(path.Count - 1);
used[i] = false;
}
}
}
```
<p align="center">
<a href="https://programmercarl.com/other/kstar.html" target="_blank">

View File

@ -453,60 +453,66 @@ func isValid(n, row, col int, chessboard [][]string) bool {
### Javascript
```Javascript
var solveNQueens = function(n) {
function isValid(row, col, chessBoard, n) {
for(let i = 0; i < row; i++) {
if(chessBoard[i][col] === 'Q') {
return false
}
}
for(let i = row - 1, j = col - 1; i >= 0 && j >= 0; i--, j--) {
if(chessBoard[i][j] === 'Q') {
return false
}
}
for(let i = row - 1, j = col + 1; i >= 0 && j < n; i--, j++) {
if(chessBoard[i][j] === 'Q') {
return false
}
}
return true
}
function transformChessBoard(chessBoard) {
let chessBoardBack = []
chessBoard.forEach(row => {
let rowStr = ''
row.forEach(value => {
rowStr += value
})
chessBoardBack.push(rowStr)
})
return chessBoardBack
}
let result = []
function backtracing(row,chessBoard) {
if(row === n) {
result.push(transformChessBoard(chessBoard))
return
}
for(let col = 0; col < n; col++) {
if(isValid(row, col, chessBoard, n)) {
chessBoard[row][col] = 'Q'
backtracing(row + 1,chessBoard)
chessBoard[row][col] = '.'
}
}
}
let chessBoard = new Array(n).fill([]).map(() => new Array(n).fill('.'))
backtracing(0,chessBoard)
return result
/**
* @param {number} n
* @return {string[][]}
*/
var solveNQueens = function (n) {
const ans = [];
const path = [];
const matrix = new Array(n).fill(0).map(() => new Array(n).fill("."));
// 判断是否能相互攻击
const canAttack = (matrix, row, col) => {
let i;
let j;
// 判断正上方和正下方是否有皇后
for (i = 0, j = col; i < n; i++) {
if (matrix[i][j] === "Q") {
return true;
}
}
// 判断正左边和正右边是否有皇后
for (i = row, j = 0; j < n; j++) {
if (matrix[i][j] === "Q") {
return true;
}
}
// 判断左上方是否有皇后
for (i = row - 1, j = col - 1; i >= 0 && j >= 0; i--, j--) {
if (matrix[i][j] === "Q") {
return true;
}
}
// 判断右上方是否有皇后
for (i = row - 1, j = col + 1; i >= 0 && j < n; i--, j++) {
if (matrix[i][j] === "Q") {
return true;
}
}
return false;
};
const backtrack = (matrix, row, col) => {
if (path.length === matrix.length) {
ans.push(path.slice());
return;
}
for (let i = row; i < matrix.length; i++) {
for (let j = col; j < matrix.length; j++) {
// 当前位置会导致互相攻击 继续下一轮搜索
if (canAttack(matrix, i, j)) {
continue;
}
matrix[i][j] = "Q";
path.push(matrix[i].join(""));
// 另起一行搜索 同一行只能有一个皇后
backtrack(matrix, i + 1, 0);
matrix[i][j] = ".";
path.pop();
}
}
};
backtrack(matrix, 0, 0);
return ans;
};
```
@ -859,6 +865,60 @@ object Solution {
}
}
```
### C#
```csharp
public class Solution
{
public List<IList<string>> res = new();
public IList<IList<string>> SolveNQueens(int n)
{
char[][] chessBoard = new char[n][];
for (int i = 0; i < n; i++)
{
chessBoard[i] = new char[n];
for (int j = 0; j < n; j++)
{
chessBoard[i][j] = '.';
}
}
BackTracking(n, 0, chessBoard);
return res;
}
public void BackTracking(int n, int row, char[][] chessBoard)
{
if (row == n)
{
res.Add(chessBoard.Select(x => new string(x)).ToList());
return;
}
for (int col = 0; col < n; col++)
{
if (IsValid(row, col, chessBoard, n))
{
chessBoard[row][col] = 'Q';
BackTracking(n, row + 1, chessBoard);
chessBoard[row][col] = '.';
}
}
}
public bool IsValid(int row, int col, char[][] chessBoard, int n)
{
for (int i = 0; i < row; i++)
{
if (chessBoard[i][col] == 'Q') return false;
}
for (int i = row - 1, j = col - 1; i >= 0 && j >= 0; i--, j--)
{
if (chessBoard[i][j] == 'Q') return false;
}
for (int i = row - 1, j = col + 1; i >= 0 && j < n; i--, j++)
{
if (chessBoard[i][j] == 'Q') return false;
}
return true;
}
}
```
<p align="center">
<a href="https://programmercarl.com/other/kstar.html" target="_blank">

View File

@ -406,6 +406,26 @@ object Solution {
}
}
```
### C#
**贪心**
```csharp
public class Solution
{
public int MaxSubArray(int[] nums)
{
int res = Int32.MinValue;
int count = 0;
for (int i = 0; i < nums.Length; i++)
{
count += nums[i];
res = Math.Max(res, count);
if (count < 0) count = 0;
}
return res;
}
}
```
<p align="center">
<a href="https://programmercarl.com/other/kstar.html" target="_blank">

View File

@ -792,7 +792,59 @@ def backtracking(result, path, n, j, k)
end
```
### C#
```C#
// 暴力
public class Solution
{
public IList<IList<int>> res = new List<IList<int>>();
public IList<int> path = new List<int>();
public IList<IList<int>> Combine(int n, int k)
{
BackTracking(n, k, 1);
return res;
}
public void BackTracking(int n, int k, int start)
{
if (path.Count == k)
{
res.Add(new List<int>(path));
return;
}
for (int i = start; i <= n; i++)
{
path.Add(i);
BackTracking(n, k, i + 1);
path.RemoveAt(path.Count - 1);
}
}
}
// 剪枝
public class Solution
{
public IList<IList<int>> res = new List<IList<int>>();
public IList<int> path = new List<int>();
public IList<IList<int>> Combine(int n, int k)
{
BackTracking(n, k, 1);
return res;
}
public void BackTracking(int n, int k, int start)
{
if (path.Count == k)
{
res.Add(new List<int>(path));
return;
}
for (int i = start; i <= n - (k - path.Count) + 1; i++)
{
path.Add(i);
BackTracking(n, k, i + 1);
path.RemoveAt(path.Count - 1);
}
}
}
```
<p align="center">
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>

View File

@ -443,6 +443,27 @@ object Solution {
}
}
```
### C#
```csharp
public class Solution {
public IList<IList<int>> res = new List<IList<int>>();
public IList<int> path = new List<int>();
public IList<IList<int>> Subsets(int[] nums) {
BackTracking(nums, 0);
return res;
}
public void BackTracking(int[] nums, int start){
res.Add(new List<int>(path));
if(start > nums.Length) return;
for (int i = start; i < nums.Length; i++)
{
path.Add(nums[i]);
BackTracking(nums, i + 1);
path.RemoveAt(path.Count - 1);
}
}
}
```
<p align="center">

View File

@ -515,27 +515,31 @@ func largestRectangleArea(heights []int) int {
var largestRectangleArea = function(heights) {
const len = heights.length;
const minLeftIndex = new Array(len);
const maxRigthIndex = new Array(len);
const maxRightIndex = new Array(len);
// 记录每个柱子 左边第一个小于该柱子的下标
minLeftIndex[0] = -1; // 注意这里初始化防止下面while死循环
for(let i = 1; i < len; i++) {
let t = i - 1;
// 这里不是用if而是不断向左寻找的过程
while(t >= 0 && heights[t] >= heights[i]) t = minLeftIndex[t];
while (t >= 0 && heights[t] >= heights[i]) {
t = minLeftIndex[t];
}
minLeftIndex[i] = t;
}
// 记录每个柱子 右边第一个小于该柱子的下标
maxRigthIndex[len - 1] = len; // 注意这里初始化防止下面while死循环
maxRightIndex[len - 1] = len; // 注意这里初始化防止下面while死循环
for(let i = len - 2; i >= 0; i--){
let t = i + 1;
// 这里不是用if而是不断向右寻找的过程
while(t < len && heights[t] >= heights[i]) t = maxRigthIndex[t];
maxRigthIndex[i] = t;
while (t <= n && heights[t] > heights[i]) {
t = maxRightIndex[t];
}
maxRightIndex[i] = t;
}
// 求和
let maxArea = 0;
for(let i = 0; i < len; i++){
let sum = heights[i] * (maxRigthIndex[i] - minLeftIndex[i] - 1);
let sum = heights[i] * (maxRightIndex[i] - minLeftIndex[i] - 1);
maxArea = Math.max(maxArea , sum);
}
return maxArea;
@ -543,27 +547,37 @@ var largestRectangleArea = function(heights) {
//单调栈
var largestRectangleArea = function(heights) {
let maxArea = 0;
const stack = [];
heights = [0,...heights,0]; // 数组头部加入元素0 数组尾部加入元素0
for(let i = 0; i < heights.length; i++){
if(heights[i] > heights[stack[stack.length-1]]){ // 情况三
stack.push(i);
} else if(heights[i] === heights[stack[stack.length-1]]){ // 情况二
stack.pop(); // 这个可以加,可以不加,效果一样,思路不同
stack.push(i);
} else { // 情况一
while(heights[i] < heights[stack[stack.length-1]]){// 当前bar比栈顶bar矮
const stackTopIndex = stack.pop();// 栈顶元素出栈并保存栈顶bar的索引
let w = i - stack[stack.length -1] - 1;
let h = heights[stackTopIndex]
let maxArea = 0;
const stack = [0];
heights.push(0);
const n = heights.length;
for (let i = 1; i < n; i++) {
let top = stack.at(-1);
// 情况三
if (heights[top] < heights[i]) {
stack.push(i);
}
// 情况二
if (heights[top] === heights[i]) {
stack.pop(); // 这个可以加,可以不加,效果一样,思路不同
stack.push(i);
}
// 情况一
if (heights[top] > heights[i]) {
while (stack.length > 0 && heights[top] > heights[i]) {
// 栈顶元素出栈并保存栈顶bar的索引
const h = heights[stack.pop()];
const left = stack.at(-1) ?? -1;
const w = i - left - 1;
// 计算面积,并取最大面积
maxArea = Math.max(maxArea, w * h);
}
stack.push(i);// 当前bar比栈顶bar高了入栈
}
}
return maxArea;
maxArea = Math.max(maxArea, w * h);
top = stack.at(-1);
}
stack.push(i);
}
}
return maxArea;
};
//单调栈 简洁

View File

@ -640,6 +640,31 @@ object Solution {
}
}
```
### C#
```c#
public class Solution
{
public IList<IList<int>> res = new List<IList<int>>();
public IList<int> path = new List<int>();
public IList<IList<int>> SubsetsWithDup(int[] nums)
{
Array.Sort(nums);
BackTracking(nums, 0);
return res;
}
public void BackTracking(int[] nums, int start)
{
res.Add(new List<int>(path));
for (int i = start; i < nums.Length; i++)
{
if (i > start && nums[i] == nums[i - 1]) continue;
path.Add(nums[i]);
BackTracking(nums, i + 1);
path.RemoveAt(path.Count - 1);
}
}
}
```
<p align="center">
<a href="https://programmercarl.com/other/kstar.html" target="_blank">

View File

@ -799,6 +799,53 @@ object Solution {
}
}
```
### C#
```csharp
public class Solution
{
public IList<string> res = new List<string>();
public IList<string> RestoreIpAddresses(string s)
{
if (s.Length < 4 || s.Length > 12) return res;
BackTracking(s, 0, 0);
return res;
}
public void BackTracking(string s, int start, int pointSum)
{
if (pointSum == 3)
{
if (IsValid(s, start, s.Length - 1))
{
res.Add(s);
}
return;
}
for (int i = start; i < s.Length; i++)
{
if (IsValid(s, start, i))
{
s = s.Insert(i + 1, ".");
BackTracking(s, i + 2, pointSum + 1);
s = s.Remove(i + 1, 1);
}
else break;
}
}
public bool IsValid(string s, int start, int end)
{
if (start > end) return false;
if (s[start] == '0' && start != end) return false;
int num = 0;
for (int i = start; i <= end; i++)
{
if (s[i] > '9' || s[i] < '0') return false;
num = num * 10 + s[i] - '0';
if (num > 255) return false;
}
return true;
}
}
```
<p align="center">

View File

@ -791,6 +791,20 @@ impl Solution {
}
}
```
### C#
```C#
// 递归
public long val = Int64.MinValue;
public bool IsValidBST(TreeNode root)
{
if (root == null) return true;
bool left = IsValidBST(root.left);
if (root.val > val) val = root.val;
else return false;
bool right = IsValidBST(root.right);
return left && right;
}
```
<p align="center">
<a href="https://programmercarl.com/other/kstar.html" target="_blank">

View File

@ -530,6 +530,23 @@ impl Solution {
}
}
```
### C#
```csharp
// 递归
public TreeNode SortedArrayToBST(int[] nums)
{
return Traversal(nums, 0, nums.Length - 1);
}
public TreeNode Traversal(int[] nums, int left, int right)
{
if (left > right) return null;
int mid = left + (right - left) / 2;
TreeNode node = new TreeNode(nums[mid]);
node.left = Traversal(nums, left, mid - 1);
node.right = Traversal(nums, mid + 1, right);
return node;
}
```
<p align="center">

View File

@ -50,7 +50,7 @@
![111.二叉树的最小深度](https://code-thinking.cdn.bcebos.com/pics/111.%E4%BA%8C%E5%8F%89%E6%A0%91%E7%9A%84%E6%9C%80%E5%B0%8F%E6%B7%B1%E5%BA%A6.png)
这就重新审题了,题目中说的是:**最小深度是从根节点到最近叶子节点的最短路径上的节点数量。**注意是**叶子节点**。
这就重新审题了,题目中说的是:**最小深度是从根节点到最近叶子节点的最短路径上的节点数量。**注意是**叶子节点**。
什么是叶子节点,左右孩子都为空的节点才是叶子节点!

View File

@ -349,6 +349,65 @@ class Solution {
}
```
### Java
回溯+动态规划优化回文串判断
```Java
class Solution {
List<List<String>> result;
LinkedList<String> path;
boolean[][] dp;
public List<List<String>> partition(String s) {
result = new ArrayList<>();
char[] str = s.toCharArray();
path = new LinkedList<>();
dp = new boolean[str.length + 1][str.length + 1];
isPalindrome(str);
backtracking(s, 0);
return result;
}
public void backtracking(String str, int startIndex) {
if (startIndex >= str.length()) {
//如果起始位置大于s的大小说明找到了一组分割方案
result.add(new ArrayList<>(path));
} else {
for (int i = startIndex; i < str.length(); ++i) {
if (dp[startIndex][i]) {
//是回文子串,进入下一步递归
//先将当前子串保存入path
path.addLast(str.substring(startIndex, i + 1));
//起始位置后移,保证不重复
backtracking(str, i + 1);
path.pollLast();
} else {
//不是回文子串,跳过
continue;
}
}
}
}
//通过动态规划判断是否是回文串,参考动态规划篇 52 回文子串
public void isPalindrome(char[] str) {
for (int i = 0; i <= str.length; ++i) {
dp[i][i] = true;
}
for (int i = 1; i < str.length; ++i) {
for (int j = i; j >= 0; --j) {
if (str[j] == str[i]) {
if (i - j <= 1) {
dp[j][i] = true;
} else if (dp[j + 1][i - 1]) {
dp[j][i] = true;
}
}
}
}
}
}
```
### Python
回溯 基本版
```python
@ -847,6 +906,50 @@ object Solution {
}
}
```
### CSharp
```csharp
public class Solution
{
public IList<IList<string>> res = new List<IList<string>>();
public IList<string> path = new List<string>();
public IList<IList<string>> Partition(string s)
{
BackTracking(s, 0);
return res;
}
public void BackTracking(string s, int start)
{
if (start >= s.Length)
{
res.Add(new List<string>(path));
return;
}
for (int i = start; i < s.Length; i++)
{
if (IsPalindrome(s, start, i))
{
path.Add(s.Substring(start, i - start + 1));
}
else
{
continue;
}
BackTracking(s, i + 1);
path.RemoveAt(path.Count - 1);
}
}
public bool IsPalindrome(string s, int start, int end)
{
for (int i = start, j = end; i < j; i++, j--)
{
if (s[i] != s[j])
return false;
}
return true;
}
}
```
<p align="center">

View File

@ -276,6 +276,52 @@ var numIslands = function (grid) {
};
```
### TypeScript
```TypeScript
function numIslands2(grid: string[][]): number {
// 四个方向
const dir: number[][] = [[0, 1], [1, 0], [-1, 0], [0, -1]];
const [m, n]: [number, number] = [grid.length, grid[0].length];
function dfs(grid: string[][], visited: boolean[][], x: number, y: number) {
const queue: number[][] = [[x, y]];
while (queue.length !== 0) {
//取出队列头部元素
const top: number[] = queue.shift()!;
for (let i = 0; i < 4; i++) {
const nextX: number = top[0] + dir[i][0];
const nextY: number = top[1] + dir[i][1];
// 越界了,直接跳过
if (nextX < 0 || nextX >= m || nextY < 0 || nextY >= n) {
continue;
}
if (!visited[nextX][nextY] && grid[nextX][nextY] === '1') {
queue.push([nextX, nextY]);
// 只要加入队列立刻标记
visited[nextX][nextY] = true;
}
}
}
}
const visited: boolean[][] = Array.from({ length: m }, _ => new Array(n).fill(false));
let result = 0;
for (let i = 0; i < m; i++) {
for (let k = 0; k < n; k++) {
if (!visited[i][k] && grid[i][k] === '1') {
++result; // 遇到没访问过的陆地,+1
visited[i][k] = true;
dfs(grid, visited, i, k); // 将与其链接的陆地都标记上 true
}
}
}
return result;
}
```
### Rust
```rust

View File

@ -346,6 +346,46 @@ var numIslands = function (grid) {
};
```
### TypeScript
```TypeScript
function numIslands(grid: string[][]): number {
// 四个方向
const dir: number[][] = [[0, 1], [1, 0], [-1, 0], [0, -1]];
const [m, n]: [number, number] = [grid.length, grid[0].length];
function dfs(grid: string[][], visited: boolean[][], x: number, y: number) {
for (let i = 0; i < 4; i++) {
let nextX: number = x + dir[i][0];
let nextY: number = y + dir[i][1];
// 越界了,直接跳过
if (nextX < 0 || nextX >= m || nextY < 0 || nextY >= n) {
continue;
}
// 没有访问过同时是陆地
if (!visited[nextX][nextY] && grid[nextX][nextY] === '1') {
visited[nextX][nextY] = true;
dfs(grid, visited, nextX, nextY);
}
}
}
const visited: boolean[][] = Array.from({ length: m }, _ => new Array(n).fill(false));
let result: number = 0;
for (let i = 0; i < m; i++) {
for (let k = 0; k < n; k++) {
if (!visited[i][k] && grid[i][k] === '1') {
++result; // 遇到没访问过的陆地,+1
visited[i][k] = true;
dfs(grid, visited, i, k); // 将与其链接的陆地都标记上 true
}
}
}
return result;
}
```
### Go
```go

View File

@ -330,7 +330,40 @@ class Solution:
```
### Go
直接使用原链表
```go
/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
func removeElements(head *ListNode, val int) *ListNode {
//依旧是先定义逻辑
//如果原链表的头节点为val的话head=head.next且为持续过程防止头节点后面的节点也为Val
//这里前置循环 并且要判定head 是否为nil防止出错
for head != nil && head.Val == val {//由于leetcode代码运行方式for循环条件判断前后顺序不能修改下面的for循环也同样如此
head = head.Next
}
cur := head
for cur != nil && cur.Next != nil {
if cur.Next.Val == val {
cur.Next = cur.Next.Next
} else {
cur = cur.Next
}
}
return head
}
```
虚拟头节点方式:
```go
/**
* Definition for singly-linked list.

View File

@ -633,7 +633,66 @@ object Solution {
}
}
```
### C#
```csharp
public class Solution
{
public IList<IList<int>> res = new List<IList<int>>();
public IList<int> path = new List<int>();
public IList<IList<int>> CombinationSum3(int k, int n)
{
BackTracking(k, n, 0, 1);
return res;
}
public void BackTracking(int k, int n, int sum, int start)
{
if (path.Count == k)
{
if (sum == n)
res.Add(new List<int>(path));
return;
}
for (int i = start; i <= 9; i++)
{
sum += i;
path.Add(i);
BackTracking(k, n, sum, i + 1);
sum -= i;
path.RemoveAt(path.Count - 1);
}
}
}
// 剪枝
public class Solution
{
public IList<IList<int>> res = new List<IList<int>>();
public IList<int> path = new List<int>();
public IList<IList<int>> CombinationSum3(int k, int n)
{
BackTracking(k, n, 0, 1);
return res;
}
public void BackTracking(int k, int n, int sum, int start)
{
if (sum > n)
return;
if (path.Count == k)
{
if (sum == n)
res.Add(new List<int>(path));
return;
}
for (int i = start; i <= 9 - (k - path.Count) + 1; i++)
{
sum += i;
path.Add(i);
BackTracking(k, n, sum, i + 1);
sum -= i;
path.RemoveAt(path.Count - 1);
}
}
}
```

View File

@ -235,52 +235,77 @@ class MyQueue:
### Go
```Go
type MyQueue struct {
stackIn []int //输入栈
stackOut []int //输出栈
// 通过切片实现一个栈
// 由于只是辅助实现算法题目,因此不做异常情况处理
type MyStack []int
func (s *MyStack) Push(v int) {
*s = append(*s, v)
}
func (s *MyStack) Pop() int {
val := (*s)[len(*s)-1]
*s = (*s)[:len(*s)-1]
return val
}
func (s *MyStack) Peek() int {
return (*s)[len(*s)-1]
}
func (s *MyStack) Size() int {
return len(*s)
}
func (s *MyStack) Empty() bool {
return s.Size() == 0
}
// ---------- 分界线 ----------
type MyQueue struct {
stackIn *MyStack
stackOut *MyStack
}
func Constructor() MyQueue {
return MyQueue{
stackIn: make([]int, 0),
stackOut: make([]int, 0),
return MyQueue {
stackIn: &MyStack{},
stackOut: &MyStack{},
}
}
// 往输入栈做push
func (this *MyQueue) Push(x int) {
this.stackIn = append(this.stackIn, x)
func (this *MyQueue) Push(x int) {
this.stackIn.Push(x)
}
// 在输出栈做poppop时如果输出栈数据为空需要将输入栈全部数据导入如果非空则可直接使用
func (this *MyQueue) Pop() int {
inLen, outLen := len(this.stackIn), len(this.stackOut)
if outLen == 0 {
if inLen == 0 {
return -1
}
for i := inLen - 1; i >= 0; i-- {
this.stackOut = append(this.stackOut, this.stackIn[i])
}
this.stackIn = []int{} //导出后清空
outLen = len(this.stackOut) //更新长度值
}
val := this.stackOut[outLen-1]
this.stackOut = this.stackOut[:outLen-1]
return val
this.fillStackOut()
return this.stackOut.Pop()
}
func (this *MyQueue) Peek() int {
val := this.Pop()
if val == -1 {
return -1
}
this.stackOut = append(this.stackOut, val)
return val
this.fillStackOut()
return this.stackOut.Peek()
}
func (this *MyQueue) Empty() bool {
return len(this.stackIn) == 0 && len(this.stackOut) == 0
return this.stackIn.Empty() && this.stackOut.Empty()
}
// fillStackOut 填充输出栈
func (this *MyQueue) fillStackOut() {
if this.stackOut.Empty() {
for !this.stackIn.Empty() {
val := this.stackIn.Pop()
this.stackOut.Push(val)
}
}
}
```

View File

@ -48,7 +48,7 @@
在有序树里如果判断一个节点的左子树里有p右子树里有q呢
因为是有序树,所 如果 中间节点是 q 和 p 的公共祖先,那么 中节点的数组 一定是在 [p, q]区间的。即 中节点 > p && 中节点 < q 或者 中节点 > q && 中节点 < p
因为是有序树,所 如果 中间节点是 q 和 p 的公共祖先,那么 中节点的数组 一定是在 [p, q]区间的。即 中节点 > p && 中节点 < q 或者 中节点 > q && 中节点 < p
那么只要从上到下去遍历遇到 cur节点是数值在[p, q]区间中则一定可以说明该节点cur就是p q的公共祖先 那问题来了**一定是最近公共祖先吗**
@ -328,27 +328,34 @@ class Solution:
```
### Go
递归法
递归法
```go
func lowestCommonAncestor(root, p, q *TreeNode) *TreeNode {
if root == nil {
return nil
}
for {
if root.Val > p.Val && root.Val > q.Val {
root = root.Left
}
if root.Val < p.Val && root.Val < q.Val {
root = root.Right
}
if (root.Val - p.Val) * (root.Val - q.Val) <= 0 {
return root
}
}
if root.Val > p.Val && root.Val > q.Val {
return lowestCommonAncestor(root.Left, p, q)
} else if root.Val < p.Val && root.Val < q.Val {
return lowestCommonAncestor(root.Right, p, q)
} else {
return root
}
}
```
迭代法
```go
func lowestCommonAncestor(root, p, q *TreeNode) *TreeNode {
for root != nil {
if root.Val > p.Val && root.Val > q.Val {
root = root.Left
} else if root.Val < p.Val && root.Val < q.Val {
root = root.Right
} else {
return root
}
}
return nil
}
```
### JavaScript
@ -513,6 +520,31 @@ impl Solution {
}
}
```
### C#
```C#
// 递归
public TreeNode LowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q)
{
if (root.val > p.val && root.val > q.val)
return LowestCommonAncestor(root.left, p, q);
if (root.val < p.val && root.val < q.val)
return LowestCommonAncestor(root.right, p, q);
return root;
}
// 迭代
public TreeNode LowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q)
{
while (root != null)
{
if (root.val > p.val && root.val > q.val)
root = root.left;
else if (root.val < p.val && root.val < q.val)
root = root.right;
else return root;
}
return null;
}
```
<p align="center">

View File

@ -431,6 +431,19 @@ impl Solution {
}
}
```
### C#
```C#
public TreeNode LowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q)
{
if (root == null || root == p || root == q) return root;
TreeNode left = LowestCommonAncestor(root.left, p, q);
TreeNode right = LowestCommonAncestor(root.right, p, q);
if (left != null && right != null) return root;
if (left == null && right != null) return right;
if (left != null && right == null) return left;
return null;
}
```
<p align="center">
<a href="https://programmercarl.com/other/kstar.html" target="_blank">

View File

@ -130,7 +130,7 @@ public:
class Solution {
public int lengthOfLIS(int[] nums) {
int[] dp = new int[nums.length];
int res = 0;
int res = 1;
Arrays.fill(dp, 1);
for (int i = 1; i < dp.length; i++) {
for (int j = 0; j < i; j++) {

View File

@ -562,6 +562,7 @@ func findItinerary(tickets [][]string) []string {
```
### Javascript
```Javascript
var findItinerary = function(tickets) {
@ -605,6 +606,74 @@ var findItinerary = function(tickets) {
```
**javascript版本二 处理对象key无序问题**
```javascript
/**
* @param {string[][]} tickets
* @return {string[]}
*/
var findItinerary = function (tickets) {
const ans = ["JFK"];
let map = {};
// 整理每个站点的终点站信息
tickets.forEach((t) => {
let targets = map[t[0]];
if (!targets) {
targets = { [t[1]]: 0 };
map[t[0]] = targets;
}
targets[t[1]] = (targets[t[1]] || 0) + 1;
});
// 按照key字典序排序对象
const sortObject = (obj) => {
const newObj = {};
const keys = Object.keys(obj);
keys.sort((k1, k2) => (k1 < k2 ? -1 : 1));
keys.forEach((key) => {
if (obj[key] !== null && typeof obj[key] === "object") {
newObj[key] = sortObject(obj[key]);
} else {
newObj[key] = obj[key];
}
});
return newObj;
};
const backtrack = (tickets, targets) => {
if (ans.length === tickets.length + 1) {
return true;
}
const target = targets[ans[ans.length - 1]];
// 没有下一站
if (!target) {
return false;
}
// 或者在这里排序
// const keyList = Object.keys(target).sort((k1, k2) => (k1 < k2 ? -1 : 1));
const keyList = Object.keys(target);
for (const key of keyList) {
// 判断当前站是否还能飞
if (target[key] > 0) {
target[key]--;
ans.push(key);
// 对象key有序 此时的行程就是字典序最小的 直接跳出
if (backtrack(tickets, targets)) {
return true;
}
target[key]++;
ans.pop();
}
}
return false;
};
map = sortObject(map);
backtrack(tickets, map);
return ans;
};
```
### TypeScript
```typescript
@ -901,3 +970,4 @@ impl Solution {
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
</a>

View File

@ -145,43 +145,43 @@ public:
class Solution {
//解法1基于大顶堆实现
public int[] topKFrequent1(int[] nums, int k) {
Map<Integer,Integer> map = new HashMap<>();//key为数组元素值,val为对应出现次数
for(int num:nums){
map.put(num,map.getOrDefault(num,0)+1);
Map<Integer,Integer> map = new HashMap<>(); //key为数组元素值,val为对应出现次数
for (int num : nums) {
map.put(num, map.getOrDefault(num,0) + 1);
}
//在优先队列中存储二元组(num,cnt),cnt表示元素值num在数组中的出现次数
//在优先队列中存储二元组(num, cnt),cnt表示元素值num在数组中的出现次数
//出现次数按从队头到队尾的顺序是从大到小排,出现次数最多的在队头(相当于大顶堆)
PriorityQueue<int[]> pq = new PriorityQueue<>((pair1, pair2)->pair2[1]-pair1[1]);
for(Map.Entry<Integer,Integer> entry:map.entrySet()){//大顶堆需要对所有元素进行排序
pq.add(new int[]{entry.getKey(),entry.getValue()});
PriorityQueue<int[]> pq = new PriorityQueue<>((pair1, pair2) -> pair2[1] - pair1[1]);
for (Map.Entry<Integer, Integer> entry : map.entrySet()) {//大顶堆需要对所有元素进行排序
pq.add(new int[]{entry.getKey(), entry.getValue()});
}
int[] ans = new int[k];
for(int i=0;i<k;i++){//依次从队头弹出k个,就是出现频率前k高的元素
for (int i = 0; i < k; i++) { //依次从队头弹出k个,就是出现频率前k高的元素
ans[i] = pq.poll()[0];
}
return ans;
}
//解法2基于小顶堆实现
public int[] topKFrequent2(int[] nums, int k) {
Map<Integer,Integer> map = new HashMap<>();//key为数组元素值,val为对应出现次数
for(int num:nums){
map.put(num,map.getOrDefault(num,0)+1);
Map<Integer,Integer> map = new HashMap<>(); //key为数组元素值,val为对应出现次数
for (int num : nums) {
map.put(num, map.getOrDefault(num, 0) + 1);
}
//在优先队列中存储二元组(num,cnt),cnt表示元素值num在数组中的出现次数
//在优先队列中存储二元组(num, cnt),cnt表示元素值num在数组中的出现次数
//出现次数按从队头到队尾的顺序是从小到大排,出现次数最低的在队头(相当于小顶堆)
PriorityQueue<int[]> pq = new PriorityQueue<>((pair1,pair2)->pair1[1]-pair2[1]);
for(Map.Entry<Integer,Integer> entry:map.entrySet()){//小顶堆只需要维持k个元素有序
if(pq.size()<k){//小顶堆元素个数小于k个时直接加
pq.add(new int[]{entry.getKey(),entry.getValue()});
}else{
if(entry.getValue()>pq.peek()[1]){//当前元素出现次数大于小顶堆的根结点(这k个元素中出现次数最少的那个)
pq.poll();//弹出队头(小顶堆的根结点),即把堆里出现次数最少的那个删除,留下的就是出现次数多的了
pq.add(new int[]{entry.getKey(),entry.getValue()});
PriorityQueue<int[]> pq = new PriorityQueue<>((pair1, pair2) -> pair1[1] - pair2[1]);
for (Map.Entry<Integer, Integer> entry : map.entrySet()) { //小顶堆只需要维持k个元素有序
if (pq.size() < k) { //小顶堆元素个数小于k个时直接加
pq.add(new int[]{entry.getKey(), entry.getValue()});
} else {
if (entry.getValue() > pq.peek()[1]) { //当前元素出现次数大于小顶堆的根结点(这k个元素中出现次数最少的那个)
pq.poll(); //弹出队头(小顶堆的根结点),即把堆里出现次数最少的那个删除,留下的就是出现次数多的了
pq.add(new int[]{entry.getKey(), entry.getValue()});
}
}
}
int[] ans = new int[k];
for(int i=k-1;i>=0;i--){//依次弹出小顶堆,先弹出的是堆的根,出现次数少,后面弹出的出现次数多
for (int i = k - 1; i >= 0; i--) { //依次弹出小顶堆,先弹出的是堆的根,出现次数少,后面弹出的出现次数多
ans[i] = pq.poll()[0];
}
return ans;
@ -197,8 +197,8 @@ class Solution {
PriorityQueue<int[]> pq = new PriorityQueue<>((o1, o2) -> o1[1] - o2[1]);
int[] res = new int[k]; // 答案数组为 k 个元素
Map<Integer, Integer> map = new HashMap<>(); // 记录元素出现次数
for(int num : nums) map.put(num, map.getOrDefault(num, 0) + 1);
for(var x : map.entrySet()) { // entrySet 获取 k-v Set 集合
for (int num : nums) map.put(num, map.getOrDefault(num, 0) + 1);
for (var x : map.entrySet()) { // entrySet 获取 k-v Set 集合
// 将 kv 转化成数组
int[] tmp = new int[2];
tmp[0] = x.getKey();
@ -209,7 +209,7 @@ class Solution {
pq.poll();
}
}
for(int i = 0; i < k; i ++) {
for (int i = 0; i < k; i++) {
res[i] = pq.poll()[0]; // 获取优先队列里的元素
}
return res;

View File

@ -64,7 +64,7 @@
在计算是否有峰值的时候,大家知道遍历的下标 i ,计算 prediffnums[i] - nums[i-1] 和 curdiffnums[i+1] - nums[i]),如果`prediff < 0 && curdiff > 0` 或者 `prediff > 0 && curdiff < 0` 此时就有波动就需要统计。
这是我们思考本题的一个大思路,但本题要考虑三种情况:
这是我们思考本题的一个大思路,但本题要考虑三种情况:
1. 情况一:上下坡中有平坡
2. 情况二:数组首尾两端
@ -692,6 +692,27 @@ object Solution {
}
}
```
### C#
```csharp
public class Solution
{
public int WiggleMaxLength(int[] nums)
{
if (nums.Length < 2) return nums.Length;
int curDiff = 0, preDiff = 0, res = 1;
for (int i = 0; i < nums.Length - 1; i++)
{
curDiff = nums[i + 1] - nums[i];
if ((curDiff > 0 && preDiff <= 0) || (curDiff < 0 && preDiff >= 0))
{
res++;
preDiff = curDiff;
}
}
return res;
}
}
```
<p align="center">
<a href="https://programmercarl.com/other/kstar.html" target="_blank">

View File

@ -378,6 +378,28 @@ object Solution {
}
}
```
### C#
```csharp
public class Solution
{
public int FindContentChildren(int[] g, int[] s)
{
Array.Sort(g);
Array.Sort(s);
int index = s.Length - 1;
int res = 0;
for (int i = g.Length - 1; i >=0; i--)
{
if(index >=0 && s[index]>=g[i])
{
res++;
index--;
}
}
return res;
}
}
```
<p align="center">
<a href="https://programmercarl.com/other/kstar.html" target="_blank">

View File

@ -614,6 +614,32 @@ object Solution {
}
}
```
### C#
```csharp
public class Solution {
public IList<IList<int>> res = new List<IList<int>>();
public IList<int> path = new List<int>();
public IList<IList<int>> FindSubsequences(int[] nums) {
BackTracking(nums, 0);
return res;
}
public void BackTracking(int[] nums, int start){
if(path.Count >= 2){
res.Add(new List<int>(path));
}
HashSet<int> hs = new HashSet<int>();
for(int i = start; i < nums.Length; i++){
if(path.Count > 0 && path[path.Count - 1] > nums[i] || hs.Contains(nums[i])){
continue;
}
hs.Add(nums[i]);
path.Add(nums[i]);
BackTracking(nums, i + 1);
path.RemoveAt(path.Count - 1);
}
}
}
```
<p align="center">
<a href="https://programmercarl.com/other/kstar.html" target="_blank">

View File

@ -275,19 +275,23 @@ class Solution {
public int findTargetSumWays(int[] nums, int target) {
int sum = 0;
for (int i = 0; i < nums.length; i++) sum += nums[i];
//如果target过大 sum将无法满足
if ( target < 0 && sum < -target) return 0;
if ((target + sum) % 2 != 0) return 0;
int size = (target + sum) / 2;
if(size < 0) size = -size;
int[] dp = new int[size + 1];
//如果target的绝对值大于sum那么是没有方案的
if (Math.abs(target) > sum) return 0;
//如果(target+sum)除以2的余数不为0也是没有方案的
if ((target + sum) % 2 == 1) return 0;
int bagSize = (target + sum) / 2;
int[] dp = new int[bagSize + 1];
dp[0] = 1;
for (int i = 0; i < nums.length; i++) {
for (int j = size; j >= nums[i]; j--) {
for (int j = bagSize; j >= nums[i]; j--) {
dp[j] += dp[j - nums[i]];
}
}
return dp[size];
return dp[bagSize];
}
}
```

View File

@ -1009,6 +1009,46 @@ pub fn find_mode(root: Option<Rc<RefCell<TreeNode>>>) -> Vec<i32> {
res
}
```
### C#
```C#
// 递归
public class Solution
{
public List<int> res = new List<int>();
public int count = 0;
public int maxCount = 0;
public TreeNode pre = null;
public int[] FindMode(TreeNode root)
{
SearchBST(root);
return res.ToArray();
}
public void SearchBST(TreeNode root)
{
if (root == null) return;
SearchBST(root.left);
if (pre == null)
count = 1;
else if (pre.val == root.val)
count++;
else
count = 1;
pre = root;
if (count == maxCount)
{
res.Add(root.val);
}
else if (count > maxCount)
{
res.Clear();
res.Add(root.val);
maxCount = count;
}
SearchBST(root.right);
}
}
```
<p align="center">

View File

@ -647,6 +647,27 @@ impl Solution {
}
}
```
### C#
```C#
// 递归
public class Solution
{
public List<int> res = new List<int>();
public int GetMinimumDifference(TreeNode root)
{
Traversal(root);
return res.SelectMany((x, i) => res.Skip(i + 1).Select(y => Math.Abs(x - y))).Min();
}
public void Traversal(TreeNode root)
{
if (root == null) return;
Traversal(root.left);
res.Add(root.val);
Traversal(root.right);
}
}
```
<p align="center">
<a href="https://programmercarl.com/other/kstar.html" target="_blank">

View File

@ -529,6 +529,23 @@ impl Solution {
}
}
```
### C#
```C#
// 递归
public class Solution
{
int pre = 0;
public TreeNode ConvertBST(TreeNode root)
{
if (root == null) return null;
ConvertBST(root.right);
root.val += pre;
pre = root.val;
ConvertBST(root.left);
return root;
}
}
```
<p align="center">

View File

@ -567,6 +567,23 @@ impl Solution {
}
}
```
### C#
```C#
// 递归
public TreeNode TrimBST(TreeNode root, int low, int high)
{
if (root == null) return null;
if (root.val < low)
return TrimBST(root.right, low, high);
if (root.val > high)
return TrimBST(root.left, low, high);
root.left = TrimBST(root.left, low, high);
root.right = TrimBST(root.right, low, high);
return root;
}
```
<p align="center">

View File

@ -464,6 +464,28 @@ impl Solution {
}
}
```
### C#
```C#
// 递归
public TreeNode SearchBST(TreeNode root, int val)
{
if (root == null || root.val == val) return root;
if (root.val > val) return SearchBST(root.left, val);
if (root.val < val) return SearchBST(root.right, val);
return null;
}
// 迭代
public TreeNode SearchBST(TreeNode root, int val)
{
while (root != null)
{
if (root.val > val) root = root.left;
else if (root.val < val) root = root.right;
else return root;
}
return null;
}
```
<p align="center">
<a href="https://programmercarl.com/other/kstar.html" target="_blank">

View File

@ -691,6 +691,17 @@ impl Solution {
}
}
```
### C#
``` C#
// 递归
public TreeNode InsertIntoBST(TreeNode root, int val) {
if (root == null) return new TreeNode(val);
if (root.val > val) root.left = InsertIntoBST(root.left, val);
if (root.val < val) root.right = InsertIntoBST(root.right, val);
return root;
}
```
<p align="center">

View File

@ -2,7 +2,7 @@
<a href="https://programmercarl.com/other/xunlianying.html" target="_blank">
<img src="../pics/训练营.png" width="1000"/>
</a>
<p align="center"><strong><a href="https://mp.weixin.qq.com/s/tqCxrMEU-ajQumL1i8im9A">参与本项目</a>,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们益!</strong></p>
<p align="center"><strong><a href="https://mp.weixin.qq.com/s/tqCxrMEU-ajQumL1i8im9A">参与本项目</a>,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们益!</strong></p>
# 704. 二分查找
@ -251,40 +251,60 @@ class Solution:
(版本一)左闭右闭区间
```go
// 时间复杂度 O(logn)
func search(nums []int, target int) int {
high := len(nums)-1
low := 0
for low <= high {
mid := low + (high-low)/2
if nums[mid] == target {
return mid
} else if nums[mid] > target {
high = mid-1
} else {
low = mid+1
}
}
return -1
// 初始化左右边界
left := 0
right := len(nums) - 1
// 循环逐步缩小区间范围
for left <= right {
// 求区间中点
mid := left + (right-left)>>1
// 根据 nums[mid] 和 target 的大小关系
// 调整区间范围
if nums[mid] == target {
return mid
} else if nums[mid] < target {
left = mid + 1
} else {
right = mid - 1
}
}
// 在输入数组内没有找到值等于 target 的元素
return -1
}
```
(版本二)左闭右开区间
```go
// 时间复杂度 O(logn)
func search(nums []int, target int) int {
high := len(nums)
low := 0
for low < high {
mid := low + (high-low)/2
if nums[mid] == target {
return mid
} else if nums[mid] > target {
high = mid
} else {
low = mid+1
}
}
return -1
// 初始化左右边界
left := 0
right := len(nums)
// 循环逐步缩小区间范围
for left < right {
// 求区间中点
mid := left + (right-left)>>1
// 根据 nums[mid] 和 target 的大小关系
// 调整区间范围
if nums[mid] == target {
return mid
} else if nums[mid] < target {
left = mid + 1
} else {
right = mid
}
}
// 在输入数组内没有找到值等于 target 的元素
return -1
}
```

View File

@ -16,7 +16,7 @@
示例 1
* 输入A = [4,2,3], K = 1
* 输出5
* 解释:选择索引 (1,) ,然后 A 变为 [4,-2,3]。
* 解释:选择索引 (1) ,然后 A 变为 [4,-2,3]。
示例 2
* 输入A = [3,-1,0,2], K = 3

View File

@ -183,11 +183,67 @@ func main(){
fmt.Printf(string(strByte))
}
````
Go使用双指针解法
````go
package main
import "fmt"
func replaceNumber(strByte []byte) string {
// 查看有多少字符
numCount, oldSize := 0, len(strByte)
for i := 0; i < len(strByte); i++ {
if (strByte[i] <= '9') && (strByte[i] >= '0') {
numCount ++
}
}
// 增加长度
for i := 0; i < numCount; i++ {
strByte = append(strByte, []byte(" ")...)
}
tmpBytes := []byte("number")
// 双指针从后遍历
leftP, rightP := oldSize-1, len(strByte)-1
for leftP < rightP {
rightShift := 1
// 如果是数字则加入number
if (strByte[leftP] <= '9') && (strByte[leftP] >= '0') {
for i, tmpByte := range tmpBytes {
strByte[rightP-len(tmpBytes)+i+1] = tmpByte
}
rightShift = len(tmpBytes)
} else {
strByte[rightP] = strByte[leftP]
}
// 更新指针
rightP -= rightShift
leftP -= 1
}
return string(strByte)
}
func main(){
var strByte []byte
fmt.Scanln(&strByte)
newString := replaceNumber(strByte)
fmt.Println(newString)
}
````
### python
```Python
class Solution:
def change(self, s):
lst = list(s) # Python里面的string也是不可改的所以也是需要额外空间的。空间复杂度O(n)。
for i in range(len(lst)):
if lst[i].isdigit():
lst[i] = "number"
return ''.join(lst)
```
### JavaScript:

View File

@ -10,7 +10,7 @@
**时间复杂度是一个函数,它定性描述该算法的运行时间**
我们在软件开发中,时间复杂度就是用来方便开发者估算出程序运行的答题时间。
我们在软件开发中,时间复杂度就是用来方便开发者估算出程序运行的大体时间。
那么该如何估计程序运行时间呢通常会估算算法的操作单元数量来代表程序消耗的时间这里默认CPU的每个单元运行消耗的时间都是相同的。
@ -80,13 +80,13 @@ O(2*n^2 + 10*n)
O(n^2 + n)
```
只保留保留最高项去掉数量级小一级的n 因为n^2 的数据规模远大于n最终简化为
只保留最高项去掉数量级小一级的n 因为n^2 的数据规模远大于n最终简化为
```
O(n^2)
```
如果这一步理解有困难那也可以做提取n的操作变成O(n(n+1))省略加法常数项后也就变成了
如果这一步理解有困难那也可以做提取n的操作变成O(n(n+1))省略加法常数项后也就变成了
```
O(n^2)
@ -96,7 +96,7 @@ O(n^2)
也可以用另一种简化的思路其实当n大于40的时候 这个复杂度会恒小于O(3 × n^2)
O(2 × n^2 + 10 × n + 1000) < O(3 × n^2)所以说最后省略掉常数项系数最终时间复杂度也是O(n^2)。
O(2 × n^2 + 10 × n + 1000) < O(3 × n^2)3 × n^2省略掉常数项系数最终时间复杂度也是O(n^2)。
## O(log n)中的log是以什么为底
@ -127,7 +127,7 @@ O(2 × n^2 + 10 × n + 1000) < O(3 × n^2),所以说最后省略掉常数项
接下来再想一下其他解题思路
对n个字符串按字典序来排序排序后n个字符串就是有序的意味着两个相同的字符串就是挨在一起然后遍历一遍n个字符串这样就找到两个相同的字符串了
先对n个字符串按字典序来排序排序后n个字符串就是有序的意味着两个相同的字符串就是挨在一起然后遍历一遍n个字符串这样就找到两个相同的字符串了
那看看这种算法的时间复杂度快速排序时间复杂度为O(nlog n)依然要考虑字符串的长度是m那么快速排序每次的比较都要有m次的字符比较的操作就是O(m × n × log n)。
@ -139,13 +139,13 @@ O(2 × n^2 + 10 × n + 1000) < O(3 × n^2),所以说最后省略掉常数项
所以先把字符串集合排序再遍历一遍找到两个相同字符串的方法要比直接暴力枚举的方式更快
这就是我们通过分析两种算法的时间复杂度得来的
这就是我们通过分析两种算法的时间复杂度得来的结论
**当然这不是这道题目的最优解,我仅仅是用这道题目来讲解一下时间复杂度**
## 总结
本篇讲解了什么是时间复杂度复杂度是用来干什么以及数据规模对时间复杂度的影响
本篇讲解了什么是时间复杂度复杂度是用来干什么以及数据规模对时间复杂度的影响
还讲解了被大多数同学忽略的大O的定义以及log究竟是以谁为底的问题

View File

@ -65,7 +65,7 @@
**回溯法解决的问题都可以抽象为树形结构**,是的,我指的是所有回溯法的问题都可以抽象为树形结构!
因为回溯法解决的都是在集合中递归查找子集,**集合的大小就构成了树的宽度,递归的深度,都构成树的深度**。
因为回溯法解决的都是在集合中递归查找子集,**集合的大小就构成了树的宽度,递归的深度构成树的深度**。
递归就要有终止条件所以必然是一棵高度有限的树N叉树

View File

@ -115,7 +115,7 @@ cd a/b/c/../../
**单调队列不是一成不变的,而是不同场景不同写法**,总之要保证队列里单调递减或递增的原则,所以叫做单调队列。
**不要以为本中的单调队列实现就是固定的写法。**
**不要以为本中的单调队列实现就是固定的写法。**
我们用deque作为单调队列的底层数据结构C++中deque是stack和queue默认的底层实现容器这个我们之前已经讲过deque是可以两边扩展的而且deque里元素并不是严格的连续分布的。

View File

@ -165,7 +165,43 @@ int main() {
### Java
```Java
import java.util.Scanner;
class multi_pack{
public static void main(String [] args) {
Scanner sc = new Scanner(System.in);
/**
* bagWeight:背包容量
* n:物品种类
*/
int bagWeight, n;
//获取用户输入数据,中间用空格隔开,回车键换行
bagWeight = sc.nextInt();
n = sc.nextInt();
int[] weight = new int[n];
int[] value = new int[n];
int[] nums = new int[n];
for (int i = 0; i < n; i++) weight[i] = sc.nextInt();
for (int i = 0; i < n; i++) value[i] = sc.nextInt();
for (int i = 0; i < n; i++) nums[i] = sc.nextInt();
int[] dp = new int[bagWeight + 1];
//先遍历物品再遍历背包作为01背包处理
for (int i = 0; i < n; i++) {
for (int j = bagWeight; j >= weight[i]; j--) {
//遍历每种物品的个数
for (int k = 1; k <= nums[i] && (j - k * weight[i]) >= 0; k++) {
dp[j] = Math.max(dp[j], dp[j - k * weight[i]] + k * value[i]);
}
}
}
System.out.println(dp[bagWeight]);
}
}
```
### Python
### Go

View File

@ -22,7 +22,7 @@
### 虚拟头结点
在[链表:听说用虚拟头节点会方便很多?](https://programmercarl.com/0203.移除链表元素.html)中,我们讲解了链表操作中一个非常要的技巧:虚拟头节点。
在[链表:听说用虚拟头节点会方便很多?](https://programmercarl.com/0203.移除链表元素.html)中,我们讲解了链表操作中一个非常要的技巧:虚拟头节点。
链表的一大问题就是操作当前节点必须要找前一个节点才能操作。这就造成了,头结点的尴尬,因为头结点没有前一个节点了。
@ -32,7 +32,7 @@
### 链表的基本操作
在[链表:一道题目考察了常见的五个操作!](https://programmercarl.com/0707.设计链表.html)中,我们通设计链表把链表常见的五个操作练习了一遍。
在[链表:一道题目考察了常见的五个操作!](https://programmercarl.com/0707.设计链表.html)中,我们通设计链表把链表常见的五个操作练习了一遍。
这是练习链表基础操作的非常好的一道题目,考察了:

View File

@ -250,9 +250,32 @@ typedef struct ListNodeT {
} ListNode;
```
### C#
```c#
public class Node<T>
{
// 节点存储的数据
public T Data { get; set; }
// 指向下一个节点的引用
public Node<T> Next { get; set; }
// 节点的构造函数,用于初始化节点
public Node(T data)
{
Data = data;
Next = null; // 初始时没有下一个节点,因此设为 null
}
}
```
<p align="center">
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
</a>