diff --git "a/problems/0200.345円262円233円345円261円277円346円225円260円351円207円217円.346円267円261円346円220円234円347円211円210円.md" "b/problems/0200.345円262円233円345円261円277円346円225円260円351円207円217円.346円267円261円346円220円234円347円211円210円.md"
index 6d42162a57..c30ace1999 100644
--- "a/problems/0200.345円262円233円345円261円277円346円225円260円351円207円217円.346円267円261円346円220円234円347円211円210円.md"
+++ "b/problems/0200.345円262円233円345円261円277円346円225円260円351円207円217円.346円267円261円346円220円234円347円211円210円.md"
@@ -176,6 +176,48 @@ public void dfs(char[][] grid, int i, int j){
dfs(grid,i,j + 1);
dfs(grid,i,j - 1);
}
+```
+```java
+//graph - dfs (和卡哥的代碼邏輯一致)
+class Solution {
+ boolean[][] visited;
+ int dir[][] = {
+ {0, 1}, //right
+ {1, 0}, //down
+ {-1, 0}, //up
+ {0, -1} //left
+ };
+ public int numIslands(char[][] grid) {
+ int count = 0;
+ visited = new boolean[grid.length][grid[0].length];
+
+ for(int i = 0; i < grid.length; i++){ + for(int j = 0; j < grid[0].length; j++){ + if(visited[i][j] == false && grid[i][j] == '1'){ + count++; + dfs(grid, i, j); + } + } + } + return count; + } + + private void dfs(char[][]grid, int x, int y){ + if(visited[x][y] == true || grid[x][y] == '0') + return; + + visited[x][y] = true; + + for(int i = 0; i < 4; i++){ + int nextX = x + dir[i][0]; + int nextY = y + dir[i][1]; + if(nextX < 0 || nextY < 0 || nextX>= grid.length || nextY>= grid[0].length)
+ continue;
+ dfs(grid, nextX, nextY);
+ }
+ }
+}
+```
diff --git "a/problems/0242.346円234円211円346円225円210円347円232円204円345円255円227円346円257円215円345円274円202円344円275円215円350円257円215円.md" "b/problems/0242.346円234円211円346円225円210円347円232円204円345円255円227円346円257円215円345円274円202円344円275円215円350円257円215円.md"
index 101dd6f255..4ea43947e8 100644
--- "a/problems/0242.346円234円211円346円225円210円347円232円204円345円255円227円346円257円215円345円274円202円344円275円215円350円257円215円.md"
+++ "b/problems/0242.346円234円211円346円225円210円347円232円204円345円255円227円346円257円215円345円274円202円344円275円215円350円257円215円.md"
@@ -163,6 +163,7 @@ class Solution(object):
a_count = Counter(s)
b_count = Counter(t)
return a_count == b_count
+```
Go:
diff --git "a/problems/0494.347円233円256円346円240円207円345円222円214円.md" "b/problems/0494.347円233円256円346円240円207円345円222円214円.md"
index 32931e6b1f..1902d5ed44 100644
--- "a/problems/0494.347円233円256円346円240円207円345円222円214円.md"
+++ "b/problems/0494.347円233円256円346円240円207円345円222円214円.md"
@@ -292,6 +292,85 @@ class Solution {
}
```
+易于理解的二维数组版本:
+```java
+class Solution {
+ public int findTargetSumWays(int[] nums, int target) {
+
+ // 01背包应用之"有多少种不同的填满背包最大容量的方法"
+ // 易于理解的二维数组解法及详细注释
+
+ int sum = 0;
+ for(int i = 0; i < nums.length; i++) { + sum += nums[i]; + } + + // 注意nums[i]>= 0的题目条件,意味着sum也是所有nums[i]的绝对值之和
+ // 这里保证了sum + target一定是大于等于零的,也就是left大于等于零(毕竟我们定义left大于right)
+ if(sum < Math.abs(target)){ + return 0; + } + + // 利用二元一次方程组将left用target和sum表示出来(替换掉right组合),详见代码随想录对此题的分析 + // 如果所求的left数组和为小数,则作为整数数组的nums里的任何元素自然是没有办法凑出这个小数的 + if((sum + target) % 2 != 0) { + return 0; + } + + int left = (sum + target) / 2; + + // dp[i][j]:遍历到数组第i个数时, left为j时的能装满背包的方法总数 + int[][] dp = new int[nums.length][left + 1]; + + // 初始化最上行(dp[0][j]),当nums[0] == j时(注意nums[0]和j都一定是大于等于零的,因此不需要判断等于-j时的情况),有唯一一种取法可取到j,dp[0][j]此时等于1 + // 其他情况dp[0][j] = 0 + // java整数数组默认初始值为0 + for(int j = 0; j <= left; j++) { + if(nums[0] == j) { + dp[0][j] = 1; + } + } + + // 初始化最左列(dp[i][0]) + // 当从nums数组的索引0到i的部分有n个0时(n> 0),每个0可以取+/-,因此有2的n次方中可以取到j = 0的方案
+ // n = 0说明当前遍历到的数组部分没有0全为正数,因此只有一种方案可以取到j = 0(就是所有数都不取)
+ int numZeros = 0;
+ for(int i = 0; i < nums.length; i++) { + if(nums[i] == 0) { + numZeros++; + } + dp[i][0] = (int) Math.pow(2, numZeros); + + } + + // 递推公式分析: + // 当nums[i]> j时,这时候nums[i]一定不能取,所以是dp[i - 1][j]种方案数
+ // nums[i] <= j时,num[i]可取可不取,因此方案数是dp[i - 1][j] + dp[i - 1][j - nums[i]] + // 由递推公式可知,先遍历i或j都可 + for(int i = 1; i < nums.length; i++) { + for(int j = 1; j <= left; j++) { + if(nums[i]> j) {
+ dp[i][j] = dp[i - 1][j];
+ } else {
+ dp[i][j] = dp[i - 1][j] + dp[i - 1][j - nums[i]];
+ }
+ }
+ }
+
+ // 打印dp数组
+ // for(int i = 0; i < nums.length; i++) { + // for(int j = 0; j <= left; j++) { + // System.out.print(dp[i][j] + " "); + // } + // System.out.println(""); + // } + + return dp[nums.length - 1][left]; + + } +} +``` + ### Python 回溯版 ```python diff --git "a/problems/0647.345円233円236円346円226円207円345円255円220円344円270円262円.md" "b/problems/0647.345円233円236円346円226円207円345円255円220円344円270円262円.md" index e172de54d9..084b9f74e6 100644 --- "a/problems/0647.345円233円236円346円226円207円345円255円220円344円270円262円.md" +++ "b/problems/0647.345円233円236円346円226円207円345円255円220円344円270円262円.md" @@ -304,7 +304,38 @@ class Solution { } } ``` +LeetCode 5. Longest Palindromic Substring(LeetCode 647. 同一題的思路改一下、加一點,就能通過LeetCode 5) +```java +class Solution { + public String longestPalindrome(String s) { + //題目要求要return 最長的回文連續子串,故需要記錄當前最長的連續回文子串長度、最終起點、最終終點。 + int finalStart = 0; + int finalEnd = 0; + int finalLen = 0; + + char[] chars = s.toCharArray(); + int len = chars.length; + boolean[][] dp = new boolean[len][len]; + for (int i = len - 1; i>= 0; i--) {
+ for (int j = i; j < len; j++) { + if (chars[i] == chars[j] && (j - i <= 1 || dp[i + 1][j - 1])) + dp[i][j] = true; + //和LeetCode 647,差別就在這個if statement。 + //如果當前[i, j]範圍內的substring是回文子串(dp[i][j]) 且(&&) 長度大於當前要記錄的最終長度(j - i + 1> finalLen)
+ //我們就更新 當前最長的連續回文子串長度、最終起點、最終終點
+ if (dp[i][j] && j - i + 1> finalLen) {
+ finalLen = j - i + 1;
+ finalStart = i;
+ finalEnd = j;
+ }
+ }
+ }
+ //String.substring這個method的用法是[起點, 終點),包含起點,不包含終點(左閉右開區間),故終點 + 1。
+ return s.substring(finalStart, finalEnd + 1);
+ }
+}
+```
Python: