diff --git a/problems/0059.螺旋矩阵II.md b/problems/0059.螺旋矩阵II.md index 228892de..4231fb39 100644 --- a/problems/0059.螺旋矩阵II.md +++ b/problems/0059.螺旋矩阵II.md @@ -191,33 +191,48 @@ class Solution { python: -```python +```python3 class Solution: + def generateMatrix(self, n: int) -> List[List[int]]: - left, right, up, down = 0, n-1, 0, n-1 - matrix = [ [0]*n for _ in range(n)] - num = 1 - while left<=right and up<=down: - # 填充左到右 - for i in range(left, right+1): - matrix[up][i] = num - num += 1 - up += 1 - # 填充上到下 - for i in range(up, down+1): - matrix[i][right] = num - num += 1 - right -= 1 - # 填充右到左 - for i in range(right, left-1, -1): - matrix[down][i] = num - num += 1 - down -= 1 - # 填充下到上 - for i in range(down, up-1, -1): - matrix[i][left] = num - num += 1 + # 初始化要填充的正方形 + matrix = [[0] * n for _ in range(n)] + + left, right, up, down = 0, n - 1, 0, n - 1 + number = 1 # 要填充的数字 + + while left < right and up < down: + + # 从左到右填充上边 + for x in range(left, right): + matrix[up][x] = number + number += 1 + + # 从上到下填充右边 + for y in range(up, down): + matrix[y][right] = number + number += 1 + + # 从右到左填充下边 + for x in range(right, left, -1): + matrix[down][x] = number + number += 1 + + # 从下到上填充左边 + for y in range(down, up, -1): + matrix[y][left] = number + number += 1 + + # 缩小要填充的范围 left += 1 + right -= 1 + up += 1 + down -= 1 + + # 如果阶数为奇数,额外填充一次中心 + if n % 2: + matrix[n // 2][n // 2] = number + return matrix ``` diff --git a/problems/0337.打家劫舍III.md b/problems/0337.打家劫舍III.md index 2a69ac56..dfb8ba57 100644 --- a/problems/0337.打家劫舍III.md +++ b/problems/0337.打家劫舍III.md @@ -29,7 +29,7 @@ 与198.打家劫舍,213.打家劫舍II一样,关键是要讨论当前节点抢还是不抢。 -如果抢了当前节点,两个孩子就不是动,如果没抢当前节点,就可以考虑抢左右孩子(**注意这里说的是“考虑”**) +如果抢了当前节点,两个孩子就不能动,如果没抢当前节点,就可以考虑抢左右孩子(**注意这里说的是“考虑”**) ### 暴力递归 @@ -91,7 +91,7 @@ public: ### 动态规划 -在上面两种方法,其实对一个节点 投与不投得到的最大金钱都没有做记录,而是需要实时计算。 +在上面两种方法,其实对一个节点 偷与不偷得到的最大金钱都没有做记录,而是需要实时计算。 而动态规划其实就是使用状态转移容器来记录状态的变化,这里可以使用一个长度为2的数组,记录当前节点偷与不偷所得到的的最大金钱。 @@ -121,7 +121,7 @@ vector robTree(TreeNode* cur) { 2. 确定终止条件 -在遍历的过程中,如果遇到空间点的话,很明显,无论偷还是不偷都是0,所以就返回 +在遍历的过程中,如果遇到空节点的话,很明显,无论偷还是不偷都是0,所以就返回 ``` if (cur == NULL) return vector{0, 0}; ``` diff --git a/problems/0673.最长递增子序列的个数.md b/problems/0673.最长递增子序列的个数.md index ce3e8639..b3907e0e 100644 --- a/problems/0673.最长递增子序列的个数.md +++ b/problems/0673.最长递增子序列的个数.md @@ -9,6 +9,10 @@ # 673.最长递增子序列的个数 + +[力扣题目链接](https://leetcode-cn.com/problems/number-of-longest-increasing-subsequence/) + + 给定一个未排序的整数数组,找到最长递增子序列的个数。 示例 1: @@ -224,16 +228,110 @@ public: ## Java ```java +class Solution { + public int findNumberOfLIS(int[] nums) { + if (nums.length <= 1) return nums.length; + int[] dp = new int[nums.length]; + for(int i = 0; i < dp.length; i++) dp[i] = 1; + int[] count = new int[nums.length]; + for(int i = 0; i < count.length; i++) count[i] = 1; + + int maxCount = 0; + for (int i = 1; i < nums.length; i++) { + for (int j = 0; j < i; j++) { + if (nums[i] > nums[j]) { + if (dp[j] + 1 > dp[i]) { + dp[i] = dp[j] + 1; + count[i] = count[j]; + } else if (dp[j] + 1 == dp[i]) { + count[i] += count[j]; + } + } + if (dp[i] > maxCount) maxCount = dp[i]; + } + } + int result = 0; + for (int i = 0; i < nums.length; i++) { + if (maxCount == dp[i]) result += count[i]; + } + return result; + } +} ``` ## Python ```python +class Solution: + def findNumberOfLIS(self, nums: List[int]) -> int: + size = len(nums) + if size<= 1: return size + + dp = [1 for i in range(size)] + count = [1 for i in range(size)] + + maxCount = 0 + for i in range(1, size): + for j in range(i): + if nums[i] > nums[j]: + if dp[j] + 1 > dp[i] : + dp[i] = dp[j] + 1 + count[i] = count[j] + elif dp[j] + 1 == dp[i] : + count[i] += count[j] + if dp[i] > maxCount: + maxCount = dp[i]; + result = 0 + for i in range(size): + if maxCount == dp[i]: + result += count[i] + return result; ``` ## Go ```go + +func findNumberOfLIS(nums []int) int { + size := len(nums) + if size <= 1 { + return size + } + + dp := make([]int, size); + for i, _ := range dp { + dp[i] = 1 + } + count := make([]int, size); + for i, _ := range count { + count[i] = 1 + } + + maxCount := 0 + for i := 1; i < size; i++ { + for j := 0; j < i; j++ { + if nums[i] > nums[j] { + if dp[j] + 1 > dp[i] { + dp[i] = dp[j] + 1 + count[i] = count[j] + } else if dp[j] + 1 == dp[i] { + count[i] += count[j] + } + } + if dp[i] > maxCount { + maxCount = dp[i] + } + } + } + + result := 0 + for i := 0; i < size; i++ { + if maxCount == dp[i] { + result += count[i] + } + } + return result +} ``` ## JavaScript diff --git a/problems/1005.K次取反后最大化的数组和.md b/problems/1005.K次取反后最大化的数组和.md index 8bdd0f41..30718b13 100644 --- a/problems/1005.K次取反后最大化的数组和.md +++ b/problems/1005.K次取反后最大化的数组和.md @@ -117,11 +117,8 @@ class Solution { } // 如果K还大于0,那么反复转变数值最小的元素,将K用完 if (k % 2 == 1) nums[len - 1] = -nums[len - 1]; - int result = 0; - for (int a : nums) { - result += a; - } - return result; + + return Arrays.stream(nums).sum(); } } ``` diff --git a/problems/背包问题理论基础完全背包.md b/problems/背包问题理论基础完全背包.md index f4abc535..455a3c33 100644 --- a/problems/背包问题理论基础完全背包.md +++ b/problems/背包问题理论基础完全背包.md @@ -80,7 +80,7 @@ dp状态图如下: * [动态规划:关于01背包问题,你该了解这些!](https://programmercarl.com/背包理论基础01背包-1.html) * [动态规划:关于01背包问题,你该了解这些!(滚动数组)](https://programmercarl.com/背包理论基础01背包-2.html) -就知道了,01背包中二维dp数组的两个for遍历的先后循序是可以颠倒了,一位dp数组的两个for循环先后循序一定是先遍历物品,再遍历背包容量。 +就知道了,01背包中二维dp数组的两个for遍历的先后循序是可以颠倒了,一维dp数组的两个for循环先后循序一定是先遍历物品,再遍历背包容量。 **在完全背包中,对于一维dp数组来说,其实两个for循环嵌套顺序同样无所谓!**