diff --git a/problems/0001.两数之和.md b/problems/0001.两数之和.md index 459a66ad..6969c2e2 100644 --- a/problems/0001.两数之和.md +++ b/problems/0001.两数之和.md @@ -274,6 +274,30 @@ class Solution { } } ``` + +Scala: +```scala +object Solution { + // 导入包 + import scala.collection.mutable + def twoSum(nums: Array[Int], target: Int): Array[Int] = { + // key存储值,value存储下标 + val map = new mutable.HashMap[Int, Int]() + for (i <- nums.indices) { + val tmp = target - nums(i) // 计算差值 + // 如果这个差值存在于map,则说明找到了结果 + if (map.contains(tmp)) { + return Array(map.get(tmp).get, i) + } + // 如果不包含把当前值与其下标放到map + map.put(nums(i), i) + } + // 如果没有找到直接返回一个空的数组,return关键字可以省略 + new Array[Int](2) + } +} +``` + C#: ```csharp public class Solution { @@ -293,5 +317,6 @@ public class Solution { } ``` + -----------------------
diff --git a/problems/0015.三数之和.md b/problems/0015.三数之和.md index cc184c87..1764d244 100644 --- a/problems/0015.三数之和.md +++ b/problems/0015.三数之和.md @@ -616,6 +616,49 @@ public class Solution } } ``` +Scala: +```scala +object Solution { + // 导包 + import scala.collection.mutable.ListBuffer + import scala.util.control.Breaks.{break, breakable} + def threeSum(nums: Array[Int]): List[List[Int]] = { + // 定义结果集,最后需要转换为List + val res = ListBuffer[List[Int]]() + val nums_tmp = nums.sorted // 对nums进行排序 + for (i <- nums_tmp.indices) { + // 如果要排的第一个数字大于0,直接返回结果 + if (nums_tmp(i) > 0) { + return res.toList + } + // 如果i大于0并且和前一个数字重复,则跳过本次循环,相当于continue + breakable { + if (i > 0 && nums_tmp(i) == nums_tmp(i - 1)) { + break + } else { + var left = i + 1 + var right = nums_tmp.length - 1 + while (left < right) { + var sum = nums_tmp(i) + nums_tmp(left) + nums_tmp(right) // 求三数之和 + if (sum < 0) left += 1 + else if (sum > 0) right -= 1 + else { + res += List(nums_tmp(i), nums_tmp(left), nums_tmp(right)) // 如果等于0 添加进结果集 + // 为了避免重复,对left和right进行移动 + while (left < right && nums_tmp(left) == nums_tmp(left + 1)) left += 1 + while (left < right && nums_tmp(right) == nums_tmp(right - 1)) right -= 1 + left += 1 + right -= 1 + } + } + } + } + } + // 最终返回需要转换为List,return关键字可以省略 + res.toList + } +} +``` -----------------------
diff --git a/problems/0018.四数之和.md b/problems/0018.四数之和.md index ee70cb69..6cbd40c2 100644 --- a/problems/0018.四数之和.md +++ b/problems/0018.四数之和.md @@ -522,6 +522,49 @@ public class Solution } } ``` - +Scala: +```scala +object Solution { + // 导包 + import scala.collection.mutable.ListBuffer + import scala.util.control.Breaks.{break, breakable} + def fourSum(nums: Array[Int], target: Int): List[List[Int]] = { + val res = ListBuffer[List[Int]]() + val nums_tmp = nums.sorted // 先排序 + for (i <- nums_tmp.indices) { + breakable { + if (i > 0 && nums_tmp(i) == nums_tmp(i - 1)) { + break // 如果该值和上次的值相同,跳过本次循环,相当于continue + } else { + for (j <- i + 1 until nums_tmp.length) { + breakable { + if (j > i + 1 && nums_tmp(j) == nums_tmp(j - 1)) { + break // 同上 + } else { + // 双指针 + var (left, right) = (j + 1, nums_tmp.length - 1) + while (left < right) { + var sum = nums_tmp(i) + nums_tmp(j) + nums_tmp(left) + nums_tmp(right) + if (sum == target) { + // 满足要求,直接加入到集合里面去 + res += List(nums_tmp(i), nums_tmp(j), nums_tmp(left), nums_tmp(right)) + while (left < right && nums_tmp(left) == nums_tmp(left + 1)) left += 1 + while (left < right && nums_tmp(right) == nums_tmp(right - 1)) right -= 1 + left += 1 + right -= 1 + } else if (sum < target) left += 1 + else right -= 1 + } + } + } + } + } + } + } + // 最终返回的res要转换为List,return关键字可以省略 + res.toList + } +} +``` -----------------------
diff --git a/problems/0020.有效的括号.md b/problems/0020.有效的括号.md index 7bb7f746..a0df0d07 100644 --- a/problems/0020.有效的括号.md +++ b/problems/0020.有效的括号.md @@ -400,6 +400,27 @@ bool isValid(char * s){ return !stackTop; } ``` - +Scala: +```scala +object Solution { + import scala.collection.mutable + def isValid(s: String): Boolean = { + if(s.length % 2 != 0) return false // 如果字符串长度是奇数直接返回false + val stack = mutable.Stack[Char]() + // 循环遍历字符串 + for (i <- s.indices) { + val c = s(i) + if (c == '(' || c == '[' || c == '{') stack.push(c) + else if(stack.isEmpty) return false // 如果没有(、[、{则直接返回false + // 以下三种情况,不满足则直接返回false + else if(c==')' && stack.pop() != '(') return false + else if(c==']' && stack.pop() != '[') return false + else if(c=='}' && stack.pop() != '{') return false + } + // 如果为空则正确匹配,否则还有余孽就不匹配 + stack.isEmpty + } +} +``` -----------------------
diff --git a/problems/0028.实现strStr.md b/problems/0028.实现strStr.md index d67e5f70..1cdd5292 100644 --- a/problems/0028.实现strStr.md +++ b/problems/0028.实现strStr.md @@ -1166,5 +1166,80 @@ func strStr(_ haystack: String, _ needle: String) -> Int { ``` +PHP: + +> 前缀表统一减一 +```php +function strStr($haystack, $needle) { + if (strlen($needle) == 0) return 0; + $next= []; + $this->getNext($next,$needle); + + $j = -1; + for ($i = 0;$i < strlen($haystack); $i++) { // 注意i就从0开始 + while($j >= 0 && $haystack[$i] != $needle[$j + 1]) { + $j = $next[$j]; + } + if ($haystack[$i] == $needle[$j + 1]) { + $j++; + } + if ($j == (strlen($needle) - 1) ) { + return ($i - strlen($needle) + 1); + } + } + return -1; +} + +function getNext(&$next, $s){ + $j = -1; + $next[0] = $j; + for($i = 1; $i < strlen($s); $i++) { // 注意i从1开始 + while ($j >= 0 && $s[$i] != $s[$j + 1]) { + $j = $next[$j]; + } + if ($s[$i] == $s[$j + 1]) { + $j++; + } + $next[$i] = $j; + } +} +``` + +> 前缀表统一不减一 +```php +function strStr($haystack, $needle) { + if (strlen($needle) == 0) return 0; + $next= []; + $this->getNext($next,$needle); + + $j = 0; + for ($i = 0;$i < strlen($haystack); $i++) { // 注意i就从0开始 + while($j > 0 && $haystack[$i] != $needle[$j]) { + $j = $next[$j-1]; + } + if ($haystack[$i] == $needle[$j]) { + $j++; + } + if ($j == strlen($needle)) { + return ($i - strlen($needle) + 1); + } + } + return -1; +} + +function getNext(&$next, $s){ + $j = 0; + $next[0] = $j; + for($i = 1; $i < strlen($s); $i++) { // 注意i从1开始 + while ($j > 0 && $s[$i] != $s[$j]) { + $j = $next[$j-1]; + } + if ($s[$i] == $s[$j]) { + $j++; + } + $next[$i] = $j; + } +} +``` -----------------------
diff --git a/problems/0056.合并区间.md b/problems/0056.合并区间.md index 92b66473..e444a221 100644 --- a/problems/0056.合并区间.md +++ b/problems/0056.合并区间.md @@ -96,7 +96,7 @@ public: vector> merge(vector>& intervals) { vector> result; if (intervals.size() == 0) return result; - // 排序的参数使用了lamda表达式 + // 排序的参数使用了lambda表达式 sort(intervals.begin(), intervals.end(), [](const vector& a, const vector& b){return a[0] < b[0];}); result.push_back(intervals[0]); diff --git a/problems/0063.不同路径II.md b/problems/0063.不同路径II.md index d09ea0e6..59c60156 100644 --- a/problems/0063.不同路径II.md +++ b/problems/0063.不同路径II.md @@ -66,7 +66,7 @@ dp[i][j] :表示从(0 ,0)出发,到(i, j) 有dp[i][j]条不同的路 所以代码为: -``` +```cpp if (obstacleGrid[i][j] == 0) { // 当(i, j)没有障碍的时候,再推导dp[i][j] dp[i][j] = dp[i - 1][j] + dp[i][j - 1]; } @@ -76,7 +76,7 @@ if (obstacleGrid[i][j] == 0) { // 当(i, j)没有障碍的时候,再推导dp[i 在[62.不同路径](https://programmercarl.com/0062.不同路径.html)不同路径中我们给出如下的初始化: -``` +```cpp vector> dp(m, vector(n, 0)); // 初始值为0 for (int i = 0; i < m; i++) dp[i][0] = 1; for (int j = 0; j < n; j++) dp[0][j] = 1; @@ -138,6 +138,8 @@ public: int uniquePathsWithObstacles(vector>& obstacleGrid) { int m = obstacleGrid.size(); int n = obstacleGrid[0].size(); + if (obstacleGrid[m - 1][n - 1] == 1 || obstacleGrid[0][0] == 1) //如果在起点或终点出现了障碍,直接返回0 + return 0; vector> dp(m, vector(n, 0)); for (int i = 0; i < m && obstacleGrid[i][0] == 0; i++) dp[i][0] = 1; for (int j = 0; j < n && obstacleGrid[0][j] == 0; j++) dp[0][j] = 1; diff --git a/problems/0102.二叉树的层序遍历.md b/problems/0102.二叉树的层序遍历.md index 5f69f53d..1743243d 100644 --- a/problems/0102.二叉树的层序遍历.md +++ b/problems/0102.二叉树的层序遍历.md @@ -319,6 +319,36 @@ func levelOrder(_ root: TreeNode?) -> [[Int]] { } ``` +Rust: + +```rust +pub fn level_order(root: Option>>) -> Vec> { + let mut ans = Vec::new(); + let mut stack = Vec::new(); + if root.is_none(){ + return ans; + } + stack.push(root.unwrap()); + while stack.is_empty()!= true{ + let num = stack.len(); + let mut level = Vec::new(); + for _i in 0..num{ + let tmp = stack.remove(0); + level.push(tmp.borrow_mut().val); + if tmp.borrow_mut().left.is_some(){ + stack.push(tmp.borrow_mut().left.take().unwrap()); + } + if tmp.borrow_mut().right.is_some(){ + stack.push(tmp.borrow_mut().right.take().unwrap()); + } + } + ans.push(level); + } + ans +} +``` + + **此时我们就掌握了二叉树的层序遍历了,那么如下九道力扣上的题目,只需要修改模板的两三行代码(不能再多了),便可打倒!** @@ -548,6 +578,35 @@ func levelOrderBottom(_ root: TreeNode?) -> [[Int]] { } ``` +Rust: + +```rust +pub fn level_order(root: Option>>) -> Vec> { + let mut ans = Vec::new(); + let mut stack = Vec::new(); + if root.is_none(){ + return ans; + } + stack.push(root.unwrap()); + while stack.is_empty()!= true{ + let num = stack.len(); + let mut level = Vec::new(); + for _i in 0..num{ + let tmp = stack.remove(0); + level.push(tmp.borrow_mut().val); + if tmp.borrow_mut().left.is_some(){ + stack.push(tmp.borrow_mut().left.take().unwrap()); + } + if tmp.borrow_mut().right.is_some(){ + stack.push(tmp.borrow_mut().right.take().unwrap()); + } + } + ans.push(level); + } + ans +} +``` + # 199.二叉树的右视图 [力扣题目链接](https://leetcode-cn.com/problems/binary-tree-right-side-view/) diff --git a/problems/0104.二叉树的最大深度.md b/problems/0104.二叉树的最大深度.md index 2229a854..65a155fb 100644 --- a/problems/0104.二叉树的最大深度.md +++ b/problems/0104.二叉树的最大深度.md @@ -192,6 +192,33 @@ public: }; ``` +rust: +```rust +impl Solution { + pub fn max_depth(root: Option>>) -> i32 { + if root.is_none(){ + return 0; + } + let mut max_depth: i32 = 0; + let mut stack = vec![root.unwrap()]; + while !stack.is_empty() { + let num = stack.len(); + for _i in 0..num{ + let top = stack.remove(0); + if top.borrow_mut().left.is_some(){ + stack.push(top.borrow_mut().left.take().unwrap()); + } + if top.borrow_mut().right.is_some(){ + stack.push(top.borrow_mut().right.take().unwrap()); + } + } + max_depth+=1; + } + max_depth + } +``` + + 那么我们可以顺便解决一下n叉树的最大深度问题 # 559.n叉树的最大深度 diff --git a/problems/0111.二叉树的最小深度.md b/problems/0111.二叉树的最小深度.md index 224caa5e..b1331659 100644 --- a/problems/0111.二叉树的最小深度.md +++ b/problems/0111.二叉树的最小深度.md @@ -488,5 +488,69 @@ func minDepth(_ root: TreeNode?) -> Int { } ``` +rust: +```rust +impl Solution { + pub fn min_depth(root: Option>>) -> i32 { + return Solution::bfs(root) + } + + // 递归 + pub fn dfs(node: Option>>) -> i32{ + if node.is_none(){ + return 0; + } + let parent = node.unwrap(); + let left_child = parent.borrow_mut().left.take(); + let right_child = parent.borrow_mut().right.take(); + if left_child.is_none() && right_child.is_none(){ + return 1; + } + let mut min_depth = i32::MAX; + if left_child.is_some(){ + let left_depth = Solution::dfs(left_child); + if left_depth <= min_depth{ + min_depth = left_depth + } + } + if right_child.is_some(){ + let right_depth = Solution::dfs(right_child); + if right_depth <= min_depth{ + min_depth = right_depth + } + } + min_depth + 1 + + } + + // 迭代 + pub fn bfs(node: Option>>) -> i32{ + let mut min_depth = 0; + if node.is_none(){ + return min_depth + } + let mut stack = vec![node.unwrap()]; + while !stack.is_empty(){ + min_depth += 1; + let num = stack.len(); + for _i in 0..num{ + let top = stack.remove(0); + let left_child = top.borrow_mut().left.take(); + let right_child = top.borrow_mut().right.take(); + if left_child.is_none() && right_child.is_none(){ + return min_depth; + } + if left_child.is_some(){ + stack.push(left_child.unwrap()); + } + if right_child.is_some(){ + stack.push(right_child.unwrap()); + } + } + } + min_depth + } +``` + -----------------------
diff --git a/problems/0150.逆波兰表达式求值.md b/problems/0150.逆波兰表达式求值.md index 6ce7e2f9..5452c304 100644 --- a/problems/0150.逆波兰表达式求值.md +++ b/problems/0150.逆波兰表达式求值.md @@ -325,6 +325,33 @@ func evalRPN(_ tokens: [String]) -> Int { return stack.last! } ``` - +Scala: +```scala +object Solution { + import scala.collection.mutable + def evalRPN(tokens: Array[String]): Int = { + val stack = mutable.Stack[Int]() // 定义栈 + // 抽取运算操作,需要传递x,y,和一个函数 + def operator(x: Int, y: Int, f: (Int, Int) => Int): Int = f(x, y) + for (token <- tokens) { + // 模式匹配,匹配不同的操作符做什么样的运算 + token match { + // 最后一个参数 _+_,代表x+y,遵循Scala的函数至简原则,以下运算同理 + case "+" => stack.push(operator(stack.pop(), stack.pop(), _ + _)) + case "-" => stack.push(operator(stack.pop(), stack.pop(), -_ + _)) + case "*" => stack.push(operator(stack.pop(), stack.pop(), _ * _)) + case "/" => { + var pop1 = stack.pop() + var pop2 = stack.pop() + stack.push(operator(pop2, pop1, _ / _)) + } + case _ => stack.push(token.toInt) // 不是运算符就入栈 + } + } + // 最后返回栈顶,不需要加return关键字 + stack.pop() + } +} +``` -----------------------
diff --git a/problems/0151.翻转字符串里的单词.md b/problems/0151.翻转字符串里的单词.md index d03de421..0e25fc4d 100644 --- a/problems/0151.翻转字符串里的单词.md +++ b/problems/0151.翻转字符串里的单词.md @@ -758,7 +758,63 @@ func reverseWord(_ s: inout [Character]) { } ``` +Scala: +```scala +object Solution { + def reverseWords(s: String): String = { + var sb = removeSpace(s) // 移除多余的空格 + reverseString(sb, 0, sb.length - 1) // 翻转字符串 + reverseEachWord(sb) + sb.mkString + } + + // 移除多余的空格 + def removeSpace(s: String): Array[Char] = { + var start = 0 + var end = s.length - 1 + // 移除字符串前面的空格 + while (start < s.length && s(start) == ' ') start += 1 + // 移除字符串后面的空格 + while (end >= 0 && s(end) == ' ') end -= 1 + var sb = "" // String + // 当start小于等于end的时候,执行添加操作 + while (start <= end) { + var c = s(start) + // 当前字符不等于空,sb的最后一个字符不等于空的时候添加到sb + if (c != ' ' || sb(sb.length - 1) != ' ') { + sb ++= c.toString + } + start += 1 // 指针向右移动 + } + sb.toArray + } + + // 翻转字符串 + def reverseString(s: Array[Char], start: Int, end: Int): Unit = { + var (left, right) = (start, end) + while (left < right) { + var tmp = s(left) + s(left) = s(right) + s(right) = tmp + left += 1 + right -= 1 + } + } + + // 翻转每个单词 + def reverseEachWord(s: Array[Char]): Unit = { + var i = 0 + while (i < s.length) { + var j = i + 1 + // 向后迭代寻找每个单词的坐标 + while (j < s.length && s(j) != ' ') j += 1 + reverseString(s, i, j - 1) // 翻转每个单词 + i = j + 1 // i往后更新 + } + } +} +``` diff --git a/problems/0203.移除链表元素.md b/problems/0203.移除链表元素.md index 67776529..fe78ddab 100644 --- a/problems/0203.移除链表元素.md +++ b/problems/0203.移除链表元素.md @@ -266,6 +266,27 @@ public ListNode removeElements(ListNode head, int val) { } return head; } +/** + * 不添加虚拟节点and pre Node方式 + * 时间复杂度 O(n) + * 空间复杂度 O(1) + * @param head + * @param val + * @return + */ +public ListNode removeElements(ListNode head, int val) { + while(head!=null && head.val==val){ + head = head.next; + } + ListNode curr = head; + while(curr!=null){ + while(curr.next!=null && curr.next.val == val){ + curr.next = curr.next.next; + } + curr = curr.next; + } + return head; +} ``` Python: diff --git a/problems/0225.用队列实现栈.md b/problems/0225.用队列实现栈.md index 3457c4b3..3c134870 100644 --- a/problems/0225.用队列实现栈.md +++ b/problems/0225.用队列实现栈.md @@ -815,6 +815,89 @@ class MyStack { } } ``` +Scala: +使用两个队列模拟栈: +```scala +import scala.collection.mutable + +class MyStack() { + + val queue1 = new mutable.Queue[Int]() + val queue2 = new mutable.Queue[Int]() + + def push(x: Int) { + queue1.enqueue(x) + } + + def pop(): Int = { + var size = queue1.size + // 将queue1中的每个元素都移动到queue2 + for (i <- 0 until size - 1) { + queue2.enqueue(queue1.dequeue()) + } + var res = queue1.dequeue() + // 再将queue2中的每个元素都移动到queue1 + while (!queue2.isEmpty) { + queue1.enqueue(queue2.dequeue()) + } + res + } + + def top(): Int = { + var size = queue1.size + for (i <- 0 until size - 1) { + queue2.enqueue(queue1.dequeue()) + } + var res = queue1.dequeue() + while (!queue2.isEmpty) { + queue1.enqueue(queue2.dequeue()) + } + // 最终还需要把res送进queue1 + queue1.enqueue(res) + res + } + + def empty(): Boolean = { + queue1.isEmpty + } +} +``` +使用一个队列模拟: +```scala +import scala.collection.mutable + +class MyStack() { + + val queue = new mutable.Queue[Int]() + + def push(x: Int) { + queue.enqueue(x) + } + + def pop(): Int = { + var size = queue.size + for (i <- 0 until size - 1) { + queue.enqueue(queue.head) // 把头添到队列最后 + queue.dequeue() // 再出队 + } + queue.dequeue() + } + + def top(): Int = { + var size = queue.size + var res = 0 + for (i <- 0 until size) { + queue.enqueue(queue.head) // 把头添到队列最后 + res = queue.dequeue() // 再出队 + } + res + } + + def empty(): Boolean = { + queue.isEmpty + } +} +``` -----------------------
diff --git a/problems/0232.用栈实现队列.md b/problems/0232.用栈实现队列.md index 1a56d9f3..d9ba8e26 100644 --- a/problems/0232.用栈实现队列.md +++ b/problems/0232.用栈实现队列.md @@ -495,6 +495,45 @@ void myQueueFree(MyQueue* obj) { obj->stackOutTop = 0; } ``` +Scala: +```scala +class MyQueue() { + import scala.collection.mutable + val stackIn = mutable.Stack[Int]() // 负责出栈 + val stackOut = mutable.Stack[Int]() // 负责入栈 + // 添加元素 + def push(x: Int) { + stackIn.push(x) + } + + // 复用代码,如果stackOut为空就把stackIn的所有元素都压入StackOut + def dumpStackIn(): Unit = { + if (!stackOut.isEmpty) return + while (!stackIn.isEmpty) { + stackOut.push(stackIn.pop()) + } + } + + // 弹出元素 + def pop(): Int = { + dumpStackIn() + stackOut.pop() + } + + // 获取队头 + def peek(): Int = { + dumpStackIn() + val res: Int = stackOut.pop() + stackOut.push(res) + res + } + + // 判断是否为空 + def empty(): Boolean = { + stackIn.isEmpty && stackOut.isEmpty + } +} +``` -----------------------
diff --git a/problems/0239.滑动窗口最大值.md b/problems/0239.滑动窗口最大值.md index f269450f..eb32fdd2 100644 --- a/problems/0239.滑动窗口最大值.md +++ b/problems/0239.滑动窗口最大值.md @@ -630,6 +630,53 @@ func maxSlidingWindow(_ nums: [Int], _ k: Int) -> [Int] { return result } ``` +Scala: +```scala +import scala.collection.mutable.ArrayBuffer +object Solution { + def maxSlidingWindow(nums: Array[Int], k: Int): Array[Int] = { + var len = nums.length - k + 1 // 滑动窗口长度 + var res: Array[Int] = new Array[Int](len) // 声明存储结果的数组 + var index = 0 // 结果数组指针 + val queue: MyQueue = new MyQueue // 自定义队列 + // 将前k个添加到queue + for (i <- 0 until k) { + queue.add(nums(i)) + } + res(index) = queue.peek // 第一个滑动窗口的最大值 + index += 1 + for (i <- k until nums.length) { + queue.poll(nums(i - k)) // 首先移除第i-k个元素 + queue.add(nums(i)) // 添加当前数字到队列 + res(index) = queue.peek() // 赋值 + index+=1 + } + // 最终返回res,return关键字可以省略 + res + } +} + +class MyQueue { + var queue = ArrayBuffer[Int]() + + // 移除元素,如果传递进来的跟队头相等,那么移除 + def poll(value: Int): Unit = { + if (!queue.isEmpty && queue.head == value) { + queue.remove(0) + } + } + + // 添加元素,当队尾大于当前元素就删除 + def add(value: Int): Unit = { + while (!queue.isEmpty && value > queue.last) { + queue.remove(queue.length - 1) + } + queue.append(value) + } + + def peek(): Int = queue.head +} +``` -----------------------
diff --git a/problems/0344.反转字符串.md b/problems/0344.反转字符串.md index 58bada05..e1f27bd7 100644 --- a/problems/0344.反转字符串.md +++ b/problems/0344.反转字符串.md @@ -266,6 +266,20 @@ public class Solution } } ``` - +Scala: +```scala +object Solution { + def reverseString(s: Array[Char]): Unit = { + var (left, right) = (0, s.length - 1) + while (left < right) { + var tmp = s(left) + s(left) = s(right) + s(right) = tmp + left += 1 + right -= 1 + } + } +} +``` -----------------------
diff --git a/problems/0347.前K个高频元素.md b/problems/0347.前K个高频元素.md index 1d6a358b..20932b28 100644 --- a/problems/0347.前K个高频元素.md +++ b/problems/0347.前K个高频元素.md @@ -374,7 +374,49 @@ function topKFrequent(nums: number[], k: number): number[] { }; ``` +Scala: +解法一: 优先级队列 +```scala +object Solution { + import scala.collection.mutable + def topKFrequent(nums: Array[Int], k: Int): Array[Int] = { + val map = mutable.HashMap[Int, Int]() + // 将所有元素都放入Map + for (num <- nums) { + map.put(num, map.getOrElse(num, 0) + 1) + } + // 声明一个优先级队列,在函数柯里化那块需要指明排序方式 + var queue = mutable.PriorityQueue[(Int, Int)]()(Ordering.fromLessThan((x, y) => x._2 > y._2)) + // 将map里面的元素送入优先级队列 + for (elem <- map) { + queue.enqueue(elem) + if(queue.size > k){ + queue.dequeue // 如果队列元素大于k个,出队 + } + } + // 最终只需要key的Array形式就可以了,return关键字可以省略 + queue.map(_._1).toArray + } +} +``` +解法二: 相当于一个wordCount程序 +```scala +object Solution { + def topKFrequent(nums: Array[Int], k: Int): Array[Int] = { + // 首先将数据变为(x,1),然后按照x分组,再使用map进行转换(x,sum),变换为Array + // 再使用sort针对sum进行排序,最后take前k个,再把数据变为x,y,z这种格式 + nums.map((_, 1)).groupBy(_._1) + .map { + case (x, arr) => (x, arr.map(_._2).sum) + } + .toArray + .sortWith(_._2 > _._2) + .take(k) + .map(_._1) + } +} +``` -----------------------
diff --git a/problems/0383.赎金信.md b/problems/0383.赎金信.md index 933a7c31..75dafb72 100644 --- a/problems/0383.赎金信.md +++ b/problems/0383.赎金信.md @@ -363,6 +363,70 @@ impl Solution { } ``` +Scala: + +版本一: 使用数组作为哈希表 +```scala +object Solution { + def canConstruct(ransomNote: String, magazine: String): Boolean = { + // 如果magazine的长度小于ransomNote的长度,必然是false + if (magazine.length < ransomNote.length) { + return false + } + // 定义一个数组,存储magazine字符出现的次数 + val map: Array[Int] = new Array[Int](26) + // 遍历magazine字符串,对应的字符+=1 + for (i <- magazine.indices) { + map(magazine(i) - 'a') += 1 + } + // 遍历ransomNote + for (i <- ransomNote.indices) { + if (map(ransomNote(i) - 'a') > 0) + map(ransomNote(i) - 'a') -= 1 + else return false + } + // 如果上面没有返回false,直接返回true,关键字return可以省略 + true + } +} +``` + +```scala +object Solution { + import scala.collection.mutable + def canConstruct(ransomNote: String, magazine: String): Boolean = { + // 如果magazine的长度小于ransomNote的长度,必然是false + if (magazine.length < ransomNote.length) { + return false + } + // 定义map,key是字符,value是字符出现的次数 + val map = new mutable.HashMap[Char, Int]() + // 遍历magazine,把所有的字符都记录到map里面 + for (i <- magazine.indices) { + val tmpChar = magazine(i) + // 如果map包含该字符,那么对应的value++,否则添加该字符 + if (map.contains(tmpChar)) { + map.put(tmpChar, map.get(tmpChar).get + 1) + } else { + map.put(tmpChar, 1) + } + } + // 遍历ransomNote + for (i <- ransomNote.indices) { + val tmpChar = ransomNote(i) + // 如果map包含并且该字符的value大于0,则匹配成功,map对应的--,否则直接返回false + if (map.contains(tmpChar) && map.get(tmpChar).get > 0) { + map.put(tmpChar, map.get(tmpChar).get - 1) + } else { + return false + } + } + // 如果上面没有返回false,直接返回true,关键字return可以省略 + true + } +} + + C#: ```csharp public bool CanConstruct(string ransomNote, string magazine) { @@ -379,6 +443,7 @@ public bool CanConstruct(string ransomNote, string magazine) { } return true; } + ``` -----------------------
diff --git a/problems/0404.左叶子之和.md b/problems/0404.左叶子之和.md index d7fd629e..4ef68d3b 100644 --- a/problems/0404.左叶子之和.md +++ b/problems/0404.左叶子之和.md @@ -336,8 +336,8 @@ var sumOfLeftLeaves = function(root) { if(node===null){ return 0; } - let leftValue = sumOfLeftLeaves(node.left); - let rightValue = sumOfLeftLeaves(node.right); + let leftValue = nodesSum(node.left); + let rightValue = nodesSum(node.right); // 3. 单层递归逻辑 let midValue = 0; if(node.left&&node.left.left===null&&node.left.right===null){ diff --git a/problems/0454.四数相加II.md b/problems/0454.四数相加II.md index 962fe7a5..bfdee26e 100644 --- a/problems/0454.四数相加II.md +++ b/problems/0454.四数相加II.md @@ -318,6 +318,43 @@ impl Solution { } ``` + +Scala: +```scala +object Solution { + // 导包 + import scala.collection.mutable + def fourSumCount(nums1: Array[Int], nums2: Array[Int], nums3: Array[Int], nums4: Array[Int]): Int = { + // 定义一个HashMap,key存储值,value存储该值出现的次数 + val map = new mutable.HashMap[Int, Int]() + // 遍历前两个数组,把他们所有可能的情况都记录到map + for (i <- nums1.indices) { + for (j <- nums2.indices) { + val tmp = nums1(i) + nums2(j) + // 如果包含该值,则对他的key加1,不包含则添加进去 + if (map.contains(tmp)) { + map.put(tmp, map.get(tmp).get + 1) + } else { + map.put(tmp, 1) + } + } + } + var res = 0 // 结果变量 + // 遍历后两个数组 + for (i <- nums3.indices) { + for (j <- nums4.indices) { + val tmp = -(nums3(i) + nums4(j)) + // 如果map中存在该值,结果就+=value + if (map.contains(tmp)) { + res += map.get(tmp).get + } + } + } + // 返回最终结果,可以省略关键字return + res + } +} + C#: ```csharp public int FourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) { diff --git a/problems/0516.最长回文子序列.md b/problems/0516.最长回文子序列.md index 69536cef..63120b14 100644 --- a/problems/0516.最长回文子序列.md +++ b/problems/0516.最长回文子序列.md @@ -186,29 +186,28 @@ class Solution: Go: ```Go func longestPalindromeSubseq(s string) int { - lenth:=len(s) - dp:=make([][]int,lenth) - for i:=0;i b { + return a + } + return b + } + dp := make([][]int, size) + for i := 0; i < size; i++ { + dp[i] = make([]int, size) + dp[i][i] = 1 + } + for i := size - 1; i >= 0; i-- { + for j := i + 1; j < size; j++ { + if s[i] == s[j] { + dp[i][j] = dp[i+1][j-1] + 2 + } else { + dp[i][j] = max(dp[i][j-1], dp[i+1][j]) } } } - for i:=lenth-1;i>=0;i--{ - for j:=i+1;j res.length) { + reverse(res, i, s.length - 1) + } else { + reverse(res, i, i + k - 1) + } + } + new String(res) + } + // 翻转字符串,从start到end + def reverse(s: Array[Char], start: Int, end: Int): Unit = { + var (left, right) = (start, end) + while (left < right) { + var tmp = s(left) + s(left) = s(right) + s(right) = tmp + left += 1 + right -= 1 + } + } +} +``` +版本二: 首先利用sliding每隔k个进行分割,随后转换为数组,再使用zipWithIndex添加每个数组的索引,紧接着利用map做变换,如果索引%2==0则说明需要翻转,否则原封不动,最后再转换为String +```scala +object Solution { + def reverseStr(s: String, k: Int): String = { + s.sliding(k, k) + .toArray + .zipWithIndex + .map(v => if (v._2 % 2 == 0) v._1.reverse else v._1) + .mkString + } +} +``` -----------------------
diff --git a/problems/0714.买卖股票的最佳时机含手续费(动态规划).md b/problems/0714.买卖股票的最佳时机含手续费(动态规划).md index 4ab63e79..5625604b 100644 --- a/problems/0714.买卖股票的最佳时机含手续费(动态规划).md +++ b/problems/0714.买卖股票的最佳时机含手续费(动态规划).md @@ -200,6 +200,29 @@ const maxProfit = (prices,fee) => { } ``` +TypeScript: + +```typescript +function maxProfit(prices: number[], fee: number): number { + /** + dp[i][0]:持有股票 + dp[i][1]: 不持有 + */ + const length: number = prices.length; + if (length === 0) return 0; + const dp: number[][] = new Array(length).fill(0).map(_ => []); + dp[0][0] = -prices[0]; + dp[0][1] = 0; + for (let i = 1; i < 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] - fee); + } + return dp[length - 1][1]; +}; +``` + + + -----------------------
diff --git a/problems/0739.每日温度.md b/problems/0739.每日温度.md index 58edd489..987ce27e 100644 --- a/problems/0739.每日温度.md +++ b/problems/0739.每日温度.md @@ -34,7 +34,8 @@ 那么单调栈的原理是什么呢?为什么时间复杂度是O(n)就可以找到每一个元素的右边第一个比它大的元素位置呢? -单调栈的本质是空间换时间,因为在遍历的过程中需要用一个栈来记录右边第一个比当前元素大的元素,优点是只需要遍历一次。 + +单调栈的本质是空间换时间,因为在遍历的过程中需要用一个栈来记录右边第一个比当前元素高的元素,优点是只需要遍历一次。 在使用单调栈的时候首先要明确如下几点: @@ -192,7 +193,7 @@ class Solution { 否则的话,可以直接入栈。 注意,单调栈里 加入的元素是 下标。 */ - Stackstack=new Stack<>(); + Deque stack=new LinkedList<>(); stack.push(0); for(int i=1;istack=new Stack<>(); + Deque stack=new LinkedList<>(); for(int i=0;itemperatures[stack.peek()]){ diff --git a/problems/1047.删除字符串中的所有相邻重复项.md b/problems/1047.删除字符串中的所有相邻重复项.md index 638c8f4e..a92a3911 100644 --- a/problems/1047.删除字符串中的所有相邻重复项.md +++ b/problems/1047.删除字符串中的所有相邻重复项.md @@ -374,6 +374,27 @@ func removeDuplicates(_ s: String) -> String { return String(stack) } ``` - +Scala: +```scala +object Solution { + import scala.collection.mutable + def removeDuplicates(s: String): String = { + var stack = mutable.Stack[Int]() + var str = "" // 保存最终结果 + for (i <- s.indices) { + var tmp = s(i) + // 如果栈非空并且栈顶元素等于当前字符,那么删掉栈顶和字符串最后一个元素 + if (!stack.isEmpty && tmp == stack.head) { + str = str.take(str.length - 1) + stack.pop() + } else { + stack.push(tmp) + str += tmp + } + } + str + } +} +``` -----------------------
diff --git a/problems/剑指Offer05.替换空格.md b/problems/剑指Offer05.替换空格.md index 037bd427..eecd7f0c 100644 --- a/problems/剑指Offer05.替换空格.md +++ b/problems/剑指Offer05.替换空格.md @@ -413,8 +413,62 @@ func replaceSpace(_ s: String) -> String { } ``` +Scala: - +方式一: 双指针 +```scala +object Solution { + def replaceSpace(s: String): String = { + var count = 0 + s.foreach(c => if (c == ' ') count += 1) // 统计空格的数量 + val sOldSize = s.length // 旧数组字符串长度 + val sNewSize = s.length + count * 2 // 新数组字符串长度 + val res = new Array[Char](sNewSize) // 新数组 + var index = sNewSize - 1 // 新数组索引 + // 逆序遍历 + for (i <- (0 until sOldSize).reverse) { + if (s(i) == ' ') { + res(index) = '0' + index -= 1 + res(index) = '2' + index -= 1 + res(index) = '%' + } else { + res(index) = s(i) + } + index -= 1 + } + res.mkString + } +} +``` +方式二: 使用一个集合,遇到空格就添加%20 +```scala +object Solution { + import scala.collection.mutable.ListBuffer + def replaceSpace(s: String): String = { + val res: ListBuffer[Char] = ListBuffer[Char]() + for (i <- s.indices) { + if (s(i) == ' ') { + res += '%' + res += '2' + res += '0' + }else{ + res += s(i) + } + } + res.mkString + } +} +``` +方式三: 使用map +```scala +object Solution { + def replaceSpace(s: String): String = { + s.map(c => if(c == ' ') "%20" else c).mkString + } +} +``` ----------------------- diff --git a/problems/剑指Offer58-II.左旋转字符串.md b/problems/剑指Offer58-II.左旋转字符串.md index fec83e1d..7c39ed69 100644 --- a/problems/剑指Offer58-II.左旋转字符串.md +++ b/problems/剑指Offer58-II.左旋转字符串.md @@ -291,6 +291,56 @@ func reverseString(_ s: inout [Character], startIndex: Int, endIndex: Int) { ``` +### PHP + +```php +function reverseLeftWords($s, $n) { + $this->reverse($s,0,$n-1); //反转区间为前n的子串 + $this->reverse($s,$n,strlen($s)-1); //反转区间为n到末尾的子串 + $this->reverse($s,0,strlen($s)-1); //反转整个字符串 + return $s; +} + +// 按指定进行翻转 【array、string都可】 +function reverse(&$s, $start, $end) { + for ($i = $start, $j = $end; $i < $j; $i++, $j--) { + $tmp = $s[$i]; + $s[$i] = $s[$j]; + $s[$j] = $tmp; + } +} +``` + + +Scala: + +```scala +object Solution { + def reverseLeftWords(s: String, n: Int): String = { + var str = s.toCharArray // 转换为Array + // abcdefg => ba cdefg + reverseString(str, 0, n - 1) + // ba cdefg => ba gfedc + reverseString(str, n, str.length - 1) + // ba gfedc => cdefgab + reverseString(str, 0, str.length - 1) + // 最终返回,return关键字可以省略 + new String(str) + } + // 翻转字符串 + def reverseString(s: Array[Char], start: Int, end: Int): Unit = { + var (left, right) = (start, end) + while (left < right) { + var tmp = s(left) + s(left) = s(right) + s(right) = tmp + left += 1 + right -= 1 + } + } +} +``` +