diff --git a/problems/0053.最大子序和(动态规划).md b/problems/0053.最大子序和(动态规划).md
index 4c883cb6..99aa7acf 100644
--- a/problems/0053.最大子序和(动态规划).md
+++ b/problems/0053.最大子序和(动态规划).md
@@ -186,6 +186,24 @@ const maxSubArray = nums => {
};
```
+TypeScript:
+
+```typescript
+function maxSubArray(nums: number[]): number {
+ /**
+ dp[i]:以nums[i]结尾的最大和
+ */
+ const dp: number[] = []
+ dp[0] = nums[0];
+ let resMax: number = 0;
+ for (let i = 1; i < nums.length; i++) {
+ dp[i] = Math.max(dp[i - 1] + nums[i], nums[i]);
+ resMax = Math.max(resMax, dp[i]);
+ }
+ return resMax;
+};
+```
+
-----------------------
diff --git a/problems/0072.编辑距离.md b/problems/0072.编辑距离.md
index 3802c228..530774ee 100644
--- a/problems/0072.编辑距离.md
+++ b/problems/0072.编辑距离.md
@@ -327,5 +327,42 @@ const minDistance = (word1, word2) => {
};
```
+TypeScript:
+
+```typescript
+function minDistance(word1: string, word2: string): number {
+ /**
+ dp[i][j]: word1前i个字符,word2前j个字符,最少操作数
+ dp[0][0]=0:表示word1前0个字符为'', word2前0个字符为''
+ */
+ const length1: number = word1.length,
+ length2: number = word2.length;
+ const dp: number[][] = new Array(length1 + 1).fill(0)
+ .map(_ => new Array(length2 + 1).fill(0));
+ for (let i = 0; i <= length1; i++) {
+ dp[i][0] = i;
+ }
+ for (let i = 0; i <= length2; i++) {
+ dp[0][i] = i;
+ }
+ for (let i = 1; i <= length1; i++) {
+ for (let j = 1; j <= length2; j++) {
+ if (word1[i - 1] === word2[j - 1]) {
+ dp[i][j] = dp[i - 1][j - 1];
+ } else {
+ dp[i][j] = Math.min(
+ dp[i - 1][j],
+ dp[i][j - 1],
+ dp[i - 1][j - 1]
+ ) + 1;
+ }
+ }
+ }
+ return dp[length1][length2];
+};
+```
+
+
+
-----------------------
diff --git a/problems/0093.复原IP地址.md b/problems/0093.复原IP地址.md
index 6401824b..d5eaa8ab 100644
--- a/problems/0093.复原IP地址.md
+++ b/problems/0093.复原IP地址.md
@@ -444,7 +444,7 @@ var restoreIpAddresses = function(s) {
return;
}
for(let j = i; j < s.length; j++) {
- const str = s.substr(i, j - i + 1);
+ const str = s.slice(i, j + 1);
if(str.length > 3 || +str > 255) break;
if(str.length > 1 && str[0] === "0") break;
path.push(str);
diff --git a/problems/0101.对称二叉树.md b/problems/0101.对称二叉树.md
index 1eb43589..c79fde0e 100644
--- a/problems/0101.对称二叉树.md
+++ b/problems/0101.对称二叉树.md
@@ -725,5 +725,25 @@ func isSymmetric3(_ root: TreeNode?) -> Bool {
}
```
+## Scala
+
+递归:
+```scala
+object Solution {
+ def isSymmetric(root: TreeNode): Boolean = {
+ if (root == null) return true // 如果等于空直接返回true
+ def compare(left: TreeNode, right: TreeNode): Boolean = {
+ if (left == null && right == null) return true // 如果左右都为空,则为true
+ if (left == null && right != null) return false // 如果左空右不空,不对称,返回false
+ if (left != null && right == null) return false // 如果左不空右空,不对称,返回false
+ // 如果左右的值相等,并且往下递归
+ left.value == right.value && compare(left.left, right.right) && compare(left.right, right.left)
+ }
+ // 分别比较左子树和右子树
+ compare(root.left, root.right)
+ }
+}
+```
+
-----------------------
diff --git a/problems/0115.不同的子序列.md b/problems/0115.不同的子序列.md
index 0f762969..ca66e20d 100644
--- a/problems/0115.不同的子序列.md
+++ b/problems/0115.不同的子序列.md
@@ -267,6 +267,36 @@ const numDistinct = (s, t) => {
};
```
+TypeScript:
+
+```typescript
+function numDistinct(s: string, t: string): number {
+ /**
+ dp[i][j]: s前i个字符,t前j个字符,s子序列中t出现的个数
+ dp[0][0]=1, 表示s前0个字符为'',t前0个字符为''
+ */
+ const sLen: number = s.length,
+ tLen: number = t.length;
+ const dp: number[][] = new Array(sLen + 1).fill(0)
+ .map(_ => new Array(tLen + 1).fill(0));
+ for (let m = 0; m < sLen; m++) {
+ dp[m][0] = 1;
+ }
+ for (let i = 1; i <= sLen; i++) {
+ for (let j = 1; j <= tLen; j++) {
+ if (s[i - 1] === t[j - 1]) {
+ dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j];
+ } else {
+ dp[i][j] = dp[i - 1][j];
+ }
+ }
+ }
+ return dp[sLen][tLen];
+};
+```
+
+
+
-----------------------
diff --git a/problems/0131.分割回文串.md b/problems/0131.分割回文串.md
index 7a702898..6a370fb4 100644
--- a/problems/0131.分割回文串.md
+++ b/problems/0131.分割回文串.md
@@ -442,7 +442,7 @@ var partition = function(s) {
}
for(let j = i; j < len; j++) {
if(!isPalindrome(s, i, j)) continue;
- path.push(s.substr(i, j - i + 1));
+ path.push(s.slice(i, j + 1));
backtracking(j + 1);
path.pop();
}
diff --git a/problems/0202.快乐数.md b/problems/0202.快乐数.md
index be8686f7..7738b2f6 100644
--- a/problems/0202.快乐数.md
+++ b/problems/0202.快乐数.md
@@ -417,6 +417,7 @@ object Solution {
}
sum
}
+```
C#:
diff --git a/problems/0209.长度最小的子数组.md b/problems/0209.长度最小的子数组.md
index fbef7692..69e0da4f 100644
--- a/problems/0209.长度最小的子数组.md
+++ b/problems/0209.长度最小的子数组.md
@@ -5,7 +5,7 @@
参与本项目,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!
-## 209.长度最小的子数组
+# 209.长度最小的子数组
[力扣题目链接](https://leetcode-cn.com/problems/minimum-size-subarray-sum/)
@@ -17,6 +17,9 @@
输出:2
解释:子数组 [4,3] 是该条件下的长度最小的子数组。
+# 思路
+
+为了易于大家理解,我特意录制了[拿下滑动窗口! | LeetCode 209 长度最小的子数组](https://www.bilibili.com/video/BV1tZ4y1q7XE)
## 暴力解法
@@ -47,8 +50,8 @@ public:
}
};
```
-时间复杂度:O(n^2)
-空间复杂度:O(1)
+* 时间复杂度:O(n^2)
+* 空间复杂度:O(1)
## 滑动窗口
@@ -56,6 +59,20 @@ public:
所谓滑动窗口,**就是不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果**。
+在暴力解法中,是一个for循环滑动窗口的起始位置,一个for循环为滑动窗口的终止位置,用两个for循环 完成了一个不断搜索区间的过程。
+
+那么滑动窗口如何用一个for循环来完成这个操作呢。
+
+首先要思考 如果用一个for循环,那么应该表示 滑动窗口的起始位置,还是终止位置。
+
+如果只用一个for循环来表示 滑动窗口的起始位置,那么如何遍历剩下的终止位置?
+
+此时难免再次陷入 暴力解法的怪圈。
+
+所以 只用一个for循环,那么这个循环的索引,一定是表示 滑动窗口的终止位置。
+
+那么问题来了, 滑动窗口的起始位置如何移动呢?
+
这里还是以题目中的示例来举例,s=7, 数组是 2,3,1,2,4,3,来看一下查找的过程:

