diff --git a/problems/0020.有效的括号.md b/problems/0020.有效的括号.md index c3ff9d53..eaf0a719 100644 --- a/problems/0020.有效的括号.md +++ b/problems/0020.有效的括号.md @@ -402,6 +402,38 @@ bool isValid(char * s){ ``` +C#: +```csharp +public class Solution { + public bool IsValid(string s) { + var len = s.Length; + if(len % 2 == 1) return false; // 字符串长度为单数,直接返回 false + // 初始化栈 + var stack = new Stack(); + // 遍历字符串 + for(int i = 0; i < len; i++){ + // 当字符串为左括号时,进栈对应的右括号 + if(s[i] == '('){ + stack.Push(')'); + }else if(s[i] == '['){ + stack.Push(']'); + }else if(s[i] == '{'){ + stack.Push('}'); + } + // 当字符串为右括号时,当栈为空(无左括号) 或者 出栈字符不是当前的字符 + else if(stack.Count == 0 || stack.Pop() != s[i]) + return false; + } + // 如果栈不为空,例如“((()”,右括号少于左括号,返回false + if (stack.Count > 0) + return false; + // 上面的校验都满足,则返回true + else + return true; + } +} +``` + PHP: ```php // https://www.php.net/manual/zh/class.splstack.php diff --git a/problems/0031.下一个排列.md b/problems/0031.下一个排列.md index 1a3641b0..ada9deba 100644 --- a/problems/0031.下一个排列.md +++ b/problems/0031.下一个排列.md @@ -116,6 +116,48 @@ class Solution { } } ``` +> 优化时间复杂度为O(N),空间复杂度为O(1) +```Java +class Solution { + public void nextPermutation(int[] nums) { + // 1.从后向前获取逆序区域的前一位 + int index = findIndex(nums); + // 判断数组是否处于最小组合状态 + if(index != 0){ + // 2.交换逆序区域刚好大于它的最小数字 + exchange(nums,index); + } + // 3.把原来的逆序区转为顺序 + reverse(nums,index); + } + + public static int findIndex(int [] nums){ + for(int i = nums.length-1;i>0;i--){ + if(nums[i]>nums[i-1]){ + return i; + } + } + return 0; + } + public static void exchange(int [] nums, int index){ + int head = nums[index-1]; + for(int i = nums.length-1;i>0;i--){ + if(head < nums[i]){ + nums[index-1] = nums[i]; + nums[i] = head; + break; + } + } + } + public static void reverse(int [] nums, int index){ + for(int i = index,j = nums.length-1;i直接使用sorted()不符合题意 @@ -164,7 +206,7 @@ class Solution: high -= 1 ``` >上一版本简化版 -'''python +```python class Solution(object): def nextPermutation(self, nums: List[int]) -> None: n = len(nums) @@ -185,7 +227,7 @@ class Solution(object): end -= 1 return nums -''' +``` ## Go diff --git a/problems/0035.搜索插入位置.md b/problems/0035.搜索插入位置.md index 77def4f8..f2bbb8ca 100644 --- a/problems/0035.搜索插入位置.md +++ b/problems/0035.搜索插入位置.md @@ -142,7 +142,7 @@ public: ``` * 时间复杂度:O(log n) -* 时间复杂度:O(1) +* 空间复杂度:O(1) 效率如下: ![35_搜索插入位置2](https://img-blog.csdnimg.cn/2020121623272877.png) diff --git a/problems/0039.组合总和.md b/problems/0039.组合总和.md index 54e9f2e5..d9aa3785 100644 --- a/problems/0039.组合总和.md +++ b/problems/0039.组合总和.md @@ -417,6 +417,35 @@ function combinationSum(candidates: number[], target: number): number[][] { }; ``` +## Rust + +```Rust +impl Solution { + pub fn backtracking(result: &mut Vec>, path: &mut Vec, candidates: &Vec, target: i32, mut sum: i32, start_index: usize) { + if sum == target { + result.push(path.to_vec()); + return; + } + for i in start_index..candidates.len() { + if sum + candidates[i] <= target { + sum += candidates[i]; + path.push(candidates[i]); + Self::backtracking(result, path, candidates, target, sum, i); + sum -= candidates[i]; + path.pop(); + } + } + } + + pub fn combination_sum(candidates: Vec, target: i32) -> Vec> { + let mut result: Vec> = Vec::new(); + let mut path: Vec = Vec::new(); + Self::backtracking(&mut result, &mut path, &candidates, target, 0, 0); + result + } +} +``` + ## C ```c diff --git a/problems/0040.组合总和II.md b/problems/0040.组合总和II.md index 557eb855..99577f0c 100644 --- a/problems/0040.组合总和II.md +++ b/problems/0040.组合总和II.md @@ -599,6 +599,41 @@ function combinationSum2(candidates: number[], target: number): number[][] { }; ``` +## Rust + +```Rust +impl Solution { + pub fn backtracking(result: &mut Vec>, path: &mut Vec, candidates: &Vec, target: i32, mut sum: i32, start_index: usize, used: &mut Vec) { + if sum == target { + result.push(path.to_vec()); + return; + } + for i in start_index..candidates.len() { + if sum + candidates[i] <= target { + if i > 0 && candidates[i] == candidates[i - 1] && used[i - 1] == false { continue; } + sum += candidates[i]; + path.push(candidates[i]); + used[i] = true; + Self::backtracking(result, path, candidates, target, sum, i + 1, used); + used[i] = false; + sum -= candidates[i]; + path.pop(); + } + } + } + + pub fn combination_sum2(candidates: Vec, target: i32) -> Vec> { + let mut result: Vec> = Vec::new(); + let mut path: Vec = Vec::new(); + let mut used: Vec = vec![false; candidates.len()]; + let mut candidates = candidates; + candidates.sort(); + Self::backtracking(&mut result, &mut path, &candidates, target, 0, 0, &mut used); + result + } +} +``` + ## C ```c diff --git a/problems/0056.合并区间.md b/problems/0056.合并区间.md index a8f36fdf..627ca5b1 100644 --- a/problems/0056.合并区间.md +++ b/problems/0056.合并区间.md @@ -297,7 +297,37 @@ function merge(intervals: number[][]): number[][] { }; ``` +### Scala +```scala +object Solution { + import scala.collection.mutable + def merge(intervals: Array[Array[Int]]): Array[Array[Int]] = { + var res = mutable.ArrayBuffer[Array[Int]]() + + // 排序 + var interval = intervals.sortWith((a, b) => { + a(0) < b(0) + }) + + var left = interval(0)(0) + var right = interval(0)(1) + + for (i <- 1 until interval.length) { + if (interval(i)(0) <= right) { + left = math.min(left, interval(i)(0)) + right = math.max(right, interval(i)(1)) + } else { + res.append(Array[Int](left, right)) + left = interval(i)(0) + right = interval(i)(1) + } + } + res.append(Array[Int](left, right)) + res.toArray // 返回res的Array形式 + } +} +``` -----------------------
diff --git a/problems/0059.螺旋矩阵II.md b/problems/0059.螺旋矩阵II.md index aa3c848d..54d7b5bb 100644 --- a/problems/0059.螺旋矩阵II.md +++ b/problems/0059.螺旋矩阵II.md @@ -598,5 +598,30 @@ object Solution { } } ``` +C#: +```csharp +public class Solution { + public int[][] GenerateMatrix(int n) { + int[][] answer = new int[n][]; + for(int i = 0; i < n; i++) + answer[i] = new int[n]; + int start = 0; + int end = n - 1; + int tmp = 1; + while(tmp < n * n) + { + for(int i = start; i < end; i++) answer[start][i] = tmp++; + for(int i = start; i < end; i++) answer[i][end] = tmp++; + for(int i = end; i > start; i--) answer[end][i] = tmp++; + for(int i = end; i > start; i--) answer[i][start] = tmp++; + start++; + end--; + } + if(n % 2 == 1) answer[n / 2][n / 2] = tmp; + return answer; + } +} +``` + -----------------------
diff --git a/problems/0062.不同路径.md b/problems/0062.不同路径.md index aa7c8ab8..5790df69 100644 --- a/problems/0062.不同路径.md +++ b/problems/0062.不同路径.md @@ -436,5 +436,21 @@ int uniquePaths(int m, int n){ } ``` +### Scala + +```scala +object Solution { + def uniquePaths(m: Int, n: Int): Int = { + var dp = Array.ofDim[Int](m, n) + for (i <- 0 until m) dp(i)(0) = 1 + for (j <- 1 until n) dp(0)(j) = 1 + for (i <- 1 until m; j <- 1 until n) { + dp(i)(j) = dp(i - 1)(j) + dp(i)(j - 1) + } + dp(m - 1)(n - 1) + } +} +``` + -----------------------
diff --git a/problems/0063.不同路径II.md b/problems/0063.不同路径II.md index e3857db6..c7326b63 100644 --- a/problems/0063.不同路径II.md +++ b/problems/0063.不同路径II.md @@ -476,5 +476,37 @@ int uniquePathsWithObstacles(int** obstacleGrid, int obstacleGridSize, int* obst } ``` +### Scala + +```scala +object Solution { + import scala.util.control.Breaks._ + def uniquePathsWithObstacles(obstacleGrid: Array[Array[Int]]): Int = { + var (m, n) = (obstacleGrid.length, obstacleGrid(0).length) + var dp = Array.ofDim[Int](m, n) + + // 比如break、continue这些流程控制需要使用breakable + breakable( + for (i <- 0 until m) { + if (obstacleGrid(i)(0) != 1) dp(i)(0) = 1 + else break() + } + ) + breakable( + for (j <- 0 until n) { + if (obstacleGrid(0)(j) != 1) dp(0)(j) = 1 + else break() + } + ) + + for (i <- 1 until m; j <- 1 until n; if obstacleGrid(i)(j) != 1) { + dp(i)(j) = dp(i - 1)(j) + dp(i)(j - 1) + } + + dp(m - 1)(n - 1) + } +} +``` + -----------------------
diff --git a/problems/0070.爬楼梯.md b/problems/0070.爬楼梯.md index c92c581c..30c3642f 100644 --- a/problems/0070.爬楼梯.md +++ b/problems/0070.爬楼梯.md @@ -401,6 +401,38 @@ int climbStairs(int n){ } ``` +### Scala + +```scala +object Solution { + def climbStairs(n: Int): Int = { + if (n <= 2) return n + var dp = new Array[Int](n + 1) + dp(1) = 1 + dp(2) = 2 + for (i <- 3 to n) { + dp(i) = dp(i - 1) + dp(i - 2) + } + dp(n) + } +} +``` + +优化空间复杂度: +```scala +object Solution { + def climbStairs(n: Int): Int = { + if (n <= 2) return n + var (a, b) = (1, 2) + for (i <- 3 to n) { + var tmp = a + b + a = b + b = tmp + } + b // 最终返回b + } +} +``` -----------------------
diff --git a/problems/0090.子集II.md b/problems/0090.子集II.md index e85ec66d..d503846e 100644 --- a/problems/0090.子集II.md +++ b/problems/0090.子集II.md @@ -261,6 +261,33 @@ class Solution: self.path.pop() ``` +### Python3 +```python3 +class Solution: + def subsetsWithDup(self, nums: List[int]) -> List[List[int]]: + res = [] + path = [] + nums.sort() # 去重需要先对数组进行排序 + + def backtracking(nums, startIndex): + # 终止条件 + res.append(path[:]) + if startIndex == len(nums): + return + + # for循环 + for i in range(startIndex, len(nums)): + # 数层去重 + if i > startIndex and nums[i] == nums[i-1]: # 去重 + continue + path.append(nums[i]) + backtracking(nums, i+1) + path.pop() + + backtracking(nums, 0) + return res +``` + ### Go ```Go diff --git a/problems/0096.不同的二叉搜索树.md b/problems/0096.不同的二叉搜索树.md index 9d98c62d..9adc0457 100644 --- a/problems/0096.不同的二叉搜索树.md +++ b/problems/0096.不同的二叉搜索树.md @@ -227,7 +227,7 @@ const numTrees =(n) => { }; ``` -TypeScript +### TypeScript ```typescript function numTrees(n: number): number { @@ -282,5 +282,22 @@ int numTrees(int n){ } ``` +### Scala + +```scala +object Solution { + def numTrees(n: Int): Int = { + var dp = new Array[Int](n + 1) + dp(0) = 1 + for (i <- 1 to n) { + for (j <- 1 to i) { + dp(i) += dp(j - 1) * dp(i - j) + } + } + dp(n) + } +} +``` + -----------------------
diff --git a/problems/0111.二叉树的最小深度.md b/problems/0111.二叉树的最小深度.md index 0137bd15..6378300c 100644 --- a/problems/0111.二叉树的最小深度.md +++ b/problems/0111.二叉树的最小深度.md @@ -372,7 +372,7 @@ var minDepth1 = function(root) { // 到叶子节点 返回 1 if(!root.left && !root.right) return 1; // 只有右节点时 递归右节点 - if(!root.left) return 1 + minDepth(root.right);、 + if(!root.left) return 1 + minDepth(root.right); // 只有左节点时 递归左节点 if(!root.right) return 1 + minDepth(root.left); return Math.min(minDepth(root.left), minDepth(root.right)) + 1; diff --git a/problems/0131.分割回文串.md b/problems/0131.分割回文串.md index 64d45853..a54d6576 100644 --- a/problems/0131.分割回文串.md +++ b/problems/0131.分割回文串.md @@ -626,7 +626,8 @@ func partition(_ s: String) -> [[String]] { ## Rust -```rust +**回溯+函数判断回文串** +```Rust impl Solution { pub fn partition(s: String) -> Vec> { let mut ret = vec![]; @@ -676,6 +677,40 @@ impl Solution { } } ``` +**回溯+动态规划预处理判断回文串** +```Rust +impl Solution { + pub fn backtracking(is_palindrome: &Vec>, result: &mut Vec>, path: &mut Vec, s: &Vec, start_index: usize) { + let len = s.len(); + if start_index >= len { + result.push(path.to_vec()); + return; + } + for i in start_index..len { + if is_palindrome[start_index][i] { path.push(s[start_index..=i].iter().collect::()); } else { continue; } + Self::backtracking(is_palindrome, result, path, s, i + 1); + path.pop(); + } + } + + pub fn partition(s: String) -> Vec> { + let mut result: Vec> = Vec::new(); + let mut path: Vec = Vec::new(); + let s = s.chars().collect::>(); + let len: usize = s.len(); + // 使用动态规划预先打表 + // 当且仅当其为空串(i>j),或其长度为1(i=j),或者首尾字符相同且(s[i+1..j−1])时为回文串 + let mut is_palindrome = vec![vec![true; len]; len]; + for i in (0..len).rev() { + for j in (i + 1)..len { + is_palindrome[i][j] = s[i] == s[j] && is_palindrome[i + 1][j - 1]; + } + } + Self::backtracking(&is_palindrome, &mut result, &mut path, &s, 0); + result + } +} +``` ## Scala diff --git a/problems/0135.分发糖果.md b/problems/0135.分发糖果.md index 55c2efc7..242664f0 100644 --- a/problems/0135.分发糖果.md +++ b/problems/0135.分发糖果.md @@ -324,6 +324,31 @@ function candy(ratings: number[]): number { }; ``` +### Scala + +```scala +object Solution { + def candy(ratings: Array[Int]): Int = { + var candyVec = new Array[Int](ratings.length) + for (i <- candyVec.indices) candyVec(i) = 1 + // 从前向后 + for (i <- 1 until candyVec.length) { + if (ratings(i) > ratings(i - 1)) { + candyVec(i) = candyVec(i - 1) + 1 + } + } + + // 从后向前 + for (i <- (candyVec.length - 2) to 0 by -1) { + if (ratings(i) > ratings(i + 1)) { + candyVec(i) = math.max(candyVec(i), candyVec(i + 1) + 1) + } + } + + candyVec.sum // 求和 + } +} +``` ----------------------- diff --git a/problems/0150.逆波兰表达式求值.md b/problems/0150.逆波兰表达式求值.md index 1a90265a..21bd8593 100644 --- a/problems/0150.逆波兰表达式求值.md +++ b/problems/0150.逆波兰表达式求值.md @@ -326,6 +326,40 @@ func evalRPN(_ tokens: [String]) -> Int { } ``` +C#: +```csharp +public int EvalRPN(string[] tokens) { + int num; + Stack stack = new Stack(); + foreach(string s in tokens){ + if(int.TryParse(s, out num)){ + stack.Push(num); + }else{ + int num1 = stack.Pop(); + int num2 = stack.Pop(); + switch (s) + { + case "+": + stack.Push(num1 + num2); + break; + case "-": + stack.Push(num2 - num1); + break; + case "*": + stack.Push(num1 * num2); + break; + case "/": + stack.Push(num2 / num1); + break; + default: + break; + } + } + } + return stack.Pop(); + } +``` + PHP: ```php diff --git a/problems/0225.用队列实现栈.md b/problems/0225.用队列实现栈.md index 40415d8d..17c50cd9 100644 --- a/problems/0225.用队列实现栈.md +++ b/problems/0225.用队列实现栈.md @@ -900,6 +900,41 @@ class MyStack() { ``` +C#: +```csharp +public class MyStack { + Queue queue1; + Queue queue2; + public MyStack() { + queue1 = new Queue(); + queue2 = new Queue(); + } + + public void Push(int x) { + queue2.Enqueue(x); + while(queue1.Count != 0){ + queue2.Enqueue(queue1.Dequeue()); + } + Queue queueTemp; + queueTemp = queue1; + queue1 = queue2; + queue2 = queueTemp; + } + + public int Pop() { + return queue1.Count > 0 ? queue1.Dequeue() : -1; + } + + public int Top() { + return queue1.Count > 0 ? queue1.Peek() : -1; + } + + public bool Empty() { + return queue1.Count == 0; + } +} +``` + PHP > 双对列 ```php diff --git a/problems/0232.用栈实现队列.md b/problems/0232.用栈实现队列.md index c8374a61..4dc7b794 100644 --- a/problems/0232.用栈实现队列.md +++ b/problems/0232.用栈实现队列.md @@ -497,6 +497,49 @@ void myQueueFree(MyQueue* obj) { ``` +C#: +```csharp +public class MyQueue { + Stack inStack; + Stack outStack; + + public MyQueue() { + inStack = new Stack();// 负责进栈 + outStack = new Stack();// 负责出栈 + } + + public void Push(int x) { + inStack.Push(x); + } + + public int Pop() { + dumpstackIn(); + return outStack.Pop(); + } + + public int Peek() { + dumpstackIn(); + return outStack.Peek(); + } + + public bool Empty() { + return inStack.Count == 0 && outStack.Count == 0; + } + + // 处理方法: + // 如果outStack为空,那么将inStack中的元素全部放到outStack中 + private void dumpstackIn(){ + if (outStack.Count != 0) return; + while(inStack.Count != 0){ + outStack.Push(inStack.Pop()); + } + } +} + +``` + + + PHP: ```php // SplStack 类通过使用一个双向链表来提供栈的主要功能。[PHP 5 >= 5.3.0, PHP 7, PHP 8] @@ -583,5 +626,6 @@ class MyQueue() { } ``` + -----------------------
diff --git a/problems/0234.回文链表.md b/problems/0234.回文链表.md index 0dbe88c4..1f515623 100644 --- a/problems/0234.回文链表.md +++ b/problems/0234.回文链表.md @@ -258,7 +258,75 @@ class Solution: ### Go ```go +/** + * Definition for singly-linked list. + * type ListNode struct { + * Val int + * Next *ListNode + * } + */ +//方法一,使用数组 +func isPalindrome(head *ListNode) bool{ + //计算切片长度,避免切片频繁扩容 + cur,ln:=head,0 + for cur!=nil{ + ln++ + cur=cur.Next + } + nums:=make([]int,ln) + index:=0 + for head!=nil{ + nums[index]=head.Val + index++ + head=head.Next + } + //比较回文切片 + for i,j:=0,ln-1;i<=j;i,j=i+1,j-1{ + if nums[i]!=nums[j]{return false} + } + return true +} +// 方法二,快慢指针 +func isPalindrome(head *ListNode) bool { + if head==nil&&head.Next==nil{return true} + //慢指针,找到链表中间分位置,作为分割 + slow:=head + fast:=head + //记录慢指针的前一个节点,用来分割链表 + pre:=head + for fast!=nil && fast.Next!=nil{ + pre=slow + slow=slow.Next + fast=fast.Next.Next + } + //分割链表 + pre.Next=nil + //前半部分 + cur1:=head + //反转后半部分,总链表长度如果是奇数,cur2比cur1多一个节点 + cur2:=ReverseList(slow) + + //开始两个链表的比较 + for cur1!=nil{ + if cur1.Val!=cur2.Val{return false} + cur1=cur1.Next + cur2=cur2.Next + } + return true +} +//反转链表 +func ReverseList(head *ListNode) *ListNode{ + var pre *ListNode + cur:=head + for cur!=nil{ + tmp:=cur.Next + cur.Next=pre + pre=cur + cur=tmp + } + return pre +} ``` ### JavaScript diff --git a/problems/0239.滑动窗口最大值.md b/problems/0239.滑动窗口最大值.md index 7ee1fdb1..474b3a75 100644 --- a/problems/0239.滑动窗口最大值.md +++ b/problems/0239.滑动窗口最大值.md @@ -756,5 +756,46 @@ class MyQueue{ } ``` +C#: +```csharp +class myDequeue{ + private LinkedList linkedList = new LinkedList(); + + public void Enqueue(int n){ + while(linkedList.Count > 0 && linkedList.Last.Value < n){ + linkedList.RemoveLast(); + } + linkedList.AddLast(n); + } + + public int Max(){ + return linkedList.First.Value; + } + + public void Dequeue(int n){ + if(linkedList.First.Value == n){ + linkedList.RemoveFirst(); + } + } + } + + myDequeue window = new myDequeue(); + List res = new List(); + + public int[] MaxSlidingWindow(int[] nums, int k) { + for(int i = 0; i < k; i++){ + window.Enqueue(nums[i]); + } + res.Add(window.Max()); + for(int i = k; i < nums.Length; i++){ + window.Dequeue(nums[i-k]); + window.Enqueue(nums[i]); + res.Add(window.Max()); + } + + return res.ToArray(); + } +``` + -----------------------
diff --git a/problems/0242.有效的字母异位词.md b/problems/0242.有效的字母异位词.md index 0437330b..87302482 100644 --- a/problems/0242.有效的字母异位词.md +++ b/problems/0242.有效的字母异位词.md @@ -127,8 +127,6 @@ class Solution: if record[i] != 0: #record数组如果有的元素不为零0,说明字符串s和t 一定是谁多了字符或者谁少了字符。 return False - #如果有一个元素不为零,则可以判断字符串s和t不是字母异位词 - break return True ``` diff --git a/problems/0309.最佳买卖股票时机含冷冻期.md b/problems/0309.最佳买卖股票时机含冷冻期.md index 229fc636..3791a71f 100644 --- a/problems/0309.最佳买卖股票时机含冷冻期.md +++ b/problems/0309.最佳买卖股票时机含冷冻期.md @@ -44,6 +44,8 @@ dp[i][j],第i天状态为j,所剩的最多现金为dp[i][j]。 * 状态三:今天卖出了股票 * 状态四:今天为冷冻期状态,但冷冻期状态不可持续,只有一天! +![](https://img-blog.csdnimg.cn/518d5baaf33f4b2698064f8efb42edbf.png) + j的状态为: * 0:状态一 @@ -57,7 +59,7 @@ j的状态为: **注意这里的每一个状态,例如状态一,是买入股票状态并不是说今天已经就买入股票,而是说保存买入股票的状态即:可能是前几天买入的,之后一直没操作,所以保持买入股票的状态**。 -2. 确定递推公式 +1. 确定递推公式 达到买入股票状态(状态一)即:dp[i][0],有两个具体操作: diff --git a/problems/0343.整数拆分.md b/problems/0343.整数拆分.md index dd03937f..a4d532fd 100644 --- a/problems/0343.整数拆分.md +++ b/problems/0343.整数拆分.md @@ -335,5 +335,22 @@ int integerBreak(int n){ } ``` +### Scala + +```scala +object Solution { + def integerBreak(n: Int): Int = { + var dp = new Array[Int](n + 1) + dp(2) = 1 + for (i <- 3 to n) { + for (j <- 1 until i - 1) { + dp(i) = math.max(dp(i), math.max(j * (i - j), j * dp(i - j))) + } + } + dp(n) + } +} +``` + -----------------------
diff --git a/problems/0347.前K个高频元素.md b/problems/0347.前K个高频元素.md index 0c978b2a..430dcea1 100644 --- a/problems/0347.前K个高频元素.md +++ b/problems/0347.前K个高频元素.md @@ -371,6 +371,44 @@ function topKFrequent(nums: number[], k: number): number[] { }; ``` +C#: +```csharp + public int[] TopKFrequent(int[] nums, int k) { + //哈希表-标权重 + Dictionary dic = new(); + for(int i = 0; i < nums.Length; i++){ + if(dic.ContainsKey(nums[i])){ + dic[nums[i]]++; + }else{ + dic.Add(nums[i], 1); + } + } + //优先队列-从小到大排列 + PriorityQueue pq = new(); + foreach(var num in dic){ + pq.Enqueue(num.Key, num.Value); + if(pq.Count > k){ + pq.Dequeue(); + } + } + + // //Stack-倒置 + // Stack res = new(); + // while(pq.Count > 0){ + // res.Push(pq.Dequeue()); + // } + // return res.ToArray(); + + //数组倒装 + int[] res = new int[k]; + for(int i = k - 1; i >= 0; i--){ + res[i] = pq.Dequeue(); + } + return res; + } + +``` + Scala: 解法一: 优先级队列 @@ -413,6 +451,7 @@ object Solution { .map(_._1) } } + ``` ----------------------- diff --git a/problems/0406.根据身高重建队列.md b/problems/0406.根据身高重建队列.md index 879820ea..827b7481 100644 --- a/problems/0406.根据身高重建队列.md +++ b/problems/0406.根据身高重建队列.md @@ -354,8 +354,27 @@ function reconstructQueue(people: number[][]): number[][] { }; ``` +### Scala +```scala +object Solution { + import scala.collection.mutable + def reconstructQueue(people: Array[Array[Int]]): Array[Array[Int]] = { + val person = people.sortWith((a, b) => { + if (a(0) == b(0)) a(1) < b(1) + else a(0) > b(0) + }) + var que = mutable.ArrayBuffer[Array[Int]]() + + for (per <- person) { + que.insert(per(1), per) + } + + que.toArray + } +} +``` ----------------------- diff --git a/problems/0416.分割等和子集.md b/problems/0416.分割等和子集.md index 5419fc1f..83b267ac 100644 --- a/problems/0416.分割等和子集.md +++ b/problems/0416.分割等和子集.md @@ -183,7 +183,7 @@ public: ## 其他语言版本 -Java: +### Java: ```Java class Solution { public boolean canPartition(int[] nums) { @@ -316,7 +316,7 @@ class Solution { } } ``` -Python: +### Python: ```python class Solution: def canPartition(self, nums: List[int]) -> bool: @@ -329,7 +329,7 @@ class Solution: dp[j] = max(dp[j], dp[j - nums[i]] + nums[i]) return target == dp[target] ``` -Go: +### Go: ```go // 分割等和子集 动态规划 // 时间复杂度O(n^2) 空间复杂度O(n) @@ -397,7 +397,7 @@ func canPartition(nums []int) bool { } ``` -javaScript: +### javaScript: ```js var canPartition = function(nums) { @@ -417,27 +417,11 @@ var canPartition = function(nums) { ``` -TypeScript: - -```ts -function canPartition(nums: number[]): boolean { - const sum: number = nums.reduce((a: number, b: number): number => a + b); - if (sum % 2 === 1) return false; - const target: number = sum / 2; - // dp[j]表示容量(总数和)为j的背包所能装下的数(下标[0, i]之间任意取)的总和(<= 容量)的最大值 - const dp: number[] = new Array(target + 1).fill(0); - const n: number = nums.length; - for (let i: number = 0; i < n; i++) { - for (let j: number = target; j >= nums[i]; j--) { - dp[j] = Math.max(dp[j], dp[j - nums[i]] + nums[i]); - } - } - return dp[target] === target; -}; -``` -C: + +### C: + 二维dp: ```c /** @@ -538,7 +522,7 @@ bool canPartition(int* nums, int numsSize){ } ``` -TypeScript: +### TypeScript: > 一维数组,简洁 @@ -593,7 +577,50 @@ function canPartition(nums: number[]): boolean { }; ``` +### Scala +滚动数组: +```scala +object Solution { + def canPartition(nums: Array[Int]): Boolean = { + var sum = nums.sum + if (sum % 2 != 0) return false + var half = sum / 2 + var dp = new Array[Int](half + 1) + + // 遍历 + for (i <- 0 until nums.length; j <- half to nums(i) by -1) { + dp(j) = math.max(dp(j), dp(j - nums(i)) + nums(i)) + } + + if (dp(half) == half) true else false + } +} +``` + +二维数组: +```scala +object Solution { + def canPartition(nums: Array[Int]): Boolean = { + var sum = nums.sum + if (sum % 2 != 0) return false + var half = sum / 2 + var dp = Array.ofDim[Int](nums.length, half + 1) + + // 初始化 + for (j <- nums(0) to half) dp(0)(j) = nums(0) + + // 遍历 + for (i <- 1 until nums.length; j <- 1 to half) { + if (j - nums(i) >= 0) dp(i)(j) = nums(i) + dp(i - 1)(j - nums(i)) + dp(i)(j) = math.max(dp(i)(j), dp(i - 1)(j)) + } + + // 如果等于half就返回ture,否则返回false + if (dp(nums.length - 1)(half) == half) true else false + } +} +``` -----------------------
diff --git a/problems/0435.无重叠区间.md b/problems/0435.无重叠区间.md index f1e259ae..3aa4eeb6 100644 --- a/problems/0435.无重叠区间.md +++ b/problems/0435.无重叠区间.md @@ -352,7 +352,27 @@ function eraseOverlapIntervals(intervals: number[][]): number { }; ``` +### Scala +```scala +object Solution { + def eraseOverlapIntervals(intervals: Array[Array[Int]]): Int = { + var result = 0 + var interval = intervals.sortWith((a, b) => { + a(1) < b(1) + }) + var edge = Int.MinValue + for (i <- 0 until interval.length) { + if (edge <= interval(i)(0)) { + edge = interval(i)(1) + } else { + result += 1 + } + } + result + } +} +``` diff --git a/problems/0450.删除二叉搜索树中的节点.md b/problems/0450.删除二叉搜索树中的节点.md index 3bc8369c..2d6d4ef2 100644 --- a/problems/0450.删除二叉搜索树中的节点.md +++ b/problems/0450.删除二叉搜索树中的节点.md @@ -322,33 +322,25 @@ class Solution { ```python class Solution: - def deleteNode(self, root: TreeNode, key: int) -> TreeNode: - if not root: return root #第一种情况:没找到删除的节点,遍历到空节点直接返回了 - if root.val == key: - if not root.left and not root.right: #第二种情况:左右孩子都为空(叶子节点),直接删除节点, 返回NULL为根节点 - del root - return None - if not root.left and root.right: #第三种情况:其左孩子为空,右孩子不为空,删除节点,右孩子补位 ,返回右孩子为根节点 - tmp = root - root = root.right - del tmp - return root - if root.left and not root.right: #第四种情况:其右孩子为空,左孩子不为空,删除节点,左孩子补位,返回左孩子为根节点 - tmp = root - root = root.left - del tmp - return root - else: #第五种情况:左右孩子节点都不为空,则将删除节点的左子树放到删除节点的右子树的最左面节点的左孩子的位置 - v = root.right - while v.left: - v = v.left - v.left = root.left - tmp = root - root = root.right - del tmp - return root - if root.val > key: root.left = self.deleteNode(root.left,key) #左递归 - if root.val < key: root.right = self.deleteNode(root.right,key) #右递归 + def deleteNode(self, root: Optional[TreeNode], key: int) -> Optional[TreeNode]: + if not root : return None # 节点为空,返回 + if root.val < key : + root.right = self.deleteNode(root.right, key) + elif root.val > key : + root.left = self.deleteNode(root.left, key) + else: + # 当前节点的左子树为空,返回当前的右子树 + if not root.left : return root.right + # 当前节点的右子树为空,返回当前的左子树 + if not root.right: return root.left + # 左右子树都不为空,找到右孩子的最左节点 记为p + node = root.right + while node.left : + node = node.left + # 将当前节点的左子树挂在p的左孩子上 + node.left = root.left + # 当前节点的右子树替换掉当前节点,完成当前节点的删除 + root = root.right return root ``` diff --git a/problems/0452.用最少数量的箭引爆气球.md b/problems/0452.用最少数量的箭引爆气球.md index 5b75e64e..7b5f387d 100644 --- a/problems/0452.用最少数量的箭引爆气球.md +++ b/problems/0452.用最少数量的箭引爆气球.md @@ -151,6 +151,7 @@ class Solution { //重叠气球的最小右边界 int leftmostRightBound = points[0][1]; //如果下一个气球的左边界大于最小右边界 + for(int i = 1; i < points.length; i++){ if (points[i][0] > leftmostRightBound ) { //增加一次射击 count++; @@ -299,5 +300,30 @@ impl Solution { } } ``` + +### Scala + +```scala +object Solution { + def findMinArrowShots(points: Array[Array[Int]]): Int = { + if (points.length == 0) return 0 + // 排序 + var point = points.sortWith((a, b) => { + a(0) < b(0) + }) + + var result = 1 // points不为空就至少需要一只箭 + for (i <- 1 until point.length) { + if (point(i)(0) > point(i - 1)(1)) { + result += 1 + } else { + point(i)(1) = math.min(point(i - 1)(1), point(i)(1)) + } + } + result // 返回结果 + } +} +``` + -----------------------
diff --git a/problems/0459.重复的子字符串.md b/problems/0459.重复的子字符串.md index f7898ae0..3d6df872 100644 --- a/problems/0459.重复的子字符串.md +++ b/problems/0459.重复的子字符串.md @@ -134,7 +134,7 @@ next 数组记录的就是最长相同前后缀 [字符串:KMP算法精讲](ht 数组长度为:len。 -如果len % (len - (next[len - 1] + 1)) == 0 ,则说明 (数组长度-最长相等前后缀的长度) 正好可以被 数组的长度整除,说明有该字符串有重复的子字符串。 +如果len % (len - (next[len - 1] + 1)) == 0 ,则说明数组的长度正好可以被 (数组长度-最长相等前后缀的长度) 整除 ,说明该字符串有重复的子字符串。 **数组长度减去最长相同前后缀的长度相当于是第一个周期的长度,也就是一个周期的长度,如果这个周期可以被整除,就说明整个数组就是这个周期的循环。** diff --git a/problems/0474.一和零.md b/problems/0474.一和零.md index a5018baf..8ebe303d 100644 --- a/problems/0474.一和零.md +++ b/problems/0474.一和零.md @@ -163,7 +163,7 @@ public: ## 其他语言版本 -Java: +### Java ```Java class Solution { public int findMaxForm(String[] strs, int m, int n) { @@ -192,7 +192,7 @@ class Solution { } ``` -Python: +### Python ```python class Solution: def findMaxForm(self, strs: List[str], m: int, n: int) -> int: @@ -208,7 +208,7 @@ class Solution: return dp[m][n] ``` -Go: +### Go ```go func findMaxForm(strs []string, m int, n int) int { // 定义数组 @@ -294,7 +294,7 @@ func getMax(a,b int)int{ } ``` -Javascript: +### Javascript ```javascript const findMaxForm = (strs, m, n) => { const dp = Array.from(Array(m+1), () => Array(n+1).fill(0)); @@ -323,7 +323,7 @@ const findMaxForm = (strs, m, n) => { }; ``` -TypeScript: +### TypeScript > 滚动数组,二维数组法 @@ -446,7 +446,80 @@ function isValidSubSet(strs: string[], m: number, n: number): boolean { } ``` +### Scala +背包: +```scala +object Solution { + def findMaxForm(strs: Array[String], m: Int, n: Int): Int = { + var dp = Array.ofDim[Int](m + 1, n + 1) + + var (oneNum, zeroNum) = (0, 0) + + for (str <- strs) { + oneNum = 0 + zeroNum = 0 + for (i <- str.indices) { + if (str(i) == '0') zeroNum += 1 + else oneNum += 1 + } + + for (i <- m to zeroNum by -1) { + for (j <- n to oneNum by -1) { + dp(i)(j) = math.max(dp(i)(j), dp(i - zeroNum)(j - oneNum) + 1) + } + } + } + + dp(m)(n) + } +} +``` + +回溯法(超时): +```scala +object Solution { + import scala.collection.mutable + + var res = Int.MinValue + + def test(str: String): (Int, Int) = { + var (zero, one) = (0, 0) + for (i <- str.indices) { + if (str(i) == '1') one += 1 + else zero += 1 + } + (zero, one) + } + + def travsel(strs: Array[String], path: mutable.ArrayBuffer[String], m: Int, n: Int, startIndex: Int): Unit = { + if (startIndex > strs.length) { + return + } + + res = math.max(res, path.length) + + for (i <- startIndex until strs.length) { + + var (zero, one) = test(strs(i)) + + // 如果0的个数小于m,1的个数小于n,则可以回溯 + if (zero <= m && one <= n) { + path.append(strs(i)) + travsel(strs, path, m - zero, n - one, i + 1) + path.remove(path.length - 1) + } + } + } + + def findMaxForm(strs: Array[String], m: Int, n: Int): Int = { + res = Int.MinValue + var path = mutable.ArrayBuffer[String]() + travsel(strs, path, m, n, 0) + res + } +} +``` -----------------------
diff --git a/problems/0494.目标和.md b/problems/0494.目标和.md index cc8a08e3..f2656d41 100644 --- a/problems/0494.目标和.md +++ b/problems/0494.目标和.md @@ -156,9 +156,9 @@ dp[j] 表示:填满j(包括j)这么大容积的包,有dp[j]种方法 有哪些来源可以推出dp[j]呢? -不考虑nums[i]的情况下,填满容量为j - nums[i]的背包,有dp[j - nums[i]]种方法。 +不考虑nums[i]的情况下,填满容量为j的背包,有dp[j]种方法。 -那么只要搞到nums[i]的话,凑成dp[j]就有dp[j - nums[i]] 种方法。 +那么考虑nums[i]的话(只要搞到nums[i]),凑成dp[j]就有dp[j - nums[i]] 种方法。 例如:dp[j],j 为5, @@ -251,7 +251,7 @@ dp[j] += dp[j - nums[i]]; ## 其他语言版本 -Java: +### Java ```java class Solution { public int findTargetSumWays(int[] nums, int target) { @@ -272,7 +272,7 @@ class Solution { } ``` -Python: +### Python ```python class Solution: def findTargetSumWays(self, nums: List[int], target: int) -> int: @@ -288,7 +288,7 @@ class Solution: return dp[bagSize] ``` -Go: +### Go ```go func findTargetSumWays(nums []int, target int) int { sum := 0 @@ -323,7 +323,7 @@ func abs(x int) int { } ``` -Javascript: +### Javascript ```javascript const findTargetSumWays = (nums, target) => { @@ -353,6 +353,8 @@ const findTargetSumWays = (nums, target) => { ``` +### TypeScript + TypeScript: ```ts @@ -375,7 +377,25 @@ function findTargetSumWays(nums: number[], target: number): number { }; ``` +### Scala +```scala +object Solution { + def findTargetSumWays(nums: Array[Int], target: Int): Int = { + var sum = nums.sum + if (math.abs(target) > sum) return 0 // 此时没有方案 + if ((sum + target) % 2 == 1) return 0 // 此时没有方案 + var bagSize = (sum + target) / 2 + var dp = new Array[Int](bagSize + 1) + dp(0) = 1 + for (i <- 0 until nums.length; j <- bagSize to nums(i) by -1) { + dp(j) += dp(j - nums(i)) + } + + dp(bagSize) + } +} +``` -----------------------
diff --git a/problems/0509.斐波那契数.md b/problems/0509.斐波那契数.md index 785d0125..0b53e698 100644 --- a/problems/0509.斐波那契数.md +++ b/problems/0509.斐波那契数.md @@ -263,7 +263,7 @@ var fib = function(n) { }; ``` -TypeScript +### TypeScript ```typescript function fib(n: number): number { @@ -342,5 +342,33 @@ pub fn fib(n: i32) -> i32 { return fib(n - 1) + fib(n - 2); } ``` + +### Scala + +动态规划: +```scala +object Solution { + def fib(n: Int): Int = { + if (n <= 1) return n + var dp = new Array[Int](n + 1) + dp(1) = 1 + for (i <- 2 to n) { + dp(i) = dp(i - 1) + dp(i - 2) + } + dp(n) + } +} +``` + +递归: +```scala +object Solution { + def fib(n: Int): Int = { + if (n <= 1) return n + fib(n - 1) + fib(n - 2) + } +} +``` + -----------------------
diff --git a/problems/0518.零钱兑换II.md b/problems/0518.零钱兑换II.md index 222a10d7..3abb9601 100644 --- a/problems/0518.零钱兑换II.md +++ b/problems/0518.零钱兑换II.md @@ -289,7 +289,22 @@ function change(amount: number, coins: number[]): number { }; ``` +Scala: +```scala +object Solution { + def change(amount: Int, coins: Array[Int]): Int = { + var dp = new Array[Int](amount + 1) + dp(0) = 1 + for (i <- 0 until coins.length) { + for (j <- coins(i) to amount) { + dp(j) += dp(j - coins(i)) + } + } + dp(amount) + } +} +``` -----------------------
diff --git a/problems/0541.反转字符串II.md b/problems/0541.反转字符串II.md index a8bf3804..26d0b89c 100644 --- a/problems/0541.反转字符串II.md +++ b/problems/0541.反转字符串II.md @@ -65,6 +65,9 @@ public: }; ``` + + + 那么我们也可以实现自己的reverse函数,其实和题目[344. 反转字符串](https://programmercarl.com/0344.反转字符串.html)道理是一样的。 下面我实现的reverse函数区间是左闭右闭区间,代码如下: @@ -94,7 +97,24 @@ public: ``` +另一种思路的解法 +```CPP +class Solution { +public: + string reverseStr(string s, int k) { + int n = s.size(),pos = 0; + while(pos < n){ + //剩余字符串大于等于k的情况 + if(pos + k < n) reverse(s.begin() + pos, s.begin() + pos + k); + //剩余字符串不足k的情况 + else reverse(s.begin() + pos,s.end()); + pos += 2 * k; + } + return s; + } +}; +``` diff --git a/problems/0583.两个字符串的删除操作.md b/problems/0583.两个字符串的删除操作.md index fc7e6f39..0e02e721 100644 --- a/problems/0583.两个字符串的删除操作.md +++ b/problems/0583.两个字符串的删除操作.md @@ -205,7 +205,7 @@ func min(a, b int) int { Javascript: ```javascript const minDistance = (word1, word2) => { - let dp = Array.from(Array(word1.length + 1), () => Array(word2.length+1).fill(0)); + let dp = Array.from(new Array(word1.length + 1), () => Array(word2.length+1).fill(0)); for(let i = 1; i <= word1.length; i++) { dp[i][0] = i; diff --git a/problems/0649.Dota2参议院.md b/problems/0649.Dota2参议院.md index f1b3be11..3b61a9fe 100644 --- a/problems/0649.Dota2参议院.md +++ b/problems/0649.Dota2参议院.md @@ -244,6 +244,44 @@ var predictPartyVictory = function(senateStr) { }; ``` +## TypeScript + +```typescript +function predictPartyVictory(senate: string): string { + // 数量差:Count(Radiant) - Count(Dire) + let deltaRDCnt: number = 0; + let hasR: boolean = true, + hasD: boolean = true; + const senateArr: string[] = senate.split(''); + while (hasR && hasD) { + hasR = false; + hasD = false; + for (let i = 0, length = senateArr.length; i < length; i++) { + if (senateArr[i] === 'R') { + if (deltaRDCnt < 0) { + senateArr[i] = ''; + } else { + hasR = true; + } + deltaRDCnt++; + } else if (senateArr[i] === 'D') { + if (deltaRDCnt > 0) { + senateArr[i] = ''; + } else { + hasD = true; + } + deltaRDCnt--; + } + } + } + return hasR ? 'Radiant' : 'Dire'; +}; +``` + + + + + -----------------------
diff --git a/problems/0674.最长连续递增序列.md b/problems/0674.最长连续递增序列.md index 5865a68d..7e4d0c19 100644 --- a/problems/0674.最长连续递增序列.md +++ b/problems/0674.最长连续递增序列.md @@ -300,7 +300,7 @@ Javascript: > 动态规划: ```javascript const findLengthOfLCIS = (nums) => { - let dp = Array(nums.length).fill(1); + let dp = new Array(nums.length).fill(1); for(let i = 0; i < nums.length - 1; i++) { diff --git a/problems/0714.买卖股票的最佳时机含手续费.md b/problems/0714.买卖股票的最佳时机含手续费.md index 7600c52c..824e7937 100644 --- a/problems/0714.买卖股票的最佳时机含手续费.md +++ b/problems/0714.买卖股票的最佳时机含手续费.md @@ -153,7 +153,7 @@ public: ## 其他语言版本 -Java: +### Java ```java // 贪心思路 class Solution { @@ -198,7 +198,7 @@ class Solution { // 动态规划 -Python: +### Python ```python class Solution: # 贪心思路 @@ -216,7 +216,7 @@ class Solution: # 贪心思路 return result ``` -Go: +### Go ```golang func maxProfit(prices []int, fee int) int { var minBuy int = prices[0] //第一天买入 @@ -241,7 +241,7 @@ func maxProfit(prices []int, fee int) int { return res } ``` -Javascript: +### Javascript ```Javascript // 贪心思路 var maxProfit = function(prices, fee) { @@ -293,7 +293,7 @@ var maxProfit = function(prices, fee) { }; ``` -TypeScript: +### TypeScript > 贪心 @@ -335,8 +335,28 @@ function maxProfit(prices: number[], fee: number): number { }; ``` +### Scala +贪心思路: +```scala +object Solution { + def maxProfit(prices: Array[Int], fee: Int): Int = { + var result = 0 + var minPrice = prices(0) + for (i <- 1 until prices.length) { + if (prices(i) < minPrice) { + minPrice = prices(i) // 比当前最小值还小 + } + if (prices(i) > minPrice + fee) { + result += prices(i) - minPrice - fee + minPrice = prices(i) - fee + } + } + result + } +} +``` -----------------------
diff --git a/problems/0738.单调递增的数字.md b/problems/0738.单调递增的数字.md index d2f041f5..6b7381f3 100644 --- a/problems/0738.单调递增的数字.md +++ b/problems/0738.单调递增的数字.md @@ -246,7 +246,37 @@ function monotoneIncreasingDigits(n: number): number { ``` +### Scala +直接转换为了整数数组: +```scala +object Solution { + import scala.collection.mutable + def monotoneIncreasingDigits(n: Int): Int = { + var digits = mutable.ArrayBuffer[Int]() + // 提取每位数字 + var temp = n // 因为 参数n 是不可变量所以需要赋值给一个可变量 + while (temp != 0) { + digits.append(temp % 10) + temp = temp / 10 + } + // 贪心 + var flag = -1 + for (i <- 0 until (digits.length - 1) if digits(i) < digits(i + 1)) { + flag = i + digits(i + 1) -= 1 + } + for (i <- 0 to flag) digits(i) = 9 + + // 拼接 + var res = 0 + for (i <- 0 until digits.length) { + res += digits(i) * math.pow(10, i).toInt + } + res + } +} +``` -----------------------
diff --git a/problems/0746.使用最小花费爬楼梯.md b/problems/0746.使用最小花费爬楼梯.md index 0006f7ac..92fb2920 100644 --- a/problems/0746.使用最小花费爬楼梯.md +++ b/problems/0746.使用最小花费爬楼梯.md @@ -323,5 +323,35 @@ int minCostClimbingStairs(int* cost, int costSize){ return dp[i-1] < dp[i-2] ? dp[i-1] : dp[i-2]; } ``` + +### Scala + +```scala +object Solution { + def minCostClimbingStairs(cost: Array[Int]): Int = { + var dp = new Array[Int](cost.length) + dp(0) = cost(0) + dp(1) = cost(1) + for (i <- 2 until cost.length) { + dp(i) = math.min(dp(i - 1), dp(i - 2)) + cost(i) + } + math.min(dp(cost.length - 1), dp(cost.length - 2)) + } +} +``` + +第二种思路: dp[i] 表示爬到第i-1层所需的最小花费,状态转移方程为: dp[i] = min(dp[i-1]+cost[i-1],dp[i-2]+cost[i-2]) +```scala +object Solution { + def minCostClimbingStairs(cost: Array[Int]): Int = { + var dp = new Array[Int](cost.length + 1) + for (i <- 2 until cost.length + 1) { + dp(i) = math.min(dp(i - 1) + cost(i - 1), dp(i - 2) + cost(i - 2)) + } + dp(cost.length) + } +} +``` + -----------------------
diff --git a/problems/0763.划分字母区间.md b/problems/0763.划分字母区间.md index eb21e42f..ecf064d3 100644 --- a/problems/0763.划分字母区间.md +++ b/problems/0763.划分字母区间.md @@ -317,7 +317,31 @@ function partitionLabels(s: string): number[] { }; ``` +### Scala +```scala +object Solution { + import scala.collection.mutable + def partitionLabels(s: String): List[Int] = { + var hash = new Array[Int](26) + for (i <- s.indices) { + hash(s(i) - 'a') = i + } + + var res = mutable.ListBuffer[Int]() + var (left, right) = (0, 0) + for (i <- s.indices) { + right = math.max(hash(s(i) - 'a'), right) + if (i == right) { + res.append(right - left + 1) + left = i + 1 + } + } + + res.toList + } +} +``` ----------------------- diff --git a/problems/0860.柠檬水找零.md b/problems/0860.柠檬水找零.md index f5785a91..42e8b19a 100644 --- a/problems/0860.柠檬水找零.md +++ b/problems/0860.柠檬水找零.md @@ -328,6 +328,37 @@ function lemonadeChange(bills: number[]): boolean { ``` +### Scala + +```scala +object Solution { + def lemonadeChange(bills: Array[Int]): Boolean = { + var fiveNum = 0 + var tenNum = 0 + + for (i <- bills) { + if (i == 5) fiveNum += 1 + if (i == 10) { + if (fiveNum <= 0) return false + tenNum += 1 + fiveNum -= 1 + } + if (i == 20) { + if (fiveNum > 0 && tenNum > 0) { + tenNum -= 1 + fiveNum -= 1 + } else if (fiveNum >= 3) { + fiveNum -= 3 + } else { + return false + } + } + } + true + } +} +``` + -----------------------
diff --git a/problems/0941.有效的山脉数组.md b/problems/0941.有效的山脉数组.md index 310dd35a..fb7935a8 100644 --- a/problems/0941.有效的山脉数组.md +++ b/problems/0941.有效的山脉数组.md @@ -177,7 +177,24 @@ function validMountainArray(arr: number[]): boolean { }; ``` +## C# +```csharp +public class Solution { + public bool ValidMountainArray(int[] arr) { + if (arr.Length < 3) return false; + + int left = 0; + int right = arr.Length - 1; + + while (left + 1< arr.Length && arr[left] < arr[left + 1]) left ++; + while (right > 0 && arr[right] < arr[right - 1]) right --; + if (left == right && left != 0 && right != arr.Length - 1) return true; + + return false; + } +} +``` ----------------------- diff --git a/problems/0968.监控二叉树.md b/problems/0968.监控二叉树.md index 0aa04a02..b17ff080 100644 --- a/problems/0968.监控二叉树.md +++ b/problems/0968.监控二叉树.md @@ -544,5 +544,40 @@ int minCameraCover(struct TreeNode* root){ } ``` +### Scala + +```scala +object Solution { + def minCameraCover(root: TreeNode): Int = { + var result = 0 + def traversal(cur: TreeNode): Int = { + // 空节点,该节点有覆盖 + if (cur == null) return 2 + var left = traversal(cur.left) + var right = traversal(cur.right) + // 情况1,左右节点都有覆盖 + if (left == 2 && right == 2) { + return 0 + } + // 情况2 + if (left == 0 || right == 0) { + result += 1 + return 1 + } + // 情况3 + if (left == 1 || right == 1) { + return 2 + } + -1 + } + + if (traversal(root) == 0) { + result += 1 + } + result + } +} +``` + -----------------------
diff --git a/problems/1047.删除字符串中的所有相邻重复项.md b/problems/1047.删除字符串中的所有相邻重复项.md index 9691c75b..2c51bbb3 100644 --- a/problems/1047.删除字符串中的所有相邻重复项.md +++ b/problems/1047.删除字符串中的所有相邻重复项.md @@ -376,6 +376,25 @@ func removeDuplicates(_ s: String) -> String { ``` +C#: +```csharp +public string RemoveDuplicates(string s) { + //拿字符串直接作为栈,省去了栈还要转为字符串的操作 + StringBuilder res = new StringBuilder(); + + foreach(char c in s){ + if(res.Length > 0 && res[res.Length-1] == c){ + res.Remove(res.Length-1, 1); + }else{ + res.Append(c); + } + } + + return res.ToString(); + } +``` + + PHP: ```php class Solution { diff --git a/problems/1049.最后一块石头的重量II.md b/problems/1049.最后一块石头的重量II.md index 46777642..b6a674aa 100644 --- a/problems/1049.最后一块石头的重量II.md +++ b/problems/1049.最后一块石头的重量II.md @@ -3,7 +3,6 @@

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

-# 动态规划:最后一块石头的重量 II ## 1049. 最后一块石头的重量 II @@ -152,7 +151,7 @@ public: ## 其他语言版本 -Java: +### Java: 一维数组版本 ```Java @@ -212,7 +211,7 @@ class Solution { ``` -Python: +### Python: ```python class Solution: def lastStoneWeightII(self, stones: List[int]) -> int: @@ -225,7 +224,7 @@ class Solution: return sumweight - 2 * dp[target] ``` -Go: +### Go: ```go func lastStoneWeightII(stones []int) int { // 15001 = 30 * 1000 /2 +1 @@ -254,7 +253,7 @@ func max(a, b int) int { } ``` -JavaScript版本 +### JavaScript ```javascript /** @@ -277,7 +276,7 @@ var lastStoneWeightII = function (stones) { }; ``` -C版本 +### C ```c #define MAX(a, b) (((a) > (b)) ? (a) : (b)) @@ -308,8 +307,7 @@ int lastStoneWeightII(int* stones, int stonesSize){ } ``` - -TypeScript版本 +### TypeScript: ```ts function lastStoneWeightII(stones: number[]): number { @@ -327,7 +325,47 @@ function lastStoneWeightII(stones: number[]): number { }; ``` +### Scala +滚动数组: +```scala +object Solution { + def lastStoneWeightII(stones: Array[Int]): Int = { + var sum = stones.sum + var half = sum / 2 + var dp = new Array[Int](half + 1) + + // 遍历 + for (i <- 0 until stones.length; j <- half to stones(i) by -1) { + dp(j) = math.max(dp(j), dp(j - stones(i)) + stones(i)) + } + + sum - 2 * dp(half) + } +} +``` + +二维数组: +```scala +object Solution { + def lastStoneWeightII(stones: Array[Int]): Int = { + var sum = stones.sum + var half = sum / 2 + var dp = Array.ofDim[Int](stones.length, half + 1) + + // 初始化 + for (j <- stones(0) to half) dp(0)(j) = stones(0) + + // 遍历 + for (i <- 1 until stones.length; j <- 1 to half) { + if (j - stones(i) >= 0) dp(i)(j) = stones(i) + dp(i - 1)(j - stones(i)) + dp(i)(j) = math.max(dp(i)(j), dp(i - 1)(j)) + } + + sum - 2 * dp(stones.length - 1)(half) + } +} +``` diff --git a/problems/1221.分割平衡字符串.md b/problems/1221.分割平衡字符串.md index 08d4fee7..857df7ef 100644 --- a/problems/1221.分割平衡字符串.md +++ b/problems/1221.分割平衡字符串.md @@ -108,11 +108,38 @@ class Solution { ### Python ```python +class Solution: + def balancedStringSplit(self, s: str) -> int: + diff = 0 #右左差值 + ans = 0 + for c in s: + if c == "L": + diff -= 1 + else: + diff += 1 + if tilt == 0: + ans += 1 + return ans ``` ### Go ```go +func balancedStringSplit(s string) int { + diff := 0 // 右左差值 + ans := 0 + for _, c := range s { + if c == 'L' { + diff-- + }else { + diff++ + } + if diff == 0 { + ans++ + } + } + return ans +} ``` ### JavaScript diff --git a/problems/回溯算法去重问题的另一种写法.md b/problems/回溯算法去重问题的另一种写法.md index cbfe046a..c7bf24bc 100644 --- a/problems/回溯算法去重问题的另一种写法.md +++ b/problems/回溯算法去重问题的另一种写法.md @@ -418,7 +418,7 @@ function combinationSum2(candidates, target) { **47. 全排列 II** -```javaescript +```javascript function permuteUnique(nums) { const resArr = []; const usedArr = []; diff --git a/problems/背包理论基础01背包-1.md b/problems/背包理论基础01背包-1.md index e24824b9..c2e93eb4 100644 --- a/problems/背包理论基础01背包-1.md +++ b/problems/背包理论基础01背包-1.md @@ -502,7 +502,41 @@ const size = 4; console.log(testWeightBagProblem(weight, value, size)); ``` +### Scala +```scala +object Solution { + // 01背包 + def test_2_wei_bag_problem1(): Unit = { + var weight = Array[Int](1, 3, 4) + var value = Array[Int](15, 20, 30) + var baseweight = 4 + + // 二维数组 + var dp = Array.ofDim[Int](weight.length, baseweight + 1) + + // 初始化 + for (j <- weight(0) to baseweight) { + dp(0)(j) = value(0) + } + + // 遍历 + for (i <- 1 until weight.length; j <- 1 to baseweight) { + if (j - weight(i) >= 0) dp(i)(j) = dp(i - 1)(j - weight(i)) + value(i) + dp(i)(j) = math.max(dp(i)(j), dp(i - 1)(j)) + } + + // 打印数组 + dp.foreach(x => println("[" + x.mkString(",") + "]")) + + dp(weight.length - 1)(baseweight) // 最终返回 + } + + def main(args: Array[String]): Unit = { + test_2_wei_bag_problem1() + } +} +``` -----------------------
diff --git a/problems/背包理论基础01背包-2.md b/problems/背包理论基础01背包-2.md index b66b74a6..81e61be4 100644 --- a/problems/背包理论基础01背包-2.md +++ b/problems/背包理论基础01背包-2.md @@ -375,7 +375,33 @@ console.log(testWeightBagProblem(weight, value, size)); ``` +### Scala +```scala +object Solution { + // 滚动数组 + def test_1_wei_bag_problem(): Unit = { + var weight = Array[Int](1, 3, 4) + var value = Array[Int](15, 20, 30) + var baseweight = 4 + + // dp数组 + var dp = new Array[Int](baseweight + 1) + + // 遍历 + for (i <- 0 until weight.length; j <- baseweight to weight(i) by -1) { + dp(j) = math.max(dp(j), dp(j - weight(i)) + value(i)) + } + + // 打印数组 + println("[" + dp.mkString(",") + "]") + } + + def main(args: Array[String]): Unit = { + test_1_wei_bag_problem() + } +} +``` -----------------------
diff --git a/problems/背包问题理论基础完全背包.md b/problems/背包问题理论基础完全背包.md index 54e772e0..fc4609a6 100644 --- a/problems/背包问题理论基础完全背包.md +++ b/problems/背包问题理论基础完全背包.md @@ -359,7 +359,27 @@ function test_CompletePack(): void { test_CompletePack(); ``` +Scala: +```scala +// 先遍历物品,再遍历背包容量 +object Solution { + def test_CompletePack() { + var weight = Array[Int](1, 3, 4) + var value = Array[Int](15, 20, 30) + var baseweight = 4 + + var dp = new Array[Int](baseweight + 1) + + for (i <- 0 until weight.length) { + for (j <- weight(i) to baseweight) { + dp(j) = math.max(dp(j), dp(j - weight(i)) + value(i)) + } + } + dp(baseweight) + } +} +``` -----------------------