diff --git "a/problems/0001.344円270円244円346円225円260円344円271円213円345円222円214円.md" "b/problems/0001.344円270円244円346円225円260円344円271円213円345円222円214円.md" index fb3c1d4560..ddb052b853 100644 --- "a/problems/0001.344円270円244円346円225円260円344円271円213円345円222円214円.md" +++ "b/problems/0001.344円270円244円346円225円260円344円271円213円345円222円214円.md" @@ -317,6 +317,20 @@ public class Solution { } ``` +Dart: +```dart +List twoSum(List nums, int target) { + var tmp = []; + for (var i = 0; i < nums.length; i++) { + var rest = target - nums[i]; + if(tmp.contains(rest)){ + return [tmp.indexOf(rest), i]; + } + tmp.add(nums[i]); + } + return [0 , 0]; +} +``` -----------------------
diff --git "a/problems/0018.345円233円233円346円225円260円344円271円213円345円222円214円.md" "b/problems/0018.345円233円233円346円225円260円344円271円213円345円222円214円.md" index f6cfad29cc..6ac97af132 100644 --- "a/problems/0018.345円233円233円346円225円260円344円271円213円345円222円214円.md" +++ "b/problems/0018.345円233円233円346円225円260円344円271円213円345円222円214円.md" @@ -140,6 +140,11 @@ class Solution { for (int i = 0; i < nums.length; i++) { + // nums[i]> target 直接返回, 剪枝操作 + if (nums[i]> 0 && nums[i]> target) { + return result; + } + if (i> 0 && nums[i - 1] == nums[i]) { continue; } diff --git "a/problems/0046.345円205円250円346円216円222円345円210円227円.md" "b/problems/0046.345円205円250円346円216円222円345円210円227円.md" index 9f93564c02..06e1550a83 100644 --- "a/problems/0046.345円205円250円346円216円222円345円210円227円.md" +++ "b/problems/0046.345円205円250円346円216円222円345円210円227円.md" @@ -456,6 +456,36 @@ func permute(_ nums: [Int]) -> [[Int]] { } ``` +### Scala + +```scala +object Solution { + import scala.collection.mutable + def permute(nums: Array[Int]): List[List[Int]] = { + var result = mutable.ListBuffer[List[Int]]() + var path = mutable.ListBuffer[Int]() + + def backtracking(used: Array[Boolean]): Unit = { + if (path.size == nums.size) { + // 如果path的长度和nums相等,那么可以添加到结果集 + result.append(path.toList) + return + } + // 添加循环守卫,只有当当前数字没有用过的情况下才进入回溯 + for (i <- nums.indices if used(i) == false) { + used(i) = true + path.append(nums(i)) + backtracking(used) // 回溯 + path.remove(path.size - 1) + used(i) = false + } + } + + backtracking(new Array[Boolean](nums.size)) // 调用方法 + result.toList // 最终返回结果集的List形式 + } +} +``` -----------------------
diff --git "a/problems/0047.345円205円250円346円216円222円345円210円227円II.md" "b/problems/0047.345円205円250円346円216円222円345円210円227円II.md" index f5f9e440b0..88680c8c47 100644 --- "a/problems/0047.345円205円250円346円216円222円345円210円227円II.md" +++ "b/problems/0047.345円205円250円346円216円222円345円210円227円II.md" @@ -422,5 +422,43 @@ int** permuteUnique(int* nums, int numsSize, int* returnSize, int** returnColumn } ``` +### Scala + +```scala +object Solution { + import scala.collection.mutable + def permuteUnique(nums: Array[Int]): List[List[Int]] = { + var result = mutable.ListBuffer[List[Int]]() + var path = mutable.ListBuffer[Int]() + var num = nums.sorted // 首先对数据进行排序 + + def backtracking(used: Array[Boolean]): Unit = { + if (path.size == num.size) { + // 如果path的size等于num了,那么可以添加到结果集 + result.append(path.toList) + return + } + // 循环守卫,当前元素没被使用过就进入循环体 + for (i <- num.indices if used(i) == false) { + // 当前索引为0,不存在和前一个数字相等可以进入回溯 + // 当前索引值和上一个索引不相等,可以回溯 + // 前一个索引对应的值没有被选,可以回溯 + // 因为Scala没有continue,只能将逻辑反过来写 + if (i == 0 || (i> 0 && num(i) != num(i - 1)) || used(i-1) == false) { + used(i) = true + path.append(num(i)) + backtracking(used) + path.remove(path.size - 1) + used(i) = false + } + } + } + + backtracking(new Array[Boolean](nums.length)) + result.toList + } +} +``` + -----------------------
diff --git "a/problems/0051.N347円232円207円345円220円216円.md" "b/problems/0051.N347円232円207円345円220円216円.md" index 798902aeb5..9ae1f975d7 100644 --- "a/problems/0051.N347円232円207円345円220円216円.md" +++ "b/problems/0051.N347円232円207円345円220円216円.md" @@ -455,7 +455,7 @@ var solveNQueens = function(n) { }; ``` -## TypeScript +### TypeScript ```typescript function solveNQueens(n: number): string[][] { @@ -683,5 +683,77 @@ char *** solveNQueens(int n, int* returnSize, int** returnColumnSizes){ } ``` +### Scala + +```scala +object Solution { + import scala.collection.mutable + def solveNQueens(n: Int): List[List[String]] = { + var result = mutable.ListBuffer[List[String]]() + + def judge(x: Int, y: Int, maze: Array[Array[Boolean]]): Boolean = { + // 正上方 + var xx = x + while (xx>= 0) { + if (maze(xx)(y)) return false + xx -= 1 + } + // 左边 + var yy = y + while (yy>= 0) { + if (maze(x)(yy)) return false + yy -= 1 + } + // 左上方 + xx = x + yy = y + while (xx>= 0 && yy>= 0) { + if (maze(xx)(yy)) return false + xx -= 1 + yy -= 1 + } + xx = x + yy = y + // 右上方 + while (xx>= 0 && yy < n) { + if (maze(xx)(yy)) return false + xx -= 1 + yy += 1 + } + true + } + + def backtracking(row: Int, maze: Array[Array[Boolean]]): Unit = { + if (row == n) { + // 将结果转换为题目所需要的形式 + var path = mutable.ListBuffer[String]() + for (x <- maze) { + var tmp = mutable.ListBuffer[String]() + for (y <- x) { + if (y == true) tmp.append("Q") + else tmp.append(".") + } + path.append(tmp.mkString) + } + result.append(path.toList) + return + } + + for (j <- 0 until n) { + // 判断这个位置是否可以放置皇后 + if (judge(row, j, maze)) { + maze(row)(j) = true + backtracking(row + 1, maze) + maze(row)(j) = false + } + } + } + + backtracking(0, Array.ofDim[Boolean](n, n)) + result.toList + } +} +``` + -----------------------
diff --git "a/problems/0056.345円220円210円345円271円266円345円214円272円351円227円264円.md" "b/problems/0056.345円220円210円345円271円266円345円214円272円351円227円264円.md" index 34d8dd8242..7fe7c3d009 100644 --- "a/problems/0056.345円220円210円345円271円266円345円214円272円351円227円264円.md" +++ "b/problems/0056.345円220円210円345円271円266円345円214円272円351円227円264円.md" @@ -136,24 +136,38 @@ public: ### Java ```java + +/** +时间复杂度 : O(NlogN) 排序需要O(NlogN) +空间复杂度 : O(logN) java 的内置排序是快速排序 需要 O(logN)空间 + +*/ class Solution { public int[][] merge(int[][] intervals) { List res = new LinkedList(); - Arrays.sort(intervals, (o1, o2) -> Integer.compare(o1[0], o2[0])); - + //按照左边界排序 + Arrays.sort(intervals, (x, y) -> Integer.compare(x[0], y[0])); + //initial start 是最小左边界 int start = intervals[0][0]; + int rightmostRightBound = intervals[0][1]; for (int i = 1; i < intervals.length; i++) { - if (intervals[i][0]> intervals[i - 1][1]) { - res.add(new int[]{start, intervals[i - 1][1]}); + //如果左边界大于最大右边界 + if (intervals[i][0]> rightmostRightBound) { + //加入区间 并且更新start + res.add(new int[]{start, rightmostRightBound}); start = intervals[i][0]; + rightmostRightBound = intervals[i][1]; } else { - intervals[i][1] = Math.max(intervals[i][1], intervals[i - 1][1]); + //更新最大右边界 + rightmostRightBound = Math.max(rightmostRightBound, intervals[i][1]); } } - res.add(new int[]{start, intervals[intervals.length - 1][1]}); + res.add(new int[]{start, rightmostRightBound}); return res.toArray(new int[res.size()][]); } } + +} ``` ```java // 版本2 diff --git "a/problems/0104.344円272円214円345円217円211円346円240円221円347円232円204円346円234円200円345円244円247円346円267円261円345円272円246円.md" "b/problems/0104.344円272円214円345円217円211円346円240円221円347円232円204円346円234円200円345円244円247円346円267円261円345円272円246円.md" index ed27f95d11..559801897a 100644 --- "a/problems/0104.344円272円214円345円217円211円346円240円221円347円232円204円346円234円200円345円244円247円346円267円261円345円272円246円.md" +++ "b/problems/0104.344円272円214円345円217円211円346円240円221円347円232円204円346円234円200円345円244円247円346円267円261円345円272円246円.md" @@ -294,14 +294,13 @@ class solution { /** * 递归法 */ - public int maxdepth(treenode root) { + public int maxDepth(TreeNode root) { if (root == null) { return 0; } - int leftdepth = maxdepth(root.left); - int rightdepth = maxdepth(root.right); - return math.max(leftdepth, rightdepth) + 1; - + int leftDepth = maxDepth(root.left); + int rightDepth = maxDepth(root.right); + return Math.max(leftDepth, rightDepth) + 1; } } ``` @@ -311,23 +310,23 @@ class solution { /** * 迭代法,使用层序遍历 */ - public int maxdepth(treenode root) { + public int maxDepth(TreeNode root) { if(root == null) { return 0; } - deque
deque = new linkedlist(); + Deque
deque = new LinkedList(); deque.offer(root); int depth = 0; - while (!deque.isempty()) { + while (!deque.isEmpty()) { int size = deque.size(); depth++; for (int i = 0; i < size; i++) { - treenode poll = deque.poll(); - if (poll.left != null) { - deque.offer(poll.left); + TreeNode node = deque.poll(); + if (node.left != null) { + deque.offer(node.left); } - if (poll.right != null) { - deque.offer(poll.right); + if (node.right != null) { + deque.offer(node.right); } } } diff --git "a/problems/0129.346円261円202円346円240円271円345円210円260円345円217円266円345円255円220円350円212円202円347円202円271円346円225円260円345円255円227円344円271円213円345円222円214円.md" "b/problems/0129.346円261円202円346円240円271円345円210円260円345円217円266円345円255円220円350円212円202円347円202円271円346円225円260円345円255円227円344円271円213円345円222円214円.md" index ea3845b741..f763d65aa0 100644 --- "a/problems/0129.346円261円202円346円240円271円345円210円260円345円217円266円345円255円220円350円212円202円347円202円271円346円225円260円345円255円227円344円271円213円345円222円214円.md" +++ "b/problems/0129.346円261円202円346円240円271円345円210円260円345円217円266円345円255円220円350円212円202円347円202円271円346円225円260円345円255円227円344円271円213円345円222円214円.md" @@ -3,6 +3,9 @@

参与本项目,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!

+ + + # 129. 求根节点到叶节点数字之和 [力扣题目链接](https://leetcode.cn/problems/sum-root-to-leaf-numbers/) @@ -245,6 +248,29 @@ class Solution: ``` Go: +```go +func sumNumbers(root *TreeNode) int { + sum = 0 + travel(root, root.Val) + return sum +} + +func travel(root *TreeNode, tmpSum int) { + if root.Left == nil && root.Right == nil { + sum += tmpSum + } else { + if root.Left != nil { + travel(root.Left, tmpSum*10+root.Left.Val) + } + if root.Right != nil { + travel(root.Right, tmpSum*10+root.Right.Val) + } + } +} +``` + + + JavaScript: ```javascript var sumNumbers = function(root) { diff --git "a/problems/0132.345円210円206円345円211円262円345円233円236円346円226円207円344円270円262円II.md" "b/problems/0132.345円210円206円345円211円262円345円233円236円346円226円207円344円270円262円II.md" index 92f9b60238..36db56cb16 100644 --- "a/problems/0132.345円210円206円345円211円262円345円233円236円346円226円207円344円270円262円II.md" +++ "b/problems/0132.345円210円206円345円211円262円345円233円236円346円226円207円344円270円262円II.md" @@ -206,6 +206,55 @@ public: ## Java ```java +class Solution { + + public int minCut(String s) { + if(null == s || "".equals(s)){ + return 0; + } + int len = s.length(); + // 1. + // 记录子串[i..j]是否是回文串 + boolean[][] isPalindromic = new boolean[len][len]; + // 从下到上,从左到右 + for(int i = len - 1; i>= 0; i--){ + for(int j = i; j < len; j++){ + if(s.charAt(i) == s.charAt(j)){ + if(j - i <= 1){ + isPalindromic[i][j] = true; + } else{ + isPalindromic[i][j] = isPalindromic[i + 1][j - 1]; + } + } else{ + isPalindromic[i][j] = false; + } + } + } + + // 2. + // dp[i] 表示[0..i]的最小分割次数 + int[] dp = new int[len]; + for(int i = 0; i < len; i++){ + //初始考虑最坏的情况。 1个字符分割0次, len个字符分割 len - 1次 + dp[i] = i; + } + + for(int i = 1; i < len; i++){ + if(isPalindromic[0][i]){ + // s[0..i]是回文了,那 dp[i] = 0, 一次也不用分割 + dp[i] = 0; + continue; + } + for(int j = 0; j < i; j++){ + // 按文中的思路,不清楚就拿 "ababa" 为例,先写出 isPalindromic 数组,再进行求解 + if(isPalindromic[j + 1][i]){ + dp[i] = Math.min(dp[i], dp[j] + 1); + } + } + } + return dp[len - 1]; + } +} ``` ## Python @@ -240,6 +289,7 @@ class Solution: ## Go ```go + ``` ## JavaScript diff --git "a/problems/0226.347円277円273円350円275円254円344円272円214円345円217円211円346円240円221円.md" "b/problems/0226.347円277円273円350円275円254円344円272円214円345円217円211円346円240円221円.md" index 8e35fc9d33..83d20df856 100644 --- "a/problems/0226.347円277円273円350円275円254円344円272円214円345円217円211円346円240円221円.md" +++ "b/problems/0226.347円277円273円350円275円254円344円272円214円345円217円211円346円240円221円.md" @@ -470,25 +470,14 @@ func invertTree(root *TreeNode) *TreeNode { 使用递归版本的前序遍历 ```javascript var invertTree = function(root) { - //1. 首先使用递归版本的前序遍历实现二叉树翻转 - //交换节点函数 - const inverNode=function(left,right){ - let temp=left; - left=right; - right=temp; - //需要重新给root赋值一下 - root.left=left; - root.right=right; - } - //确定递归函数的参数和返回值inverTree=function(root) - //确定终止条件 - if(root===null){ - return root; - } - //确定节点处理逻辑 交换 - inverNode(root.left,root.right); - invertTree(root.left); - invertTree(root.right); + // 终止条件 + if (!root) { + return null; + } + // 交换左右节点 + const rightNode = root.right; + root.right = invertTree(root.left); + root.left = invertTree(rightNode); return root; }; ``` diff --git "a/problems/0347.345円211円215円K344円270円252円351円253円230円351円242円221円345円205円203円347円264円240円.md" "b/problems/0347.345円211円215円K344円270円252円351円253円230円351円242円221円345円205円203円347円264円240円.md" index a04041ccdf..0c978b2a6c 100644 --- "a/problems/0347.345円211円215円K344円270円252円351円253円230円351円242円221円345円205円203円347円264円240円.md" +++ "b/problems/0347.345円211円215円K344円270円252円351円253円230円351円242円221円345円205円203円347円264円240円.md" @@ -141,13 +141,10 @@ class Solution { } Set
    > entries = map.entrySet(); - // 根据map的value值正序排,相当于一个小顶堆 - PriorityQueue
      > queue = new PriorityQueue((o1, o2) -> o1.getValue() - o2.getValue()); + // 根据map的value值,构建于一个大顶堆(o1 - o2: 小顶堆, o2 - o1 : 大顶堆) + PriorityQueue
        > queue = new PriorityQueue((o1, o2) -> o2.getValue() - o1.getValue()); for (Map.Entry entry : entries) { queue.offer(entry); - if (queue.size()> k) { - queue.poll(); - } } for (int i = k - 1; i>= 0; i--) { result[i] = queue.poll().getKey(); diff --git "a/problems/0450.345円210円240円351円231円244円344円272円214円345円217円211円346円220円234円347円264円242円346円240円221円344円270円255円347円232円204円350円212円202円347円202円271円.md" "b/problems/0450.345円210円240円351円231円244円344円272円214円345円217円211円346円220円234円347円264円242円346円240円221円344円270円255円347円232円204円350円212円202円347円202円271円.md" index 3fa2a1c586..3bc8369cc0 100644 --- "a/problems/0450.345円210円240円351円231円244円344円272円214円345円217円211円346円220円234円347円264円242円346円240円221円344円270円255円347円232円204円350円212円202円347円202円271円.md" +++ "b/problems/0450.345円210円240円351円231円244円344円272円214円345円217円211円346円220円234円347円264円242円346円240円221円344円270円255円347円232円204円350円212円202円347円202円271円.md" @@ -456,31 +456,42 @@ func deleteNode(root *TreeNode, key int) *TreeNode { * @param {number} key * @return {TreeNode} */ -var deleteNode = function (root, key) { - if (root === null) +var deleteNode = function(root, key) { + if (!root) return null; + if (key> root.val) { + root.right = deleteNode(root.right, key); return root; - if (root.val === key) { - if (!root.left) - return root.right; - else if (!root.right) + } else if (key < root.val) { + root.left = deleteNode(root.left, key); + return root; + } else { + // 场景1: 该节点是叶节点 + if (!root.left && !root.right) { + return null + } + // 场景2: 有一个孩子节点不存在 + if (root.left && !root.right) { return root.left; - else { - let cur = root.right; - while (cur.left) { - cur = cur.left; - } - cur.left = root.left; - root = root.right; - delete root; - return root; + } else if (root.right && !root.left) { + return root.right; } + // 场景3: 左右节点都存在 + const rightNode = root.right; + // 获取最小值节点 + const minNode = getMinNode(rightNode); + // 将待删除节点的值替换为最小值节点值 + root.val = minNode.val; + // 删除最小值节点 + root.right = deleteNode(root.right, minNode.val); + return root; } - if (root.val> key) - root.left = deleteNode(root.left, key); - if (root.val < key) - root.right = deleteNode(root.right, key); - return root; }; +function getMinNode(root) { + while (root.left) { + root = root.left; + } + return root; +} ``` 迭代 diff --git "a/problems/0977.346円234円211円345円272円217円346円225円260円347円273円204円347円232円204円345円271円263円346円226円271円.md" "b/problems/0977.346円234円211円345円272円217円346円225円260円347円273円204円347円232円204円345円271円263円346円226円271円.md" index 458107dd2e..59816eb36e 100644 --- "a/problems/0977.346円234円211円345円272円217円346円225円260円347円273円204円347円232円204円345円271円263円346円226円271円.md" +++ "b/problems/0977.346円234円211円345円272円217円346円225円260円347円273円204円347円232円204円345円271円263円346円226円271円.md" @@ -106,6 +106,7 @@ class Solution { int index = result.length - 1; while (left <= right) { if (nums[left] * nums[left]> nums[right] * nums[right]) { + // 正数的相对位置是不变的, 需要调整的是负数平方后的相对位置 result[index--] = nums[left] * nums[left]; ++left; } else { diff --git "a/problems/1143.346円234円200円351円225円277円345円205円254円345円205円261円345円255円220円345円272円217円345円210円227円.md" "b/problems/1143.346円234円200円351円225円277円345円205円254円345円205円261円345円255円220円345円272円217円345円210円227円.md" index ad9825b818..4f4cb32a8b 100644 --- "a/problems/1143.346円234円200円351円225円277円345円205円254円345円205円261円345円255円220円345円272円217円345円210円227円.md" +++ "b/problems/1143.346円234円200円351円225円277円345円205円254円345円205円261円345円255円220円345円272円217円345円210円227円.md" @@ -129,6 +129,9 @@ public: Java: ```java +/* + 二维dp数组 +*/ class Solution { public int longestCommonSubsequence(String text1, String text2) { int[][] dp = new int[text1.length() + 1][text2.length() + 1]; // 先对dp数组做初始化操作 @@ -146,6 +149,47 @@ class Solution { return dp[text1.length()][text2.length()]; } } + + + +/** + 一维dp数组 +*/ +class Solution { + public int longestCommonSubsequence(String text1, String text2) { + int n1 = text1.length(); + int n2 = text2.length(); + + // 多从二维dp数组过程分析 + // 关键在于 如果记录 dp[i - 1][j - 1] + // 因为 dp[i - 1][j - 1] dp[j - 1] <=> dp[i][j - 1] + int [] dp = new int[n2 + 1]; + + for(int i = 1; i <= n1; i++){ + + // 这里pre相当于 dp[i - 1][j - 1] + int pre = dp[0]; + for(int j = 1; j <= n2; j++){ + + //用于给pre赋值 + int cur = dp[j]; + if(text1.charAt(i - 1) == text2.charAt(j - 1)){ + //这里pre相当于dp[i - 1][j - 1] 千万不能用dp[j - 1] !! + dp[j] = pre + 1; + } else{ + // dp[j] 相当于 dp[i - 1][j] + // dp[j - 1] 相当于 dp[i][j - 1] + dp[j] = Math.max(dp[j], dp[j - 1]); + } + + //更新dp[i - 1][j - 1], 为下次使用做准备 + pre = cur; + } + } + + return dp[n2]; + } +} ``` Python:

AltStyle によって変換されたページ (->オリジナル) /