@@ -74,7 +91,7 @@ public:
窗口的起始位置如何移动:如果当前窗口的值大于s了,窗口就要向前移动了(也就是该缩小了)。
-窗口的结束位置如何移动:窗口的结束位置就是遍历数组的指针,窗口的起始位置设置为数组的起始位置就可以了。
+窗口的结束位置如何移动:窗口的结束位置就是遍历数组的指针,也就是for循环里的索引。
解题的关键在于 窗口的起始位置如何移动,如图所示:
@@ -107,8 +124,8 @@ public:
};
```
-时间复杂度:O(n)
-空间复杂度:O(1)
+* 时间复杂度:O(n)
+* 空间复杂度:O(1)
**一些录友会疑惑为什么时间复杂度是O(n)**。
diff --git a/problems/0216.组合总和III.md b/problems/0216.组合总和III.md
index 32b1347e..66ca7ff7 100644
--- a/problems/0216.组合总和III.md
+++ b/problems/0216.组合总和III.md
@@ -360,39 +360,30 @@ func backTree(n,k,startIndex int,track *[]int,result *[][]int){
## javaScript
```js
-// 等差数列
-var maxV = k => k * (9 + 10 - k) / 2;
-var minV = k => k * (1 + k) / 2;
+/**
+ * @param {number} k
+ * @param {number} n
+ * @return {number[][]}
+ */
var combinationSum3 = function(k, n) {
- if (k > 9 || k < 1) return [];
- // if (n > maxV(k) || n < minV(k)) return [];
- // if (n === maxV(k)) return [Array.from({length: k}).map((v, i) => 9 - i)];
- // if (n === minV(k)) return [Array.from({length: k}).map((v, i) => i + 1)];
-
- const res = [], path = [];
- backtracking(k, n, 1, 0);
- return res;
- function backtracking(k, n, i, sum){
- const len = path.length;
- if (len > k || sum > n) return;
- if (maxV(k - len) < n - sum) return;
- if (minV(k - len) > n - sum) return;
-
- if(len === k && sum == n) {
- res.push(Array.from(path));
+ const backtrack = (start) => {
+ const l = path.length;
+ if (l === k) {
+ const sum = path.reduce((a, b) => a + b);
+ if (sum === n) {
+ res.push([...path]);
+ }
return;
}
-
- const min = Math.min(n - sum, 9 + len - k + 1);
-
- for(let a = i; a <= min; a++) {
- path.push(a);
- sum += a;
- backtracking(k, n, a + 1, sum);
+ for (let i = start; i <= 9 - (k - l) + 1; i++) {
+ path.push(i);
+ backtrack(i + 1);
path.pop();
- sum -= a;
}
}
+ let res = [], path = [];
+ backtrack(1);
+ return res;
};
```
diff --git a/problems/0226.翻转二叉树.md b/problems/0226.翻转二叉树.md
index af5b8043..9b5cfbae 100644
--- a/problems/0226.翻转二叉树.md
+++ b/problems/0226.翻转二叉树.md
@@ -818,5 +818,53 @@ func invertTree(_ root: TreeNode?) -> TreeNode? {
}
```
+### Scala
+
+深度优先遍历(前序遍历):
+```scala
+object Solution {
+ def invertTree(root: TreeNode): TreeNode = {
+ if (root == null) return root
+ // 递归
+ def process(node: TreeNode): Unit = {
+ if (node == null) return
+ // 翻转节点
+ val curNode = node.left
+ node.left = node.right
+ node.right = curNode
+ process(node.left)
+ process(node.right)
+ }
+ process(root)
+ root
+ }
+}
+```
+
+广度优先遍历(层序遍历):
+```scala
+object Solution {
+ import scala.collection.mutable
+ def invertTree(root: TreeNode): TreeNode = {
+ if (root == null) return root
+ val queue = mutable.Queue[TreeNode]()
+ queue.enqueue(root)
+ while (!queue.isEmpty) {
+ val len = queue.size
+ for (i <- 0 until len) {
+ var curNode = queue.dequeue()
+ if (curNode.left != null) queue.enqueue(curNode.left)
+ if (curNode.right != null) queue.enqueue(curNode.right)
+ // 翻转
+ var tmpNode = curNode.left
+ curNode.left = curNode.right
+ curNode.right = tmpNode
+ }
+ }
+ root
+ }
+}
+```
+
-----------------------
diff --git a/problems/0349.两个数组的交集.md b/problems/0349.两个数组的交集.md
index f7dab3d7..4fbdd414 100644
--- a/problems/0349.两个数组的交集.md
+++ b/problems/0349.两个数组的交集.md
@@ -356,6 +356,8 @@ object Solution {
}
}
+```
+
C#:
```csharp
diff --git a/problems/0383.赎金信.md b/problems/0383.赎金信.md
index 75dafb72..9c3dda8c 100644
--- a/problems/0383.赎金信.md
+++ b/problems/0383.赎金信.md
@@ -425,6 +425,7 @@ object Solution {
true
}
}
+```
C#:
diff --git a/problems/0392.判断子序列.md b/problems/0392.判断子序列.md
index 671576f7..3f7eb11d 100644
--- a/problems/0392.判断子序列.md
+++ b/problems/0392.判断子序列.md
@@ -201,7 +201,32 @@ const isSubsequence = (s, t) => {
};
```
+TypeScript:
+
+```typescript
+function isSubsequence(s: string, t: string): boolean {
+ /**
+ dp[i][j]: s的前i-1个,t的前j-1个,最长公共子序列的长度
+ */
+ const sLen: number = s.length,
+ tLen: number = t.length;
+ const dp: number[][] = new Array(sLen + 1).fill(0)
+ .map(_ => new Array(tLen + 1).fill(0));
+ for (let i = 1; i <= sLen; i++) {
+ for (let j = 1; j <= tLen; j++) {
+ if (s[i - 1] === t[j - 1]) {
+ dp[i][j] = dp[i - 1][j - 1] + 1;
+ } else {
+ dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
+ }
+ }
+ }
+ return dp[sLen][tLen] === s.length;
+};
+```
+
Go:
+
```go
func isSubsequence(s string, t string) bool {
dp := make([][]int,len(s)+1)
diff --git a/problems/0454.四数相加II.md b/problems/0454.四数相加II.md
index bfdee26e..726fdb15 100644
--- a/problems/0454.四数相加II.md
+++ b/problems/0454.四数相加II.md
@@ -354,6 +354,7 @@ object Solution {
res
}
}
+```
C#:
```csharp
diff --git a/problems/0583.两个字符串的删除操作.md b/problems/0583.两个字符串的删除操作.md
index 53c1a125..00f11700 100644
--- a/problems/0583.两个字符串的删除操作.md
+++ b/problems/0583.两个字符串的删除操作.md
@@ -229,6 +229,67 @@ const minDistance = (word1, word2) => {
};
```
+TypeScript:
+
+> dp版本一:
+
+```typescript
+function minDistance(word1: string, word2: string): number {
+ /**
+ dp[i][j]: word1前i个字符,word2前j个字符,所需最小步数
+ dp[0][0]=0: word1前0个字符为'', word2前0个字符为''
+ */
+ const length1: number = word1.length,
+ length2: number = word2.length;
+ const dp: number[][] = new Array(length1 + 1).fill(0)
+ .map(_ => new Array(length2 + 1).fill(0));
+ for (let i = 0; i <= length1; i++) {
+ dp[i][0] = i;
+ }
+ for (let i = 0; i <= length2; i++) {
+ dp[0][i] = i;
+ }
+ for (let i = 1; i <= length1; i++) {
+ for (let j = 1; j <= length2; j++) {
+ if (word1[i - 1] === word2[j - 1]) {
+ dp[i][j] = dp[i - 1][j - 1];
+ } else {
+ dp[i][j] = Math.min(dp[i - 1][j], dp[i][j - 1]) + 1;
+ }
+ }
+ }
+ return dp[length1][length2];
+};
+```
+
+> dp版本二:
+
+```typescript
+function minDistance(word1: string, word2: string): number {
+ /**
+ dp[i][j]: word1前i个字符,word2前j个字符,最长公共子序列的长度
+ dp[0][0]=0: word1前0个字符为'', word2前0个字符为''
+ */
+ const length1: number = word1.length,
+ length2: number = word2.length;
+ const dp: number[][] = new Array(length1 + 1).fill(0)
+ .map(_ => new Array(length2 + 1).fill(0));
+ for (let i = 1; i <= length1; i++) {
+ for (let j = 1; j <= length2; j++) {
+ if (word1[i - 1] === word2[j - 1]) {
+ dp[i][j] = dp[i - 1][j - 1] + 1;
+ } else {
+ dp[i][j] = Math.max(dp[i][j - 1], dp[i - 1][j]);
+ }
+ }
+ }
+ const maxLen: number = dp[length1][length2];
+ return length1 + length2 - maxLen * 2;
+};
+```
+
+
+
-----------------------
diff --git a/problems/0763.划分字母区间.md b/problems/0763.划分字母区间.md
index 2210cffa..2f4d1b48 100644
--- a/problems/0763.划分字母区间.md
+++ b/problems/0763.划分字母区间.md
@@ -158,6 +158,71 @@ class Solution {
return list;
}
}
+
+class Solution{
+ /*解法二: 上述c++补充思路的Java代码实现*/
+
+ public int[][] findPartitions(String s) {
+ List temp = new ArrayList<>();
+ int[][] hash = new int[26][2];//26个字母2列 表示该字母对应的区间
+
+ for (int i = 0; i < s.length(); i++) {
+ //更新字符c对应的位置i
+ char c = s.charAt(i);
+ if (hash[c - 'a'][0] == 0) hash[c - 'a'][0] = i;
+
+ hash[c - 'a'][1] = i;
+
+ //第一个元素区别对待一下
+ hash[s.charAt(0) - 'a'][0] = 0;
+ }
+
+
+ List> h = new LinkedList<>();
+ //组装区间
+ for (int i = 0; i < 26; i++) {
+ //if (hash[i][0] != hash[i][1]) {
+ temp.clear();
+ temp.add(hash[i][0]);
+ temp.add(hash[i][1]);
+ //System.out.println(temp);
+ h.add(new ArrayList<>(temp));
+ // }
+ }
+ // System.out.println(h);
+ // System.out.println(h.size());
+ int[][] res = new int[h.size()][2];
+ for (int i = 0; i < h.size(); i++) {
+ List list = h.get(i);
+ res[i][0] = list.get(0);
+ res[i][1] = list.get(1);
+ }
+
+ return res;
+
+ }
+
+ public List partitionLabels(String s) {
+ int[][] partitions = findPartitions(s);
+ List res = new ArrayList<>();
+ Arrays.sort(partitions, (o1, o2) -> Integer.compare(o1[0], o2[0]));
+ int right = partitions[0][1];
+ int left = 0;
+ for (int i = 0; i < partitions.length; i++) {
+ if (partitions[i][0] > right) {
+ //左边界大于右边界即可纪委一次分割
+ res.add(right - left + 1);
+ left = partitions[i][0];
+ }
+ right = Math.max(right, partitions[i][1]);
+
+ }
+ //最右端
+ res.add(right - left + 1);
+ return res;
+
+ }
+}
```
### Python
diff --git a/problems/1035.不相交的线.md b/problems/1035.不相交的线.md
index 279ed816..4463c5f7 100644
--- a/problems/1035.不相交的线.md
+++ b/problems/1035.不相交的线.md
@@ -183,6 +183,30 @@ const maxUncrossedLines = (nums1, nums2) => {
};
```
+TypeScript:
+
+```typescript
+function maxUncrossedLines(nums1: number[], nums2: number[]): number {
+ /**
+ dp[i][j]: nums1前i-1个,nums2前j-1个,最大连线数
+ */
+ const length1: number = nums1.length,
+ length2: number = nums2.length;
+ const dp: number[][] = new Array(length1 + 1).fill(0)
+ .map(_ => new Array(length2 + 1).fill(0));
+ for (let i = 1; i <= length1; i++) {
+ for (let j = 1; j <= length2; j++) {
+ if (nums1[i - 1] === nums2[j - 1]) {
+ dp[i][j] = dp[i - 1][j - 1] + 1;
+ } else {
+ dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
+ }
+ }
+ }
+ return dp[length1][length2];
+};
+```
+
diff --git a/problems/qita/server.md b/problems/qita/server.md
index 16995d70..1d7a1d6b 100644
--- a/problems/qita/server.md
+++ b/problems/qita/server.md
@@ -1,6 +1,9 @@
# 一台服务器有什么用!
+* [阿里云活动期间服务器购买](https://www.aliyun.com/minisite/goods?taskCode=shareNew2205&recordId=3641992&userCode=roof0wob)
+* [腾讯云活动期间服务器购买](https://curl.qcloud.com/EiaMXllu)
+
但在组织这场活动的时候,了解到大家都有一个共同的问题: **这个服务器究竟有啥用??**
这真是一个好问题,而且我一句两句还说不清楚,所以就专门发文来讲一讲。