mirror of
https://github.com/youngyangyang04/leetcode-master.git
synced 2025-07-11 04:54:51 +08:00
Merge branch 'youngyangyang04:master' into master
This commit is contained in:
@ -317,6 +317,20 @@ public class Solution {
|
||||
}
|
||||
```
|
||||
|
||||
Dart:
|
||||
```dart
|
||||
List<int> twoSum(List<int> 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];
|
||||
}
|
||||
```
|
||||
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
@ -554,6 +554,71 @@ func threeSum(_ nums: [Int]) -> [[Int]] {
|
||||
}
|
||||
```
|
||||
|
||||
Rust:
|
||||
```Rust
|
||||
// 哈希解法
|
||||
use std::collections::HashSet;
|
||||
impl Solution {
|
||||
pub fn three_sum(nums: Vec<i32>) -> Vec<Vec<i32>> {
|
||||
let mut result: Vec<Vec<i32>> = Vec::new();
|
||||
let mut nums = nums;
|
||||
nums.sort();
|
||||
let len = nums.len();
|
||||
for i in 0..len {
|
||||
if nums[i] > 0 { break; }
|
||||
if i > 0 && nums[i] == nums[i - 1] { continue; }
|
||||
let mut set = HashSet::new();
|
||||
for j in (i + 1)..len {
|
||||
if j > i + 2 && nums[j] == nums[j - 1] && nums[j] == nums[j - 2] { continue; }
|
||||
let c = 0 - (nums[i] + nums[j]);
|
||||
if set.contains(&c) {
|
||||
result.push(vec![nums[i], nums[j], c]);
|
||||
set.remove(&c);
|
||||
} else { set.insert(nums[j]); }
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```Rust
|
||||
// 双指针法
|
||||
use std::collections::HashSet;
|
||||
impl Solution {
|
||||
pub fn three_sum(nums: Vec<i32>) -> Vec<Vec<i32>> {
|
||||
let mut result: Vec<Vec<i32>> = Vec::new();
|
||||
let mut nums = nums;
|
||||
nums.sort();
|
||||
let len = nums.len();
|
||||
for i in 0..len {
|
||||
if nums[i] > 0 { return result; }
|
||||
if i > 0 && nums[i] == nums[i - 1] { continue; }
|
||||
let (mut left, mut right) = (i + 1, len - 1);
|
||||
while left < right {
|
||||
if nums[i] + nums[left] + nums[right] > 0 {
|
||||
right -= 1;
|
||||
// 去重
|
||||
while left < right && nums[right] == nums[right + 1] { right -= 1; }
|
||||
} else if nums[i] + nums[left] + nums[right] < 0 {
|
||||
left += 1;
|
||||
// 去重
|
||||
while left < right && nums[left] == nums[left - 1] { left += 1; }
|
||||
} else {
|
||||
result.push(vec![nums[i], nums[left], nums[right]]);
|
||||
// 去重
|
||||
right -= 1;
|
||||
left += 1;
|
||||
while left < right && nums[right] == nums[right + 1] { right -= 1; }
|
||||
while left < right && nums[left] == nums[left - 1] { left += 1; }
|
||||
}
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
C:
|
||||
```C
|
||||
//qsort辅助cmp函数
|
||||
|
@ -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;
|
||||
}
|
||||
@ -522,6 +527,51 @@ public class Solution
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Rust:
|
||||
```Rust
|
||||
impl Solution {
|
||||
pub fn four_sum(nums: Vec<i32>, target: i32) -> Vec<Vec<i32>> {
|
||||
let mut result: Vec<Vec<i32>> = Vec::new();
|
||||
let mut nums = nums;
|
||||
nums.sort();
|
||||
let len = nums.len();
|
||||
for k in 0..len {
|
||||
// 剪枝
|
||||
if nums[k] > target && (nums[k] > 0 || target > 0) { break; }
|
||||
// 去重
|
||||
if k > 0 && nums[k] == nums[k - 1] { continue; }
|
||||
for i in (k + 1)..len {
|
||||
// 剪枝
|
||||
if nums[k] + nums[i] > target && (nums[k] + nums[i] >= 0 || target >= 0) { break; }
|
||||
// 去重
|
||||
if i > k + 1 && nums[i] == nums[i - 1] { continue; }
|
||||
let (mut left, mut right) = (i + 1, len - 1);
|
||||
while left < right {
|
||||
if nums[k] + nums[i] > target - (nums[left] + nums[right]) {
|
||||
right -= 1;
|
||||
// 去重
|
||||
while left < right && nums[right] == nums[right + 1] { right -= 1; }
|
||||
} else if nums[k] + nums[i] < target - (nums[left] + nums[right]) {
|
||||
left += 1;
|
||||
// 去重
|
||||
while left < right && nums[left] == nums[left - 1] { left += 1; }
|
||||
} else {
|
||||
result.push(vec![nums[k], nums[i], nums[left], nums[right]]);
|
||||
// 去重
|
||||
while left < right && nums[right] == nums[right - 1] { right -= 1; }
|
||||
while left < right && nums[left] == nums[left + 1] { left += 1; }
|
||||
left += 1;
|
||||
right -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Scala:
|
||||
```scala
|
||||
object Solution {
|
||||
|
@ -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形式
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
@ -136,24 +136,38 @@ public:
|
||||
|
||||
### Java
|
||||
```java
|
||||
|
||||
/**
|
||||
时间复杂度 : O(NlogN) 排序需要O(NlogN)
|
||||
空间复杂度 : O(logN) java 的内置排序是快速排序 需要 O(logN)空间
|
||||
|
||||
*/
|
||||
class Solution {
|
||||
public int[][] merge(int[][] intervals) {
|
||||
List<int[]> 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
|
||||
|
@ -373,6 +373,60 @@ func subsets(_ nums: [Int]) -> [[Int]] {
|
||||
}
|
||||
```
|
||||
|
||||
## Scala
|
||||
|
||||
思路一: 使用本题解思路
|
||||
|
||||
```scala
|
||||
object Solution {
|
||||
import scala.collection.mutable
|
||||
def subsets(nums: Array[Int]): List[List[Int]] = {
|
||||
var result = mutable.ListBuffer[List[Int]]()
|
||||
var path = mutable.ListBuffer[Int]()
|
||||
|
||||
def backtracking(startIndex: Int): Unit = {
|
||||
result.append(path.toList) // 存放结果
|
||||
if (startIndex >= nums.size) {
|
||||
return
|
||||
}
|
||||
for (i <- startIndex until nums.size) {
|
||||
path.append(nums(i)) // 添加元素
|
||||
backtracking(i + 1)
|
||||
path.remove(path.size - 1) // 删除
|
||||
}
|
||||
}
|
||||
|
||||
backtracking(0)
|
||||
result.toList
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
思路二: 将原问题转换为二叉树,针对每一个元素都有**选或不选**两种选择,直到遍历到最后,所有的叶子节点即为本题的答案:
|
||||
|
||||
```scala
|
||||
object Solution {
|
||||
import scala.collection.mutable
|
||||
def subsets(nums: Array[Int]): List[List[Int]] = {
|
||||
var result = mutable.ListBuffer[List[Int]]()
|
||||
|
||||
def backtracking(path: mutable.ListBuffer[Int], startIndex: Int): Unit = {
|
||||
if (startIndex == nums.length) {
|
||||
result.append(path.toList)
|
||||
return
|
||||
}
|
||||
path.append(nums(startIndex))
|
||||
backtracking(path, startIndex + 1) // 选择元素
|
||||
path.remove(path.size - 1)
|
||||
backtracking(path, startIndex + 1) // 不选择元素
|
||||
}
|
||||
|
||||
backtracking(mutable.ListBuffer[Int](), 0)
|
||||
result.toList
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
@ -434,6 +434,63 @@ func subsetsWithDup(_ nums: [Int]) -> [[Int]] {
|
||||
}
|
||||
```
|
||||
|
||||
### Scala
|
||||
|
||||
不使用userd数组:
|
||||
|
||||
```scala
|
||||
object Solution {
|
||||
import scala.collection.mutable
|
||||
def subsetsWithDup(nums: Array[Int]): List[List[Int]] = {
|
||||
var result = mutable.ListBuffer[List[Int]]()
|
||||
var path = mutable.ListBuffer[Int]()
|
||||
var num = nums.sorted // 排序
|
||||
|
||||
def backtracking(startIndex: Int): Unit = {
|
||||
result.append(path.toList)
|
||||
if (startIndex >= num.size){
|
||||
return
|
||||
}
|
||||
for (i <- startIndex until num.size) {
|
||||
// 同一树层重复的元素不进入回溯
|
||||
if (!(i > startIndex && num(i) == num(i - 1))) {
|
||||
path.append(num(i))
|
||||
backtracking(i + 1)
|
||||
path.remove(path.size - 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
backtracking(0)
|
||||
result.toList
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
使用Set去重:
|
||||
```scala
|
||||
object Solution {
|
||||
import scala.collection.mutable
|
||||
def subsetsWithDup(nums: Array[Int]): List[List[Int]] = {
|
||||
var result = mutable.Set[List[Int]]()
|
||||
var num = nums.sorted
|
||||
def backtracking(path: mutable.ListBuffer[Int], startIndex: Int): Unit = {
|
||||
if (startIndex == num.length) {
|
||||
result.add(path.toList)
|
||||
return
|
||||
}
|
||||
path.append(num(startIndex))
|
||||
backtracking(path, startIndex + 1) // 选择
|
||||
path.remove(path.size - 1)
|
||||
backtracking(path, startIndex + 1) // 不选择
|
||||
}
|
||||
|
||||
backtracking(mutable.ListBuffer[Int](), 0)
|
||||
|
||||
result.toList
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
@ -2629,21 +2629,21 @@ JavaScript:
|
||||
var minDepth = function(root) {
|
||||
if (root === null) return 0;
|
||||
let queue = [root];
|
||||
let deepth = 0;
|
||||
let depth = 0;
|
||||
while (queue.length) {
|
||||
let n = queue.length;
|
||||
deepth++;
|
||||
depth++;
|
||||
for (let i=0; i<n; i++) {
|
||||
let node = queue.shift();
|
||||
// 如果左右节点都是null,则该节点深度最小
|
||||
// 如果左右节点都是null(在遇见的第一个leaf节点上),则该节点深度最小
|
||||
if (node.left === null && node.right === null) {
|
||||
return deepth;
|
||||
return depth;
|
||||
}
|
||||
node.left && queue.push(node.left);;
|
||||
node.right && queue.push (node.right);
|
||||
node.right && queue.push(node.right);
|
||||
}
|
||||
}
|
||||
return deepth;
|
||||
return depth;
|
||||
};
|
||||
```
|
||||
|
||||
|
@ -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<treenode> deque = new linkedlist<>();
|
||||
Deque<TreeNode> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,9 @@
|
||||
<img src="https://code-thinking-1253855093.file.myqcloud.com/pics/20210924105952.png" width="1000"/>
|
||||
</a>
|
||||
<p align="center"><strong><a href="https://mp.weixin.qq.com/s/tqCxrMEU-ajQumL1i8im9A">参与本项目</a>,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!</strong></p>
|
||||
|
||||
|
||||
|
||||
# 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) {
|
||||
|
@ -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
|
||||
|
@ -315,6 +315,36 @@ class Solution {
|
||||
}
|
||||
```
|
||||
|
||||
Rust:
|
||||
```Rust
|
||||
use std::collections::HashSet;
|
||||
impl Solution {
|
||||
pub fn get_sum(mut n: i32) -> i32 {
|
||||
let mut sum = 0;
|
||||
while n > 0 {
|
||||
sum += (n % 10) * (n % 10);
|
||||
n /= 10;
|
||||
}
|
||||
sum
|
||||
}
|
||||
|
||||
pub fn is_happy(n: i32) -> bool {
|
||||
let mut n = n;
|
||||
let mut set = HashSet::new();
|
||||
loop {
|
||||
let sum = Self::get_sum(n);
|
||||
if sum == 1 {
|
||||
return true;
|
||||
}
|
||||
if set.contains(&sum) {
|
||||
return false;
|
||||
} else { set.insert(sum); }
|
||||
n = sum;
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
C:
|
||||
```C
|
||||
typedef struct HashNodeTag {
|
||||
|
@ -156,6 +156,28 @@ var isIsomorphic = function(s, t) {
|
||||
};
|
||||
```
|
||||
|
||||
## TypeScript
|
||||
|
||||
```typescript
|
||||
function isIsomorphic(s: string, t: string): boolean {
|
||||
const helperMap1: Map<string, string> = new Map();
|
||||
const helperMap2: Map<string, string> = new Map();
|
||||
for (let i = 0, length = s.length; i < length; i++) {
|
||||
let temp1: string | undefined = helperMap1.get(s[i]);
|
||||
let temp2: string | undefined = helperMap2.get(t[i]);
|
||||
if (temp1 === undefined && temp2 === undefined) {
|
||||
helperMap1.set(s[i], t[i]);
|
||||
helperMap2.set(t[i], s[i]);
|
||||
} else if (temp1 !== t[i] || temp2 !== s[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
@ -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;
|
||||
// 终止条件
|
||||
if (!root) {
|
||||
return null;
|
||||
}
|
||||
//确定递归函数的参数和返回值inverTree=function(root)
|
||||
//确定终止条件
|
||||
if(root===null){
|
||||
return root;
|
||||
}
|
||||
//确定节点处理逻辑 交换
|
||||
inverNode(root.left,root.right);
|
||||
invertTree(root.left);
|
||||
invertTree(root.right);
|
||||
// 交换左右节点
|
||||
const rightNode = root.right;
|
||||
root.right = invertTree(root.left);
|
||||
root.left = invertTree(rightNode);
|
||||
return root;
|
||||
};
|
||||
```
|
||||
|
@ -141,13 +141,10 @@ class Solution {
|
||||
}
|
||||
|
||||
Set<Map.Entry<Integer, Integer>> entries = map.entrySet();
|
||||
// 根据map的value值正序排,相当于一个小顶堆
|
||||
PriorityQueue<Map.Entry<Integer, Integer>> queue = new PriorityQueue<>((o1, o2) -> o1.getValue() - o2.getValue());
|
||||
// 根据map的value值,构建于一个大顶堆(o1 - o2: 小顶堆, o2 - o1 : 大顶堆)
|
||||
PriorityQueue<Map.Entry<Integer, Integer>> queue = new PriorityQueue<>((o1, o2) -> o2.getValue() - o1.getValue());
|
||||
for (Map.Entry<Integer, Integer> entry : entries) {
|
||||
queue.offer(entry);
|
||||
if (queue.size() > k) {
|
||||
queue.poll();
|
||||
}
|
||||
}
|
||||
for (int i = k - 1; i >= 0; i--) {
|
||||
result[i] = queue.poll().getKey();
|
||||
|
@ -456,31 +456,42 @@ func deleteNode(root *TreeNode, key int) *TreeNode {
|
||||
* @param {number} key
|
||||
* @return {TreeNode}
|
||||
*/
|
||||
var deleteNode = function (root, key) {
|
||||
if (root === null)
|
||||
return root;
|
||||
if (root.val === key) {
|
||||
if (!root.left)
|
||||
return root.right;
|
||||
else if (!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;
|
||||
}
|
||||
}
|
||||
if (root.val > key)
|
||||
root.left = deleteNode(root.left, key);
|
||||
if (root.val < key)
|
||||
var deleteNode = function(root, key) {
|
||||
if (!root) return null;
|
||||
if (key > root.val) {
|
||||
root.right = deleteNode(root.right, key);
|
||||
return root;
|
||||
return root;
|
||||
} 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 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;
|
||||
}
|
||||
};
|
||||
function getMinNode(root) {
|
||||
while (root.left) {
|
||||
root = root.left;
|
||||
}
|
||||
return root;
|
||||
}
|
||||
```
|
||||
|
||||
迭代
|
||||
|
@ -136,17 +136,28 @@ public:
|
||||
|
||||
### Java
|
||||
```java
|
||||
/**
|
||||
时间复杂度 : O(NlogN) 排序需要 O(NlogN) 的复杂度
|
||||
|
||||
空间复杂度 : O(logN) java所使用的内置函数用的是快速排序需要 logN 的空间
|
||||
*/
|
||||
class Solution {
|
||||
public int findMinArrowShots(int[][] points) {
|
||||
if (points.length == 0) return 0;
|
||||
Arrays.sort(points, (o1, o2) -> Integer.compare(o1[0], o2[0]));
|
||||
|
||||
//用x[0] - y[0] 会大于2147483647 造成整型溢出
|
||||
Arrays.sort(points, (x, y) -> Integer.compare(x[0], y[0]));
|
||||
//count = 1 因为最少需要一个箭来射击第一个气球
|
||||
int count = 1;
|
||||
for (int i = 1; i < points.length; i++) {
|
||||
if (points[i][0] > points[i - 1][1]) {
|
||||
//重叠气球的最小右边界
|
||||
int leftmostRightBound = points[0][1];
|
||||
//如果下一个气球的左边界大于最小右边界
|
||||
if (points[i][0] > leftmostRightBound ) {
|
||||
//增加一次射击
|
||||
count++;
|
||||
leftmostRightBound = points[i][1];
|
||||
//不然就更新最小右边界
|
||||
} else {
|
||||
points[i][1] = Math.min(points[i][1],points[i - 1][1]);
|
||||
leftmostRightBound = Math.min(leftmostRightBound , points[i][1]);
|
||||
}
|
||||
}
|
||||
return count;
|
||||
|
@ -522,5 +522,39 @@ func findSubsequences(_ nums: [Int]) -> [[Int]] {
|
||||
```
|
||||
|
||||
|
||||
## Scala
|
||||
|
||||
```scala
|
||||
object Solution {
|
||||
import scala.collection.mutable
|
||||
def findSubsequences(nums: Array[Int]): List[List[Int]] = {
|
||||
var result = mutable.ListBuffer[List[Int]]()
|
||||
var path = mutable.ListBuffer[Int]()
|
||||
|
||||
def backtracking(startIndex: Int): Unit = {
|
||||
// 集合元素大于1,添加到结果集
|
||||
if (path.size > 1) {
|
||||
result.append(path.toList)
|
||||
}
|
||||
|
||||
var used = new Array[Boolean](201)
|
||||
// 使用循环守卫,当前层没有用过的元素才有资格进入回溯
|
||||
for (i <- startIndex until nums.size if !used(nums(i) + 100)) {
|
||||
// 如果path没元素或 当前循环的元素比path的最后一个元素大,则可以进入回溯
|
||||
if (path.size == 0 || (!path.isEmpty && nums(i) >= path(path.size - 1))) {
|
||||
used(nums(i) + 100) = true
|
||||
path.append(nums(i))
|
||||
backtracking(i + 1)
|
||||
path.remove(path.size - 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
backtracking(0)
|
||||
result.toList
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
@ -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 {
|
||||
|
@ -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:
|
||||
|
Reference in New Issue
Block a user