diff --git a/problems/0027.移除元素.md b/problems/0027.移除元素.md index 8d6ca502..590cf0b9 100644 --- a/problems/0027.移除元素.md +++ b/problems/0027.移除元素.md @@ -281,10 +281,8 @@ func removeElement(_ nums: inout [Int], _ val: Int) -> Int { for fastIndex in 0..= nums.length - 1) return true; + cur++; + } + return false; +}; +``` + + + -----------------------
diff --git a/problems/0059.螺旋矩阵II.md b/problems/0059.螺旋矩阵II.md index 5c679982..a7b19a34 100644 --- a/problems/0059.螺旋矩阵II.md +++ b/problems/0059.螺旋矩阵II.md @@ -246,11 +246,11 @@ var generateMatrix = function(n) { res[row][col] = count++; } // 下行从右到左(左闭右开) - for (; col > startX; col--) { + for (; col > startY; col--) { res[row][col] = count++; } // 左列做下到上(左闭右开) - for (; row > startY; row--) { + for (; row > startX; row--) { res[row][col] = count++; } diff --git a/problems/0121.买卖股票的最佳时机.md b/problems/0121.买卖股票的最佳时机.md index e7c0ac65..f0bc3b97 100644 --- a/problems/0121.买卖股票的最佳时机.md +++ b/problems/0121.买卖股票的最佳时机.md @@ -311,7 +311,36 @@ class Solution: ``` Go: +> 贪心法: +```Go +func maxProfit(prices []int) int { + low := math.MaxInt32 + rlt := 0 + for i := range prices{ + low = min(low, prices[i]) + rlt = max(rlt, prices[i]-low) + } + return rlt +} +func min(a, b int) int { + if a < b{ + return a + } + + return b +} + +func max(a, b int) int { + if a > b{ + return a + } + + return b +} +``` + +> 动态规划:版本一 ```Go func maxProfit(prices []int) int { length:=len(prices) @@ -338,6 +367,29 @@ func max(a,b int)int { } ``` +> 动态规划:版本二 +```Go +func maxProfit(prices []int) int { + dp := [2][2]int{} + dp[0][0] = -prices[0] + dp[0][1] = 0 + for i := 1; i < len(prices); i++{ + dp[i%2][0] = max(dp[(i-1)%2][0], -prices[i]) + dp[i%2][1] = max(dp[(i-1)%2][1], dp[(i-1)%2][0]+prices[i]) + } + + return dp[(len(prices)-1)%2][1] +} + +func max(a, b int) int { + if a > b{ + return a + } + + return b +} +``` + JavaScript: > 动态规划 diff --git a/problems/0122.买卖股票的最佳时机II.md b/problems/0122.买卖股票的最佳时机II.md index b31cbae3..78aa5952 100644 --- a/problems/0122.买卖股票的最佳时机II.md +++ b/problems/0122.买卖股票的最佳时机II.md @@ -264,7 +264,19 @@ const maxProfit = (prices) => { dp[i][1] = Math.max(dp[i-1][1], dp[i-1][0] + prices[i]); } - return dp[prices.length -1][0]; + return dp[prices.length -1][1]; +}; +``` + +TypeScript: + +```typescript +function maxProfit(prices: number[]): number { + let resProfit: number = 0; + for (let i = 1, length = prices.length; i < length; i++) { + resProfit += Math.max(prices[i] - prices[i - 1], 0); + } + return resProfit; }; ``` diff --git a/problems/0122.买卖股票的最佳时机II(动态规划).md b/problems/0122.买卖股票的最佳时机II(动态规划).md index 615d79bb..5a165a14 100644 --- a/problems/0122.买卖股票的最佳时机II(动态规划).md +++ b/problems/0122.买卖股票的最佳时机II(动态规划).md @@ -276,7 +276,7 @@ const maxProfit = (prices) => { dp[i][1] = Math.max(dp[i-1][1], dp[i-1][0] + prices[i]); } - return dp[prices.length -1][0]; + return dp[prices.length -1][1]; }; // 方法二:动态规划(滚动数组) diff --git a/problems/0134.加油站.md b/problems/0134.加油站.md index 1777faad..e96773ff 100644 --- a/problems/0134.加油站.md +++ b/problems/0134.加油站.md @@ -235,7 +235,7 @@ class Solution { return index; } } -``` +``` ### Python ```python @@ -364,7 +364,50 @@ var canCompleteCircuit = function(gas, cost) { }; ``` +### TypeScript + +**暴力法:** + +```typescript +function canCompleteCircuit(gas: number[], cost: number[]): number { + for (let i = 0, length = gas.length; i < length; i++) { + let curSum: number = 0; + let index: number = i; + while (curSum >= 0 && index < i + length) { + let tempIndex: number = index % length; + curSum += gas[tempIndex] - cost[tempIndex]; + index++; + } + if (index === i + length && curSum >= 0) return i; + } + return -1; +}; +``` + +**解法二:** + +```typescript +function canCompleteCircuit(gas: number[], cost: number[]): number { + let total: number = 0; + let curGas: number = 0; + let tempDiff: number = 0; + let resIndex: number = 0; + for (let i = 0, length = gas.length; i < length; i++) { + tempDiff = gas[i] - cost[i]; + total += tempDiff; + curGas += tempDiff; + if (curGas < 0) { + resIndex = i + 1; + curGas = 0; + } + } + if (total < 0) return -1; + return resIndex; +}; +``` + ### C + ```c int canCompleteCircuit(int* gas, int gasSize, int* cost, int costSize){ int curSum = 0; diff --git a/problems/0135.分发糖果.md b/problems/0135.分发糖果.md index ccdabc16..b8bdae0e 100644 --- a/problems/0135.分发糖果.md +++ b/problems/0135.分发糖果.md @@ -238,6 +238,32 @@ var candy = function(ratings) { }; ``` +### TypeScript + +```typescript +function candy(ratings: number[]): number { + const candies: number[] = []; + candies[0] = 1; + // 保证右边高分孩子一定比左边低分孩子发更多的糖果 + for (let i = 1, length = ratings.length; i < length; i++) { + if (ratings[i] > ratings[i - 1]) { + candies[i] = candies[i - 1] + 1; + } else { + candies[i] = 1; + } + } + // 保证左边高分孩子一定比右边低分孩子发更多的糖果 + for (let i = ratings.length - 2; i >= 0; i--) { + if (ratings[i] > ratings[i + 1]) { + candies[i] = Math.max(candies[i], candies[i + 1] + 1); + } + } + return candies.reduce((pre, cur) => pre + cur); +}; +``` + + + -----------------------
diff --git a/problems/0416.分割等和子集.md b/problems/0416.分割等和子集.md index b24fb365..6e93ae8e 100644 --- a/problems/0416.分割等和子集.md +++ b/problems/0416.分割等和子集.md @@ -50,7 +50,7 @@ ## 01背包问题 -背包问题,大家都知道,有N件物品和一个最多能被重量为W 的背包。第i件物品的重量是weight[i],得到的价值是value[i] 。每件物品只能用一次,求解将哪些物品装入背包里物品价值总和最大。 +背包问题,大家都知道,有N件物品和一个最多能背重量为W 的背包。第i件物品的重量是weight[i],得到的价值是value[i] 。每件物品只能用一次,求解将哪些物品装入背包里物品价值总和最大。 **背包问题有多种背包方式,常见的有:01背包、完全背包、多重背包、分组背包和混合背包等等。** diff --git a/problems/0707.设计链表.md b/problems/0707.设计链表.md index 86f3a683..37ce15ad 100644 --- a/problems/0707.设计链表.md +++ b/problems/0707.设计链表.md @@ -973,6 +973,10 @@ class MyLinkedList { // 处理头节点 if (index === 0) { this.head = this.head!.next; + // 如果链表中只有一个元素,删除头节点后,需要处理尾节点 + if (index === this.size - 1) { + this.tail = null + } this.size--; return; } diff --git a/problems/0763.划分字母区间.md b/problems/0763.划分字母区间.md index 03d3a73b..d350f255 100644 --- a/problems/0763.划分字母区间.md +++ b/problems/0763.划分字母区间.md @@ -77,6 +77,61 @@ public: 但这道题目的思路是很巧妙的,所以有必要介绍给大家做一做,感受一下。 +## 补充 + +这里提供一种与[452.用最少数量的箭引爆气球](https://programmercarl.com/0452.用最少数量的箭引爆气球.html)、[435.无重叠区间](https://programmercarl.com/0435.无重叠区间.html)相同的思路。 + +统计字符串中所有字符的起始和结束位置,记录这些区间(实际上也就是[435.无重叠区间](https://programmercarl.com/0435.无重叠区间.html)题目里的输入),**将区间按左边界从小到大排序,找到边界将区间划分成组,互不重叠。找到的边界就是答案。** + +```CPP +class Solution { +public: + static bool cmp(vector &a, vector &b) { + return a[0] < b[0]; + } + // 记录每个字母出现的区间 + vector> countLabels(string s) { + vector> hash(26, vector(2, INT_MIN)); + vector> hash_filter; + for (int i = 0; i < s.size(); ++i) { + if (hash[s[i] - 'a'][0] == INT_MIN) { + hash[s[i] - 'a'][0] = i; + } + hash[s[i] - 'a'][1] = i; + } + // 去除字符串中未出现的字母所占用区间 + for (int i = 0; i < hash.size(); ++i) { + if (hash[i][0] != INT_MIN) { + hash_filter.push_back(hash[i]); + } + } + return hash_filter; + } + vector partitionLabels(string s) { + vector res; + // 这一步得到的 hash 即为无重叠区间题意中的输入样例格式:区间列表 + // 只不过现在我们要求的是区间分割点 + vector> hash = countLabels(s); + // 按照左边界从小到大排序 + sort(hash.begin(), hash.end(), cmp); + // 记录最大右边界 + int rightBoard = hash[0][1]; + int leftBoard = 0; + for (int i = 1; i < hash.size(); ++i) { + // 由于字符串一定能分割,因此, + // 一旦下一区间左边界大于当前右边界,即可认为出现分割点 + if (hash[i][0] > rightBoard) { + res.push_back(rightBoard - leftBoard + 1); + leftBoard = hash[i][0]; + } + rightBoard = max(rightBoard, hash[i][1]); + } + // 最右端 + res.push_back(rightBoard - leftBoard + 1); + return res; + } +}; +``` ## 其他语言版本 diff --git a/problems/0860.柠檬水找零.md b/problems/0860.柠檬水找零.md index ffd5490d..5d5d6ad2 100644 --- a/problems/0860.柠檬水找零.md +++ b/problems/0860.柠檬水找零.md @@ -252,5 +252,39 @@ var lemonadeChange = function(bills) { ``` +### TypeScript + +```typescript +function lemonadeChange(bills: number[]): boolean { + let five: number = 0, + ten: number = 0; + for (let bill of bills) { + switch (bill) { + case 5: + five++; + break; + case 10: + if (five < 1) return false; + five--; + ten++ + break; + case 20: + if (ten > 0 && five > 0) { + five--; + ten--; + } else if (five > 2) { + five -= 3; + } else { + return false; + } + break; + } + } + return true; +}; +``` + + + -----------------------
diff --git a/problems/1005.K次取反后最大化的数组和.md b/problems/1005.K次取反后最大化的数组和.md index 45f186e2..80c47147 100644 --- a/problems/1005.K次取反后最大化的数组和.md +++ b/problems/1005.K次取反后最大化的数组和.md @@ -211,5 +211,29 @@ var largestSumAfterKNegations = function(nums, k) { }; ``` +### TypeScript + +```typescript +function largestSumAfterKNegations(nums: number[], k: number): number { + nums.sort((a, b) => Math.abs(b) - Math.abs(a)); + let curIndex: number = 0; + const length = nums.length; + while (curIndex < length && k > 0) { + if (nums[curIndex] < 0) { + nums[curIndex] *= -1; + k--; + } + curIndex++; + } + while (k > 0) { + nums[length - 1] *= -1; + k--; + } + return nums.reduce((pre, cur) => pre + cur, 0); +}; +``` + + + -----------------------
diff --git a/problems/前序/ACM模式如何构建二叉树.md b/problems/前序/ACM模式如何构建二叉树.md index 444f0071..815eb17d 100644 --- a/problems/前序/ACM模式如何构建二叉树.md +++ b/problems/前序/ACM模式如何构建二叉树.md @@ -208,6 +208,59 @@ int main() { ## Java ```Java +public class Solution { + // 节点类 + static class TreeNode { + // 节点值 + int val; + + // 左节点 + TreeNode left; + + // 右节点 + TreeNode right; + + // 节点的构造函数(默认左右节点都为null) + public TreeNode(int x) { + this.val = x; + this.left = null; + this.right = null; + } + } + + /** + * 根据数组构建二叉树 + * @param arr 树的数组表示 + * @return 构建成功后树的根节点 + */ + public TreeNode constructBinaryTree(final int[] arr) { + // 构建和原数组相同的树节点列表 + List treeNodeList = arr.length > 0 ? new ArrayList<>(arr.length) : null; + TreeNode root = null; + // 把输入数值数组,先转化为二叉树节点列表 + for (int i = 0; i < arr.length; i++) { + TreeNode node = null; + if (arr[i] != -1) { // 用 -1 表示null + node = new TreeNode(arr[i]); + } + treeNodeList.add(node); + if (i == 0) { + root = node; + } + } + // 遍历一遍,根据规则左右孩子赋值就可以了 + // 注意这里 结束规则是 i * 2 + 2 < arr.length,避免空指针 + for (int i = 0; i * 2 + 2 < arr.length; i++) { + TreeNode node = treeNodeList.get(i); + if (node != null) { + // 线性存储转连式存储关键逻辑 + node.left = treeNodeList.get(2 * i + 1); + node.right = treeNodeList.get(2 * i + 2); + } + } + return root; + } +} ```