diff --git a/problems/0028.实现strStr.md b/problems/0028.实现strStr.md index 634d8535..d67e5f70 100644 --- a/problems/0028.实现strStr.md +++ b/problems/0028.实现strStr.md @@ -1059,5 +1059,112 @@ func getNext(_ next: inout [Int], needle: [Character]) { ``` +> 前缀表右移 + +```swift +func strStr(_ haystack: String, _ needle: String) -> Int { + + let s = Array(haystack), p = Array(needle) + guard p.count != 0 else { return 0 } + + var j = 0 + var next = [Int].init(repeating: 0, count: p.count) + getNext(&next, p) + + for i in 0 ..< s.count { + + while j > 0 && s[i] != p[j] { + j = next[j] + } + + if s[i] == p[j] { + j += 1 + } + + if j == p.count { + return i - p.count + 1 + } + } + + return -1 + } + + // 前缀表后移一位,首位用 -1 填充 + func getNext(_ next: inout [Int], _ needle: [Character]) { + + guard needle.count > 1 else { return } + + var j = 0 + next[0] = j + + for i in 1 ..< needle.count-1 { + + while j > 0 && needle[i] != needle[j] { + j = next[j-1] + } + + if needle[i] == needle[j] { + j += 1 + } + + next[i] = j + } + next.removeLast() + next.insert(-1, at: 0) + } +``` + +> 前缀表统一不减一 +```swift + +func strStr(_ haystack: String, _ needle: String) -> Int { + + let s = Array(haystack), p = Array(needle) + guard p.count != 0 else { return 0 } + + var j = 0 + var next = [Int](repeating: 0, count: needle.count) + // KMP + getNext(&next, needle: p) + + for i in 0 ..< s.count { + while j > 0 && s[i] != p[j] { + j = next[j-1] + } + + if s[i] == p[j] { + j += 1 + } + + if j == p.count { + return i - p.count + 1 + } + } + return -1 + } + + //前缀表 + func getNext(_ next: inout [Int], needle: [Character]) { + + var j = 0 + next[0] = j + + for i in 1 ..< needle.count { + + while j>0 && needle[i] != needle[j] { + j = next[j-1] + } + + if needle[i] == needle[j] { + j += 1 + } + + next[i] = j + + } + } + +``` + -----------------------
diff --git a/problems/0053.最大子序和.md b/problems/0053.最大子序和.md index b5fb7642..d0680a3b 100644 --- a/problems/0053.最大子序和.md +++ b/problems/0053.最大子序和.md @@ -230,6 +230,60 @@ var maxSubArray = function(nums) { }; ``` + +### C: +贪心: +```c +int maxSubArray(int* nums, int numsSize){ + int maxVal = INT_MIN; + int subArrSum = 0; + + int i; + for(i = 0; i < numsSize; ++i) { + subArrSum += nums[i]; + // 若当前局部和大于之前的最大结果,对结果进行更新 + maxVal = subArrSum > maxVal ? subArrSum : maxVal; + // 若当前局部和为负,对结果无益。则从nums[i+1]开始应重新计算。 + subArrSum = subArrSum < 0 ? 0 : subArrSum; + } + + return maxVal; +} +``` + +动态规划: +```c +/** + * 解题思路:动态规划: + * 1. dp数组:dp[i]表示从0到i的子序列中最大序列和的值 + * 2. 递推公式:dp[i] = max(dp[i-1] + nums[i], nums[i]) + 若dp[i-1]<0,对最后结果无益。dp[i]则为nums[i]。 + * 3. dp数组初始化:dp[0]的最大子数组和为nums[0] + * 4. 推导顺序:从前往后遍历 + */ + +#define max(a, b) (((a) > (b)) ? (a) : (b)) + +int maxSubArray(int* nums, int numsSize){ + int dp[numsSize]; + // dp[0]最大子数组和为nums[0] + dp[0] = nums[0]; + // 若numsSize为1,应直接返回nums[0] + int subArrSum = nums[0]; + + int i; + for(i = 1; i < numsSize; ++i) { + dp[i] = max(dp[i - 1] + nums[i], nums[i]); + + // 若dp[i]大于之前记录的最大值,进行更新 + if(dp[i] > subArrSum) + subArrSum = dp[i]; + } + + return subArrSum; +} +``` + ### TypeScript **贪心** @@ -267,5 +321,6 @@ function maxSubArray(nums: number[]): number { + -----------------------
diff --git a/problems/0055.跳跃游戏.md b/problems/0055.跳跃游戏.md index 94614242..17a3b4f4 100644 --- a/problems/0055.跳跃游戏.md +++ b/problems/0055.跳跃游戏.md @@ -154,6 +154,30 @@ var canJump = function(nums) { }; ``` + +### C +```c +#define max(a, b) (((a) > (b)) ? (a) : (b)) + +bool canJump(int* nums, int numsSize){ + int cover = 0; + + int i; + // 只可能获取cover范围中的步数,所以i<=cover + for(i = 0; i <= cover; ++i) { + // 更新cover为从i出发能到达的最大值/cover的值中较大值 + cover = max(i + nums[i], cover); + + // 若更新后cover可以到达最后的元素,返回true + if(cover >= numsSize - 1) + return true; + } + + return false; +} +``` + + ### TypeScript ```typescript diff --git a/problems/0093.复原IP地址.md b/problems/0093.复原IP地址.md index 7910fc50..6401824b 100644 --- a/problems/0093.复原IP地址.md +++ b/problems/0093.复原IP地址.md @@ -227,7 +227,7 @@ private: public: vector restoreIpAddresses(string s) { result.clear(); - if (s.size() > 12) return result; // 算是剪枝了 + if (s.size() < 4 || s.size() > 12) return result; // 算是剪枝了 backtracking(s, 0, 0); return result; } diff --git a/problems/0106.从中序与后序遍历序列构造二叉树.md b/problems/0106.从中序与后序遍历序列构造二叉树.md index 7ecca773..188ad3cb 100644 --- a/problems/0106.从中序与后序遍历序列构造二叉树.md +++ b/problems/0106.从中序与后序遍历序列构造二叉树.md @@ -103,7 +103,7 @@ TreeNode* traversal (vector& inorder, vector& postorder) { 中序数组相对比较好切,找到切割点(后序数组的最后一个元素)在中序数组的位置,然后切割,如下代码中我坚持左闭右开的原则: -```C++ +```CPP // 找到中序遍历的切割点 int delimiterIndex; for (delimiterIndex = 0; delimiterIndex < inorder.size(); delimiterIndex++) { @@ -130,7 +130,7 @@ vector rightInorder(inorder.begin() + delimiterIndex + 1, inorder.end() ); 代码如下: -``` +```CPP // postorder 舍弃末尾元素,因为这个元素就是中间节点,已经用过了 postorder.resize(postorder.size() - 1); @@ -144,7 +144,7 @@ vector rightPostorder(postorder.begin() + leftInorder.size(), postorder.end 接下来可以递归了,代码如下: -``` +```CPP root->left = traversal(leftInorder, leftPostorder); root->right = traversal(rightInorder, rightPostorder); ``` diff --git a/problems/0122.买卖股票的最佳时机II.md b/problems/0122.买卖股票的最佳时机II.md index 78aa5952..1e7b77d8 100644 --- a/problems/0122.买卖股票的最佳时机II.md +++ b/problems/0122.买卖股票的最佳时机II.md @@ -281,7 +281,7 @@ function maxProfit(prices: number[]): number { ``` C: - +贪心: ```c int maxProfit(int* prices, int pricesSize){ int result = 0; @@ -296,5 +296,27 @@ int maxProfit(int* prices, int pricesSize){ } ``` +动态规划: +```c +#define max(a, b) (((a) > (b)) ? (a) : (b)) + +int maxProfit(int* prices, int pricesSize){ + int dp[pricesSize][2]; + dp[0][0] = 0 - prices[0]; + dp[0][1] = 0; + + int i; + for(i = 1; i < pricesSize; ++i) { + // dp[i][0]为i-1天持股的钱数/在第i天用i-1天的钱买入的最大值。 + // 若i-1天持股,且第i天买入股票比i-1天持股时更亏,说明应在i-1天时持股 + dp[i][0] = max(dp[i-1][0], dp[i-1][1] - prices[i]); + //dp[i][1]为i-1天不持股钱数/在第i天卖出所持股票dp[i-1][0] + prices[i]的最大值 + dp[i][1] = max(dp[i-1][1], dp[i-1][0] + prices[i]); + } + // 返回在最后一天不持股时的钱数(将股票卖出后钱最大化) + return dp[pricesSize - 1][1]; +} +``` + -----------------------
diff --git a/problems/0135.分发糖果.md b/problems/0135.分发糖果.md index b8bdae0e..72f3dd56 100644 --- a/problems/0135.分发糖果.md +++ b/problems/0135.分发糖果.md @@ -238,6 +238,49 @@ var candy = function(ratings) { }; ``` + +### C +```c +#define max(a, b) (((a) > (b)) ? (a) : (b)) + +int *initCandyArr(int size) { + int *candyArr = (int*)malloc(sizeof(int) * size); + + int i; + for(i = 0; i < size; ++i) + candyArr[i] = 1; + + return candyArr; +} + +int candy(int* ratings, int ratingsSize){ + // 初始化数组,每个小孩开始至少有一颗糖 + int *candyArr = initCandyArr(ratingsSize); + + int i; + // 先判断右边是否比左边评分高。若是,右边孩子的糖果为左边孩子+1(candyArr[i] = candyArr[i - 1] + 1) + for(i = 1; i < ratingsSize; ++i) { + if(ratings[i] > ratings[i - 1]) + candyArr[i] = candyArr[i - 1] + 1; + } + + // 再判断左边评分是否比右边高。 + // 若是,左边孩子糖果为右边孩子糖果+1/自己所持糖果最大值。(若糖果已经比右孩子+1多,则不需要更多糖果) + // 举例:ratings为[1, 2, 3, 1]。此时评分为3的孩子在判断右边比左边大后为3,虽然它比最末尾的1(ratings[3])大,但是candyArr[3]为1。所以不必更新candyArr[2] + for(i = ratingsSize - 2; i >= 0; --i) { + if(ratings[i] > ratings[i + 1]) + candyArr[i] = max(candyArr[i], candyArr[i + 1] + 1); + } + + // 求出糖果之和 + int result = 0; + for(i = 0; i < ratingsSize; ++i) { + result += candyArr[i]; + } + return result; +} +``` + ### TypeScript ```typescript @@ -264,6 +307,5 @@ function candy(ratings: number[]): number { - -----------------------
diff --git a/problems/0143.重排链表.md b/problems/0143.重排链表.md index 00622623..790bcb48 100644 --- a/problems/0143.重排链表.md +++ b/problems/0143.重排链表.md @@ -336,7 +336,33 @@ class Solution: return pre ``` ### Go - +```go +# 方法三 分割链表 +func reorderList(head *ListNode) { + var slow=head + var fast=head + for fast!=nil&&fast.Next!=nil{ + slow=slow.Next + fast=fast.Next.Next + } //双指针将链表分为左右两部分 + var right =new(ListNode) + for slow!=nil{ + temp:=slow.Next + slow.Next=right.Next + right.Next=slow + slow=temp + } //翻转链表右半部分 + right=right.Next //right为反转后得右半部分 + h:=head + for right.Next!=nil{ + temp:=right.Next + right.Next=h.Next + h.Next=right + h=h.Next.Next + right=temp + } //将左右两部分重新组合 +} +``` ### JavaScript ```javascript diff --git a/problems/0209.长度最小的子数组.md b/problems/0209.长度最小的子数组.md index 23b27edd..d31cba3f 100644 --- a/problems/0209.长度最小的子数组.md +++ b/problems/0209.长度最小的子数组.md @@ -198,7 +198,7 @@ JavaScript: var minSubArrayLen = function(target, nums) { // 长度计算一次 const len = nums.length; - let l = r = sum = 0, + let l = r = sum = 0, res = len + 1; // 子数组最大不会超过自身 while(r < len) { sum += nums[r++]; @@ -260,12 +260,12 @@ Rust: ```rust impl Solution { - pub fn min_sub_array_len(target: i32, nums: Vec) -> i32 { + pub fn min_sub_array_len(target: i32, nums: Vec) -> i32 { let (mut result, mut subLength): (i32, i32) = (i32::MAX, 0); let (mut sum, mut i) = (0, 0); - + for (pos, val) in nums.iter().enumerate() { - sum += val; + sum += val; while sum >= target { subLength = (pos - i + 1) as i32; if result > subLength { @@ -364,7 +364,7 @@ int minSubArrayLen(int target, int* nums, int numsSize){ int minLength = INT_MAX; int sum = 0; - int left = 0, right = 0; + int left = 0, right = 0; //右边界向右扩展 for(; right < numsSize; ++right) { sum += nums[right]; @@ -380,5 +380,26 @@ int minSubArrayLen(int target, int* nums, int numsSize){ } ``` +Kotlin: +```kotlin +class Solution { + fun minSubArrayLen(target: Int, nums: IntArray): Int { + var start = 0 + var end = 0 + var ret = Int.MAX_VALUE + var count = 0 + while (end < nums.size) { + count += nums[end] + while (count >= target) { + ret = if (ret > (end - start + 1)) end - start + 1 else ret + count -= nums[start++] + } + end++ + } + return if (ret == Int.MAX_VALUE) 0 else ret + } +} +``` + -----------------------
diff --git a/problems/0332.重新安排行程.md b/problems/0332.重新安排行程.md index f7ef8cf7..c71b2a93 100644 --- a/problems/0332.重新安排行程.md +++ b/problems/0332.重新安排行程.md @@ -342,7 +342,7 @@ class Solution: return path ``` -### Go +### GO ```go type pair struct { target string diff --git a/problems/0376.摆动序列.md b/problems/0376.摆动序列.md index acd8996e..6822896e 100644 --- a/problems/0376.摆动序列.md +++ b/problems/0376.摆动序列.md @@ -298,6 +298,35 @@ var wiggleMaxLength = function(nums) { }; ``` + +### C +**贪心** +```c +int wiggleMaxLength(int* nums, int numsSize){ + if(numsSize <= 1) + return numsSize; + + int length = 1; + int preDiff , curDiff; + preDiff = curDiff = 0; + for(int i = 0; i < numsSize - 1; ++i) { + // 计算当前i元素与i+1元素差值 + curDiff = nums[i+1] - nums[i]; + + // 若preDiff与curDiff符号不符,则子序列长度+1。更新preDiff的符号 + // 若preDiff与curDiff符号一致,当前i元素为连续升序/连续降序子序列的中间元素。不被记录入长度 + // 注:当preDiff为0时,curDiff为正或为负都属于符号不同 + if((curDiff > 0 && preDiff <= 0) || (preDiff >= 0 && curDiff < 0)) { + preDiff = curDiff; + length++; + } + } + + return length; +} +``` + + ### TypeScript **贪心** diff --git a/problems/0383.赎金信.md b/problems/0383.赎金信.md index 00707347..5d9e8295 100644 --- a/problems/0383.赎金信.md +++ b/problems/0383.赎金信.md @@ -84,6 +84,10 @@ class Solution { public: bool canConstruct(string ransomNote, string magazine) { int record[26] = {0}; + //add + if (ransomNote.size() > magazine.size()) { + return false; + } for (int i = 0; i < magazine.length(); i++) { // 通过recode数据记录 magazine里各个字符出现次数 record[magazine[i]-'a'] ++; diff --git a/problems/0452.用最少数量的箭引爆气球.md b/problems/0452.用最少数量的箭引爆气球.md index 33bbad55..2ab14b61 100644 --- a/problems/0452.用最少数量的箭引爆气球.md +++ b/problems/0452.用最少数量的箭引爆气球.md @@ -193,7 +193,7 @@ func min(a,b int) int{ } return a } -``` +``` ### Javascript ```Javascript @@ -214,7 +214,31 @@ var findMinArrowShots = function(points) { }; ``` +### TypeScript + +```typescript +function findMinArrowShots(points: number[][]): number { + const length: number = points.length; + if (length === 0) return 0; + points.sort((a, b) => a[0] - b[0]); + let resCount: number = 1; + let right: number = points[0][1]; // 右边界 + let tempPoint: number[]; + for (let i = 1; i < length; i++) { + tempPoint = points[i]; + if (tempPoint[0] > right) { + resCount++; + right = tempPoint[1]; + } else { + right = Math.min(right, tempPoint[1]); + } + } + return resCount; +}; +``` + ### C + ```c int cmp(const void *a,const void *b) { diff --git a/problems/0459.重复的子字符串.md b/problems/0459.重复的子字符串.md index ccfb485c..a51c68ee 100644 --- a/problems/0459.重复的子字符串.md +++ b/problems/0459.重复的子字符串.md @@ -421,5 +421,89 @@ function repeatedSubstringPattern(s: string): boolean { }; ``` + +Swift: + +> 前缀表统一减一 +```swift + func repeatedSubstringPattern(_ s: String) -> Bool { + + let sArr = Array(s) + let len = s.count + if len == 0 { + return false + } + var next = Array.init(repeating: -1, count: len) + + getNext(&next,sArr) + + if next.last != -1 && len % (len - (next[len-1] + 1)) == 0{ + return true + } + + return false + } + + func getNext(_ next: inout [Int], _ str:[Character]) { + + var j = -1 + next[0] = j + + for i in 1 ..< str.count { + + while j >= 0 && str[j+1] != str[i] { + j = next[j] + } + + if str[i] == str[j+1] { + j += 1 + } + + next[i] = j + } + } +``` + +> 前缀表统一不减一 +```swift + func repeatedSubstringPattern(_ s: String) -> Bool { + + let sArr = Array(s) + let len = sArr.count + if len == 0 { + return false + } + + var next = Array.init(repeating: 0, count: len) + getNext(&next, sArr) + + if next[len-1] != 0 && len % (len - next[len-1]) == 0 { + return true + } + + return false + } + + // 前缀表不减一 + func getNext(_ next: inout [Int], _ sArr:[Character]) { + + var j = 0 + next[0] = 0 + + for i in 1 ..< sArr.count { + + while j > 0 && sArr[i] != sArr[j] { + j = next[j-1] + } + + if sArr[i] == sArr[j] { + j += 1 + } + + next[i] = j + } + } +``` + -----------------------
diff --git a/problems/1005.K次取反后最大化的数组和.md b/problems/1005.K次取反后最大化的数组和.md index 80c47147..79767deb 100644 --- a/problems/1005.K次取反后最大化的数组和.md +++ b/problems/1005.K次取反后最大化的数组和.md @@ -211,6 +211,46 @@ var largestSumAfterKNegations = function(nums, k) { }; ``` + +### C +```c +#define abs(a) (((a) > 0) ? (a) : (-(a))) + +// 对数组求和 +int sum(int *nums, int numsSize) { + int sum = 0; + + int i; + for(i = 0; i < numsSize; ++i) { + sum += nums[i]; + } + return sum; +} + +int cmp(const void* v1, const void* v2) { + return abs(*(int*)v2) - abs(*(int*)v1); +} + +int largestSumAfterKNegations(int* nums, int numsSize, int k){ + qsort(nums, numsSize, sizeof(int), cmp); + + int i; + for(i = 0; i < numsSize; ++i) { + // 遍历数组,若当前元素<0则将当前元素转变,k-- + if(nums[i] < 0 && k > 0) { + nums[i] *= -1; + --k; + } + } + + // 若遍历完数组后k还有剩余(此时所有元素应均为正),则将绝对值最小的元素nums[numsSize - 1]变为负 + if(k % 2 == 1) + nums[numsSize - 1] *= -1; + + return sum(nums, numsSize); +} +``` + ### TypeScript ```typescript @@ -235,5 +275,6 @@ function largestSumAfterKNegations(nums: number[], k: number): number { + -----------------------
diff --git a/problems/二叉树的递归遍历.md b/problems/二叉树的递归遍历.md index 35d19d7b..612f2394 100644 --- a/problems/二叉树的递归遍历.md +++ b/problems/二叉树的递归遍历.md @@ -371,18 +371,18 @@ C: ```c //前序遍历: -void preOrderTraversal(struct TreeNode* root, int* ret, int* returnSize) { +void preOrder(struct TreeNode* root, int* ret, int* returnSize) { if(root == NULL) return; ret[(*returnSize)++] = root->val; - preOrderTraverse(root->left, ret, returnSize); - preOrderTraverse(root->right, ret, returnSize); + preOrder(root->left, ret, returnSize); + preOrder(root->right, ret, returnSize); } int* preorderTraversal(struct TreeNode* root, int* returnSize){ int* ret = (int*)malloc(sizeof(int) * 100); *returnSize = 0; - preOrderTraversal(root, ret, returnSize); + preOrder(root, ret, returnSize); return ret; } diff --git a/problems/背包问题理论基础完全背包.md b/problems/背包问题理论基础完全背包.md index faa1dc46..3ec399f1 100644 --- a/problems/背包问题理论基础完全背包.md +++ b/problems/背包问题理论基础完全背包.md @@ -37,7 +37,7 @@ * [动态规划:关于01背包问题,你该了解这些!(滚动数组)](https://programmercarl.com/背包理论基础01背包-2.html) 首先在回顾一下01背包的核心代码 -``` +```cpp for(int i = 0; i < weight.size(); i++) { // 遍历物品 for(int j = bagWeight; j >= weight[i]; j--) { // 遍历背包容量 dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);