diff --git a/problems/0001.两数之和.md b/problems/0001.两数之和.md index a0acdcbe..b3abb991 100644 --- a/problems/0001.两数之和.md +++ b/problems/0001.两数之和.md @@ -109,6 +109,9 @@ public: }; ``` +* 时间复杂度: O(n) +* 空间复杂度: O(n) + ## 总结 本题其实有四个重点: diff --git a/problems/0015.三数之和.md b/problems/0015.三数之和.md index 6675e408..26c9eaa2 100644 --- a/problems/0015.三数之和.md +++ b/problems/0015.三数之和.md @@ -83,6 +83,10 @@ public: }; ``` +* 时间复杂度: O(n^2) +* 空间复杂度: O(n),额外的 set 开销 + + ## 双指针 **其实这道题目使用哈希法并不十分合适**,因为在去重的操作中有很多细节需要注意,在面试中很难直接写出没有bug的代码。 @@ -158,6 +162,10 @@ public: }; ``` +* 时间复杂度: O(n^2) +* 空间复杂度: O(1) + + ## 去重逻辑的思考 ### a的去重 diff --git a/problems/0018.四数之和.md b/problems/0018.四数之和.md index 8e87fcbd..5f4c2ec9 100644 --- a/problems/0018.四数之和.md +++ b/problems/0018.四数之和.md @@ -121,6 +121,10 @@ public: ``` +* 时间复杂度: O(n^3) +* 空间复杂度: O(1) + + ## 补充 二级剪枝的部分: diff --git a/problems/0055.跳跃游戏.md b/problems/0055.跳跃游戏.md index a898263d..6f6dec26 100644 --- a/problems/0055.跳跃游戏.md +++ b/problems/0055.跳跃游戏.md @@ -178,16 +178,16 @@ var canJump = function(nums) { ```Rust impl Solution { - fn max(a: usize, b: usize) -> usize { - if a > b { a } else { b } - } pub fn can_jump(nums: Vec) -> bool { - let mut cover = 0; - if (nums.len() == 1) { return true; } - let mut i = 0; + if nums.len() == 1 { + return true; + } + let (mut i, mut cover) = (0, 0); while i <= cover { - cover = Self::max(i + nums[i] as usize, cover); - if cover >= nums.len() - 1 { return true; } + cover = (i + nums[i] as usize).max(cover); + if cover >= nums.len() - 1 { + return true; + } i += 1; } false diff --git a/problems/0070.爬楼梯完全背包版本.md b/problems/0070.爬楼梯完全背包版本.md index 3093c833..41c2e616 100644 --- a/problems/0070.爬楼梯完全背包版本.md +++ b/problems/0070.爬楼梯完全背包版本.md @@ -128,12 +128,12 @@ Java: class Solution { public int climbStairs(int n) { int[] dp = new int[n + 1]; - int[] weight = {1,2}; + int m = 2; dp[0] = 1; - for (int i = 0; i <= n; i++) { - for (int j = 0; j < weight.length; j++) { - if (i >= weight[j]) dp[i] += dp[i - weight[j]]; + for (int i = 1; i <= n; i++) { // 遍历背包 + for (int j = 1; j <= m; j++) { //遍历物品 + if (i >= j) dp[i] += dp[i - j]; } } @@ -227,3 +227,4 @@ function climbStairs(n: number): number { + diff --git a/problems/0122.买卖股票的最佳时机II.md b/problems/0122.买卖股票的最佳时机II.md index 29242be3..2170dca3 100644 --- a/problems/0122.买卖股票的最佳时机II.md +++ b/problems/0122.买卖股票的最佳时机II.md @@ -275,6 +275,7 @@ const maxProfit = (prices) => { ### TypeScript: +贪心 ```typescript function maxProfit(prices: number[]): number { let resProfit: number = 0; @@ -285,6 +286,21 @@ function maxProfit(prices: number[]): number { }; ``` +动态规划 +```typescript +function maxProfit(prices: number[]): number { + const dp = Array(prices.length) + .fill(0) + .map(() => Array(2).fill(0)) + dp[0][0] = -prices[0] + for (let i = 1; i < prices.length; i++) { + dp[i][0] = Math.max(dp[i - 1][0], dp[i - 1][1] - prices[i]) + dp[i][1] = Math.max(dp[i - 1][1], dp[i - 1][0] + prices[i]) + } + return dp[prices.length - 1][1] +} +``` + ### Rust 贪心: diff --git a/problems/0151.翻转字符串里的单词.md b/problems/0151.翻转字符串里的单词.md index dc12ae23..eb78cc9d 100644 --- a/problems/0151.翻转字符串里的单词.md +++ b/problems/0151.翻转字符串里的单词.md @@ -516,6 +516,48 @@ class Solution: return s[:ps] + s[ps:][::-1] # Must do the last step, because the last word is omit though the pointers are on the correct positions, ``` +```python +class Solution: # 使用双指针法移除空格 + def reverseWords(self, s: str) -> str: + + def removeextraspace(s): + start = 0; end = len(s)-1 + while s[start]==' ': + start+=1 + while s[end]==' ': + end-=1 + news = list(s[start:end+1]) + slow = fast = 0 + while fast0 and news[fast]==news[fast-1]==' ': + fast+=1 + news[slow]=news[fast] + slow+=1; fast+=1 + #return "".join(news[:slow]) + return news[:slow] + + def reversestr(s): + left,right = 0,len(s)-1 + news = list(s) + while left true 那么第一个思路其实就是暴力枚举了,两层for循环,不断去寻找,代码如下: ```CPP -// 时间复杂度: O(n^2) -// 空间复杂度:O(1) class Solution { public: bool canConstruct(string ransomNote, string magazine) { @@ -62,6 +60,9 @@ public: }; ``` +* 时间复杂度: O(n^2) +* 空间复杂度: O(1) + 这里时间复杂度是比较高的,而且里面还有一个字符串删除也就是erase的操作,也是费时的,当然这段代码也可以过这道题。 @@ -78,8 +79,6 @@ public: 代码如下: ```CPP -// 时间复杂度: O(n) -// 空间复杂度:O(1) class Solution { public: bool canConstruct(string ransomNote, string magazine) { @@ -105,6 +104,10 @@ public: }; ``` +* 时间复杂度: O(n) +* 空间复杂度: O(1) + + ## 其他语言版本 diff --git a/problems/0454.四数相加II.md b/problems/0454.四数相加II.md index 07c3f711..c2a5710f 100644 --- a/problems/0454.四数相加II.md +++ b/problems/0454.四数相加II.md @@ -83,6 +83,9 @@ public: ``` +* 时间复杂度: O(n^2) +* 空间复杂度: O(n^2),最坏情况下A和B的值各不相同,相加产生的数字个数为 n^2 + diff --git a/problems/0707.设计链表.md b/problems/0707.设计链表.md index f6f16e30..5c78a12a 100644 --- a/problems/0707.设计链表.md +++ b/problems/0707.设计链表.md @@ -133,6 +133,11 @@ public: LinkedNode* tmp = cur->next; cur->next = cur->next->next; delete tmp; + //delete命令指示释放了tmp指针原本所指的那部分内存, + //被delete后的指针tmp的值(地址)并非就是NULL,而是随机值。也就是被delete后, + //如果不再加上一句tmp=nullptr,tmp会成为乱指的野指针 + //如果之后的程序不小心使用了tmp,会指向难以预想的内存空间 + tmp=nullptr; _size--; } @@ -1450,3 +1455,4 @@ impl MyLinkedList { + diff --git a/problems/0746.使用最小花费爬楼梯.md b/problems/0746.使用最小花费爬楼梯.md index 44b6406c..d6b3a177 100644 --- a/problems/0746.使用最小花费爬楼梯.md +++ b/problems/0746.使用最小花费爬楼梯.md @@ -284,6 +284,33 @@ func min(a, b int) int { return b } ``` +``` GO +第二种思路: dp[i]表示从i层起跳所需要支付的最小费用 +递推公式: +i, k: i32) -> i32 { - let mut nums = nums; - let mut k = k; - let len = nums.len(); - nums.sort_by(|a, b| b.abs().cmp(&a.abs())); - for i in 0..len { - if nums[i] < 0 && k > 0 { - nums[i] *= -1; + pub fn largest_sum_after_k_negations(mut nums: Vec, mut k: i32) -> i32 { + nums.sort_by_key(|b| std::cmp::Reverse(b.abs())); + for v in nums.iter_mut() { + if *v < 0 && k > 0 { + *v *= -1; k -= 1; } } - if k % 2 == 1 { nums[len - 1] *= -1; } - let mut result = 0; - for num in nums { - result += num; + if k % 2 == 1 { + *nums.last_mut().unwrap() *= -1; } - result + nums.iter().sum() } } ```