Merge branch 'master' of github.com:youngyangyang04/leetcode-master
This commit is contained in:
@@ -335,6 +335,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>
|
||||
|
||||
@@ -95,7 +95,7 @@ public:
|
||||
|
||||
拿这个nums数组来举例,首先将数组排序,然后有一层for循环,i从下标0的地方开始,同时定一个下标left 定义在i+1的位置上,定义下标right 在数组结尾的位置上。
|
||||
|
||||
依然还是在数组中找到 abc 使得a + b +c =0,我们这里相当于 a = nums[i] b = nums[left] c = nums[right]。
|
||||
依然还是在数组中找到 abc 使得a + b +c =0,我们这里相当于 a = nums[i],b = nums[left],c = nums[right]。
|
||||
|
||||
接下来如何移动left 和right呢, 如果nums[i] + nums[left] + nums[right] > 0 就说明 此时三数之和大了,因为数组是排序后了,所以right下标就应该向左移动,这样才能让三数之和小一些。
|
||||
|
||||
@@ -411,6 +411,76 @@ var threeSum = function(nums) {
|
||||
return res
|
||||
};
|
||||
```
|
||||
|
||||
解法二:nSum通用解法。递归
|
||||
|
||||
```js
|
||||
/**
|
||||
* nsum通用解法,支持2sum,3sum,4sum...等等
|
||||
* 时间复杂度分析:
|
||||
* 1. n = 2时,时间复杂度O(NlogN),排序所消耗的时间。、
|
||||
* 2. n > 2时,时间复杂度为O(N^n-1),即N的n-1次方,至少是2次方,此时可省略排序所消耗的时间。举例:3sum为O(n^2),4sum为O(n^3)
|
||||
* @param {number[]} nums
|
||||
* @return {number[][]}
|
||||
*/
|
||||
var threeSum = function (nums) {
|
||||
// nsum通用解法核心方法
|
||||
function nSumTarget(nums, n, start, target) {
|
||||
// 前提:nums要先排序好
|
||||
let res = [];
|
||||
if (n === 2) {
|
||||
res = towSumTarget(nums, start, target);
|
||||
} else {
|
||||
for (let i = start; i < nums.length; i++) {
|
||||
// 递归求(n - 1)sum
|
||||
let subRes = nSumTarget(
|
||||
nums,
|
||||
n - 1,
|
||||
i + 1,
|
||||
target - nums[i]
|
||||
);
|
||||
for (let j = 0; j < subRes.length; j++) {
|
||||
res.push([nums[i], ...subRes[j]]);
|
||||
}
|
||||
// 跳过相同元素
|
||||
while (nums[i] === nums[i + 1]) i++;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
function towSumTarget(nums, start, target) {
|
||||
// 前提:nums要先排序好
|
||||
let res = [];
|
||||
let len = nums.length;
|
||||
let left = start;
|
||||
let right = len - 1;
|
||||
while (left < right) {
|
||||
let sum = nums[left] + nums[right];
|
||||
if (sum < target) {
|
||||
while (nums[left] === nums[left + 1]) left++;
|
||||
left++;
|
||||
} else if (sum > target) {
|
||||
while (nums[right] === nums[right - 1]) right--;
|
||||
right--;
|
||||
} else {
|
||||
// 相等
|
||||
res.push([nums[left], nums[right]]);
|
||||
// 跳过相同元素
|
||||
while (nums[left] === nums[left + 1]) left++;
|
||||
while (nums[right] === nums[right - 1]) right--;
|
||||
left++;
|
||||
right--;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
nums.sort((a, b) => a - b);
|
||||
// n = 3,此时求3sum之和
|
||||
return nSumTarget(nums, 3, 0, 0);
|
||||
};
|
||||
```
|
||||
|
||||
TypeScript:
|
||||
|
||||
```typescript
|
||||
@@ -550,6 +620,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函数
|
||||
|
||||
@@ -454,6 +454,49 @@ function letterCombinations(digits: string): string[] {
|
||||
};
|
||||
```
|
||||
|
||||
## Rust
|
||||
|
||||
```Rust
|
||||
impl Solution {
|
||||
fn backtracking(result: &mut Vec<String>, s: &mut String, map: &[&str; 10], digits: &String, index: usize) {
|
||||
let len = digits.len();
|
||||
if len == index {
|
||||
result.push(s.to_string());
|
||||
return;
|
||||
}
|
||||
// 在保证不会越界的情况下使用unwrap()将Some()中的值提取出来
|
||||
let digit= digits.chars().nth(index).unwrap().to_digit(10).unwrap() as usize;
|
||||
let letters = map[digit];
|
||||
for i in letters.chars() {
|
||||
s.push(i);
|
||||
Self::backtracking(result, s, &map, &digits, index+1);
|
||||
s.pop();
|
||||
}
|
||||
}
|
||||
pub fn letter_combinations(digits: String) -> Vec<String> {
|
||||
if digits.len() == 0 {
|
||||
return vec![];
|
||||
}
|
||||
const MAP: [&str; 10] = [
|
||||
"",
|
||||
"",
|
||||
"abc",
|
||||
"def",
|
||||
"ghi",
|
||||
"jkl",
|
||||
"mno",
|
||||
"pqrs",
|
||||
"tuv",
|
||||
"wxyz"
|
||||
];
|
||||
let mut result: Vec<String> = Vec::new();
|
||||
let mut s: String = String::new();
|
||||
Self::backtracking(&mut result, &mut s, &MAP, &digits, 0);
|
||||
result
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## C
|
||||
|
||||
```c
|
||||
@@ -557,6 +600,37 @@ func letterCombinations(_ digits: String) -> [String] {
|
||||
}
|
||||
```
|
||||
|
||||
## Scala:
|
||||
|
||||
```scala
|
||||
object Solution {
|
||||
import scala.collection.mutable
|
||||
def letterCombinations(digits: String): List[String] = {
|
||||
var result = mutable.ListBuffer[String]()
|
||||
if(digits == "") return result.toList // 如果参数为空,返回空结果集的List形式
|
||||
var path = mutable.ListBuffer[Char]()
|
||||
// 数字和字符的映射关系
|
||||
val map = Array[String]("", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz")
|
||||
|
||||
def backtracking(index: Int): Unit = {
|
||||
if (index == digits.size) {
|
||||
result.append(path.mkString) // mkString语法:将数组类型直接转换为字符串
|
||||
return
|
||||
}
|
||||
var digit = digits(index) - '0' // 这里使用toInt会报错!必须 -'0'
|
||||
for (i <- 0 until map(digit).size) {
|
||||
path.append(map(digit)(i))
|
||||
backtracking(index + 1)
|
||||
path = path.take(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>
|
||||
|
||||
@@ -135,6 +135,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;
|
||||
}
|
||||
@@ -148,7 +153,7 @@ class Solution {
|
||||
int left = j + 1;
|
||||
int right = nums.length - 1;
|
||||
while (right > left) {
|
||||
int sum = nums[i] + nums[j] + nums[left] + nums[right];
|
||||
long sum = (long) nums[i] + nums[j] + nums[left] + nums[right];
|
||||
if (sum > target) {
|
||||
right--;
|
||||
} else if (sum < target) {
|
||||
@@ -517,6 +522,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 {
|
||||
|
||||
@@ -400,6 +400,37 @@ bool isValid(char * s){
|
||||
return !stackTop;
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
PHP:
|
||||
```php
|
||||
// https://www.php.net/manual/zh/class.splstack.php
|
||||
class Solution
|
||||
{
|
||||
function isValid($s){
|
||||
$stack = new SplStack();
|
||||
for ($i = 0; $i < strlen($s); $i++) {
|
||||
if ($s[$i] == "(") {
|
||||
$stack->push(')');
|
||||
} else if ($s[$i] == "{") {
|
||||
$stack->push('}');
|
||||
} else if ($s[$i] == "[") {
|
||||
$stack->push(']');
|
||||
// 2、遍历匹配过程中,发现栈内没有要匹配的字符 return false
|
||||
// 3、遍历匹配过程中,栈已为空,没有匹配的字符了,说明右括号没有找到对应的左括号 return false
|
||||
} else if ($stack->isEmpty() || $stack->top() != $s[$i]) {
|
||||
return false;
|
||||
} else {//$stack->top() == $s[$i]
|
||||
$stack->pop();
|
||||
}
|
||||
}
|
||||
// 1、遍历完,但是栈不为空,说明有相应的括号没有被匹配,return false
|
||||
return $stack->isEmpty();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
Scala:
|
||||
```scala
|
||||
object Solution {
|
||||
@@ -422,5 +453,6 @@ object Solution {
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
||||
@@ -256,20 +256,19 @@ TypeScript:
|
||||
|
||||
```typescript
|
||||
function swapPairs(head: ListNode | null): ListNode | null {
|
||||
const dummyHead: ListNode = new ListNode(0, head);
|
||||
let cur: ListNode = dummyHead;
|
||||
while(cur.next !== null && cur.next.next !== null) {
|
||||
const tem: ListNode = cur.next;
|
||||
const tem1: ListNode = cur.next.next.next;
|
||||
|
||||
cur.next = cur.next.next; // step 1
|
||||
cur.next.next = tem; // step 2
|
||||
cur.next.next.next = tem1; // step 3
|
||||
|
||||
cur = cur.next.next;
|
||||
}
|
||||
return dummyHead.next;
|
||||
}
|
||||
const dummyNode: ListNode = new ListNode(0, head);
|
||||
let curNode: ListNode | null = dummyNode;
|
||||
while (curNode && curNode.next && curNode.next.next) {
|
||||
let firstNode: ListNode = curNode.next,
|
||||
secNode: ListNode = curNode.next.next,
|
||||
thirdNode: ListNode | null = curNode.next.next.next;
|
||||
curNode.next = secNode;
|
||||
secNode.next = firstNode;
|
||||
firstNode.next = thirdNode;
|
||||
curNode = firstNode;
|
||||
}
|
||||
return dummyNode.next;
|
||||
};
|
||||
```
|
||||
|
||||
Kotlin:
|
||||
|
||||
@@ -219,6 +219,7 @@ func removeElement(nums []int, val int) int {
|
||||
res++
|
||||
}
|
||||
}
|
||||
nums=nums[:res]
|
||||
return res
|
||||
}
|
||||
```
|
||||
@@ -339,7 +340,6 @@ int removeElement(int* nums, int numsSize, int val){
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
Kotlin:
|
||||
```kotlin
|
||||
fun removeElement(nums: IntArray, `val`: Int): Int {
|
||||
@@ -351,7 +351,6 @@ fun removeElement(nums: IntArray, `val`: Int): Int {
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
Scala:
|
||||
```scala
|
||||
object Solution {
|
||||
@@ -368,5 +367,20 @@ object Solution {
|
||||
}
|
||||
```
|
||||
|
||||
C#:
|
||||
```csharp
|
||||
public class Solution {
|
||||
public int RemoveElement(int[] nums, int val) {
|
||||
int slow = 0;
|
||||
for (int fast = 0; fast < nums.Length; fast++) {
|
||||
if (val != nums[fast]) {
|
||||
nums[slow++] = nums[fast];
|
||||
}
|
||||
}
|
||||
return slow;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
||||
@@ -1241,5 +1241,49 @@ function getNext(&$next, $s){
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Rust:
|
||||
|
||||
> 前缀表统一不减一
|
||||
```Rust
|
||||
impl Solution {
|
||||
pub fn get_next(next: &mut Vec<usize>, s: &Vec<char>) {
|
||||
let len = s.len();
|
||||
let mut j = 0;
|
||||
for i in 1..len {
|
||||
while j > 0 && s[i] != s[j] {
|
||||
j = next[j - 1];
|
||||
}
|
||||
if s[i] == s[j] {
|
||||
j += 1;
|
||||
}
|
||||
next[i] = j;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn str_str(haystack: String, needle: String) -> i32 {
|
||||
let (haystack_len, needle_len) = (haystack.len(), needle.len());
|
||||
if haystack_len == 0 { return 0; }
|
||||
if haystack_len < needle_len { return -1;}
|
||||
let (haystack, needle) = (haystack.chars().collect::<Vec<char>>(), needle.chars().collect::<Vec<char>>());
|
||||
let mut next: Vec<usize> = vec![0; haystack_len];
|
||||
Self::get_next(&mut next, &needle);
|
||||
let mut j = 0;
|
||||
for i in 0..haystack_len {
|
||||
while j > 0 && haystack[i] != needle[j] {
|
||||
j = next[j - 1];
|
||||
}
|
||||
if haystack[i] == needle[j] {
|
||||
j += 1;
|
||||
}
|
||||
if j == needle_len {
|
||||
return (i - needle_len + 1) as i32;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
||||
@@ -171,13 +171,13 @@ class Solution(object):
|
||||
i = n-2
|
||||
while i >= 0 and nums[i] >= nums[i+1]:
|
||||
i -= 1
|
||||
|
||||
|
||||
if i > -1: // i==-1,不存在下一个更大的排列
|
||||
j = n-1
|
||||
while j >= 0 and nums[j] <= nums[i]:
|
||||
j -= 1
|
||||
nums[i], nums[j] = nums[j], nums[i]
|
||||
|
||||
|
||||
start, end = i+1, n-1
|
||||
while start < end:
|
||||
nums[start], nums[end] = nums[end], nums[start]
|
||||
@@ -190,6 +190,26 @@ class Solution(object):
|
||||
## Go
|
||||
|
||||
```go
|
||||
//卡尔的解法
|
||||
func nextPermutation(nums []int) {
|
||||
for i:=len(nums)-1;i>=0;i--{
|
||||
for j:=len(nums)-1;j>i;j--{
|
||||
if nums[j]>nums[i]{
|
||||
//交换
|
||||
nums[j],nums[i]=nums[i],nums[j]
|
||||
reverse(nums,0+i+1,len(nums)-1)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
reverse(nums,0,len(nums)-1)
|
||||
}
|
||||
//对目标切片指定区间的反转方法
|
||||
func reverse(a []int,begin,end int){
|
||||
for i,j:=begin,end;i<j;i,j=i+1,j-1{
|
||||
a[i],a[j]=a[j],a[i]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## JavaScript
|
||||
|
||||
@@ -482,6 +482,62 @@ var searchRange = function(nums, target) {
|
||||
return [-1, -1];
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
### TypeScript
|
||||
|
||||
```typescript
|
||||
function searchRange(nums: number[], target: number): number[] {
|
||||
const leftBoard: number = getLeftBorder(nums, target);
|
||||
const rightBoard: number = getRightBorder(nums, target);
|
||||
// target 在nums区间左侧或右侧
|
||||
if (leftBoard === (nums.length - 1) || rightBoard === 0) return [-1, -1];
|
||||
// target 不存在与nums范围内
|
||||
if (rightBoard - leftBoard <= 1) return [-1, -1];
|
||||
// target 存在于nums范围内
|
||||
return [leftBoard + 1, rightBoard - 1];
|
||||
};
|
||||
// 查找第一个大于target的元素下标
|
||||
function getRightBorder(nums: number[], target: number): number {
|
||||
let left: number = 0,
|
||||
right: number = nums.length - 1;
|
||||
// 0表示target在nums区间的左边
|
||||
let rightBoard: number = 0;
|
||||
while (left <= right) {
|
||||
let mid = Math.floor((left + right) / 2);
|
||||
if (nums[mid] <= target) {
|
||||
// 右边界一定在mid右边(不含mid)
|
||||
left = mid + 1;
|
||||
rightBoard = left;
|
||||
} else {
|
||||
// 右边界在mid左边(含mid)
|
||||
right = mid - 1;
|
||||
}
|
||||
}
|
||||
return rightBoard;
|
||||
}
|
||||
// 查找第一个小于target的元素下标
|
||||
function getLeftBorder(nums: number[], target: number): number {
|
||||
let left: number = 0,
|
||||
right: number = nums.length - 1;
|
||||
// length-1表示target在nums区间的右边
|
||||
let leftBoard: number = nums.length - 1;
|
||||
while (left <= right) {
|
||||
let mid = Math.floor((left + right) / 2);
|
||||
if (nums[mid] >= target) {
|
||||
// 左边界一定在mid左边(不含mid)
|
||||
right = mid - 1;
|
||||
leftBoard = right;
|
||||
} else {
|
||||
// 左边界在mid右边(含mid)
|
||||
left = mid + 1;
|
||||
}
|
||||
}
|
||||
return leftBoard;
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### Scala
|
||||
```scala
|
||||
object Solution {
|
||||
@@ -529,5 +585,49 @@ object Solution {
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### Kotlin
|
||||
```kotlin
|
||||
class Solution {
|
||||
fun searchRange(nums: IntArray, target: Int): IntArray {
|
||||
var index = binarySearch(nums, target)
|
||||
// 没找到,返回[-1, -1]
|
||||
if (index == -1) return intArrayOf(-1, -1)
|
||||
var left = index
|
||||
var right = index
|
||||
// 寻找左边界
|
||||
while (left - 1 >=0 && nums[left - 1] == target){
|
||||
left--
|
||||
}
|
||||
// 寻找右边界
|
||||
while (right + 1 <nums.size && nums[right + 1] == target){
|
||||
right++
|
||||
}
|
||||
return intArrayOf(left, right)
|
||||
}
|
||||
// 二分查找常规写法
|
||||
fun binarySearch(nums: IntArray, target: Int): Int {
|
||||
var left = 0;
|
||||
var right = nums.size - 1
|
||||
while (left <= right) {
|
||||
var middle = left + (right - left)/2
|
||||
if (nums[middle] > target) {
|
||||
right = middle - 1
|
||||
}
|
||||
else {
|
||||
if (nums[middle] < target) {
|
||||
left = middle + 1
|
||||
}
|
||||
else {
|
||||
return middle
|
||||
}
|
||||
}
|
||||
}
|
||||
// 没找到,返回-1
|
||||
return -1
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
||||
@@ -283,6 +283,28 @@ var searchInsert = function (nums, target) {
|
||||
};
|
||||
```
|
||||
|
||||
### TypeScript
|
||||
|
||||
```typescript
|
||||
// 第一种二分法
|
||||
function searchInsert(nums: number[], target: number): number {
|
||||
const length: number = nums.length;
|
||||
let left: number = 0,
|
||||
right: number = length - 1;
|
||||
while (left <= right) {
|
||||
const mid: number = Math.floor((left + right) / 2);
|
||||
if (nums[mid] < target) {
|
||||
left = mid + 1;
|
||||
} else if (nums[mid] === target) {
|
||||
return mid;
|
||||
} else {
|
||||
right = mid - 1;
|
||||
}
|
||||
}
|
||||
return right + 1;
|
||||
};
|
||||
```
|
||||
|
||||
### Swift
|
||||
|
||||
```swift
|
||||
|
||||
@@ -602,5 +602,100 @@ func solveSudoku(_ board: inout [[Character]]) {
|
||||
}
|
||||
```
|
||||
|
||||
### Scala
|
||||
|
||||
详细写法:
|
||||
```scala
|
||||
object Solution {
|
||||
|
||||
def solveSudoku(board: Array[Array[Char]]): Unit = {
|
||||
backtracking(board)
|
||||
}
|
||||
|
||||
def backtracking(board: Array[Array[Char]]): Boolean = {
|
||||
for (i <- 0 until 9) {
|
||||
for (j <- 0 until 9) {
|
||||
if (board(i)(j) == '.') { // 必须是为 . 的数字才放数字
|
||||
for (k <- '1' to '9') { // 这个位置放k是否合适
|
||||
if (isVaild(i, j, k, board)) {
|
||||
board(i)(j) = k
|
||||
if (backtracking(board)) return true // 找到了立刻返回
|
||||
board(i)(j) = '.' // 回溯
|
||||
}
|
||||
}
|
||||
return false // 9个数都试完了,都不行就返回false
|
||||
}
|
||||
}
|
||||
}
|
||||
true // 遍历完所有的都没返回false,说明找到了
|
||||
}
|
||||
|
||||
def isVaild(x: Int, y: Int, value: Char, board: Array[Array[Char]]): Boolean = {
|
||||
// 行
|
||||
for (i <- 0 until 9 ) {
|
||||
if (board(i)(y) == value) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// 列
|
||||
for (j <- 0 until 9) {
|
||||
if (board(x)(j) == value) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// 宫
|
||||
var row = (x / 3) * 3
|
||||
var col = (y / 3) * 3
|
||||
for (i <- row until row + 3) {
|
||||
for (j <- col until col + 3) {
|
||||
if (board(i)(j) == value) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
遵循Scala至简原则写法:
|
||||
```scala
|
||||
object Solution {
|
||||
|
||||
def solveSudoku(board: Array[Array[Char]]): Unit = {
|
||||
backtracking(board)
|
||||
}
|
||||
|
||||
def backtracking(board: Array[Array[Char]]): Boolean = {
|
||||
// 双重for循环 + 循环守卫
|
||||
for (i <- 0 until 9; j <- 0 until 9 if board(i)(j) == '.') {
|
||||
// 必须是为 . 的数字才放数字,使用循环守卫判断该位置是否可以放置当前循环的数字
|
||||
for (k <- '1' to '9' if isVaild(i, j, k, board)) { // 这个位置放k是否合适
|
||||
board(i)(j) = k
|
||||
if (backtracking(board)) return true // 找到了立刻返回
|
||||
board(i)(j) = '.' // 回溯
|
||||
}
|
||||
return false // 9个数都试完了,都不行就返回false
|
||||
}
|
||||
true // 遍历完所有的都没返回false,说明找到了
|
||||
}
|
||||
|
||||
def isVaild(x: Int, y: Int, value: Char, board: Array[Array[Char]]): Boolean = {
|
||||
// 行,循环守卫进行判断
|
||||
for (i <- 0 until 9 if board(i)(y) == value) return false
|
||||
// 列,循环守卫进行判断
|
||||
for (j <- 0 until 9 if board(x)(j) == value) return false
|
||||
// 宫,循环守卫进行判断
|
||||
var row = (x / 3) * 3
|
||||
var col = (y / 3) * 3
|
||||
for (i <- row until row + 3; j <- col until col + 3 if board(i)(j) == value) return false
|
||||
true // 最终没有返回false,就说明该位置可以填写true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
||||
@@ -291,7 +291,7 @@ class Solution:
|
||||
for i in range(start_index, len(candidates)):
|
||||
sum_ += candidates[i]
|
||||
self.path.append(candidates[i])
|
||||
self.backtracking(candidates, target, sum_, i) # 因为无限制重复选取,所以不是i-1
|
||||
self.backtracking(candidates, target, sum_, i) # 因为无限制重复选取,所以不是i+1
|
||||
sum_ -= candidates[i] # 回溯
|
||||
self.path.pop() # 回溯
|
||||
```
|
||||
@@ -502,5 +502,35 @@ func combinationSum(_ candidates: [Int], _ target: Int) -> [[Int]] {
|
||||
}
|
||||
```
|
||||
|
||||
## Scala
|
||||
|
||||
```scala
|
||||
object Solution {
|
||||
import scala.collection.mutable
|
||||
def combinationSum(candidates: Array[Int], target: Int): List[List[Int]] = {
|
||||
var result = mutable.ListBuffer[List[Int]]()
|
||||
var path = mutable.ListBuffer[Int]()
|
||||
|
||||
def backtracking(sum: Int, index: Int): Unit = {
|
||||
if (sum == target) {
|
||||
result.append(path.toList) // 如果正好等于target,就添加到结果集
|
||||
return
|
||||
}
|
||||
// 应该是从当前索引开始的,而不是从0
|
||||
// 剪枝优化:添加循环守卫,当sum + c(i) <= target的时候才循环,才可以进入下一次递归
|
||||
for (i <- index until candidates.size if sum + candidates(i) <= target) {
|
||||
path.append(candidates(i))
|
||||
backtracking(sum + candidates(i), i)
|
||||
path = path.take(path.size - 1)
|
||||
}
|
||||
}
|
||||
|
||||
backtracking(0, 0)
|
||||
result.toList
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
||||
@@ -693,5 +693,37 @@ func combinationSum2(_ candidates: [Int], _ target: Int) -> [[Int]] {
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Scala
|
||||
|
||||
```scala
|
||||
object Solution {
|
||||
import scala.collection.mutable
|
||||
def combinationSum2(candidates: Array[Int], target: Int): List[List[Int]] = {
|
||||
var res = mutable.ListBuffer[List[Int]]()
|
||||
var path = mutable.ListBuffer[Int]()
|
||||
var candidate = candidates.sorted
|
||||
|
||||
def backtracking(sum: Int, startIndex: Int): Unit = {
|
||||
if (sum == target) {
|
||||
res.append(path.toList)
|
||||
return
|
||||
}
|
||||
|
||||
for (i <- startIndex until candidate.size if sum + candidate(i) <= target) {
|
||||
if (!(i > startIndex && candidate(i) == candidate(i - 1))) {
|
||||
path.append(candidate(i))
|
||||
backtracking(sum + candidate(i), i + 1)
|
||||
path = path.take(path.size - 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
backtracking(0, 0)
|
||||
res.toList
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
||||
@@ -640,8 +640,44 @@ func min(a,b int)int{
|
||||
}
|
||||
```
|
||||
|
||||
单调栈解法
|
||||
```go
|
||||
func trap(height []int) int {
|
||||
if len(height) <= 2 {
|
||||
return 0
|
||||
}
|
||||
st := make([]int, 1, len(height)) // 切片模拟单调栈,st存储的是高度数组下标
|
||||
var res int
|
||||
for i := 1; i < len(height); i++ {
|
||||
if height[i] < height[st[len(st)-1]] {
|
||||
st = append(st, i)
|
||||
} else if height[i] == height[st[len(st)-1]] {
|
||||
st = st[:len(st)-1] // 比较的新元素和栈顶的元素相等,去掉栈中的,入栈新元素下标
|
||||
st = append(st, i)
|
||||
} else {
|
||||
for len(st) != 0 && height[i] > height[st[len(st)-1]] {
|
||||
top := st[len(st)-1]
|
||||
st = st[:len(st)-1]
|
||||
if len(st) != 0 {
|
||||
tmp := (min(height[i], height[st[len(st)-1]]) - height[top]) * (i - st[len(st)-1] - 1)
|
||||
res += tmp
|
||||
}
|
||||
}
|
||||
st = append(st, i)
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
|
||||
func min(x, y int) int {
|
||||
if x >= y {
|
||||
return y
|
||||
}
|
||||
return x
|
||||
}
|
||||
```
|
||||
|
||||
### JavaScript:
|
||||
|
||||
```javascript
|
||||
|
||||
@@ -279,7 +279,31 @@ function jump(nums: number[]): number {
|
||||
};
|
||||
```
|
||||
|
||||
### Scala
|
||||
|
||||
```scala
|
||||
object Solution {
|
||||
def jump(nums: Array[Int]): Int = {
|
||||
if (nums.length == 0) return 0
|
||||
var result = 0 // 记录走的最大步数
|
||||
var curDistance = 0 // 当前覆盖最远距离下标
|
||||
var nextDistance = 0 // 下一步覆盖最远距离下标
|
||||
for (i <- nums.indices) {
|
||||
nextDistance = math.max(nums(i) + i, nextDistance) // 更新下一步覆盖最远距离下标
|
||||
if (i == curDistance) {
|
||||
if (curDistance != nums.length - 1) {
|
||||
result += 1
|
||||
curDistance = nextDistance
|
||||
if (nextDistance >= nums.length - 1) return result
|
||||
} else {
|
||||
return result
|
||||
}
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -333,8 +333,41 @@ function maxSubArray(nums: number[]): number {
|
||||
};
|
||||
```
|
||||
|
||||
### Scala
|
||||
|
||||
**贪心**
|
||||
|
||||
```scala
|
||||
object Solution {
|
||||
def maxSubArray(nums: Array[Int]): Int = {
|
||||
var result = Int.MinValue
|
||||
var count = 0
|
||||
for (i <- nums.indices) {
|
||||
count += nums(i) // count累加
|
||||
if (count > result) result = count // 记录最大值
|
||||
if (count <= 0) count = 0 // 一旦count为负,则count归0
|
||||
}
|
||||
result
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**动态规划**
|
||||
|
||||
```scala
|
||||
object Solution {
|
||||
def maxSubArray(nums: Array[Int]): Int = {
|
||||
var dp = new Array[Int](nums.length)
|
||||
var result = nums(0)
|
||||
dp(0) = nums(0)
|
||||
for (i <- 1 until nums.length) {
|
||||
dp(i) = math.max(nums(i), dp(i - 1) + nums(i))
|
||||
result = math.max(result, dp(i)) // 更新最大值
|
||||
}
|
||||
result
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
||||
@@ -186,6 +186,24 @@ const maxSubArray = nums => {
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
Scala:
|
||||
|
||||
```scala
|
||||
object Solution {
|
||||
def maxSubArray(nums: Array[Int]): Int = {
|
||||
var dp = new Array[Int](nums.length)
|
||||
var result = nums(0)
|
||||
dp(0) = nums(0)
|
||||
for (i <- 1 until nums.length) {
|
||||
dp(i) = math.max(nums(i), dp(i - 1) + nums(i))
|
||||
result = math.max(result, dp(i)) // 更新最大值
|
||||
}
|
||||
result
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
TypeScript:
|
||||
|
||||
```typescript
|
||||
@@ -205,6 +223,5 @@ function maxSubArray(nums: number[]): number {
|
||||
```
|
||||
|
||||
|
||||
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
||||
@@ -193,7 +193,22 @@ function canJump(nums: number[]): boolean {
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
### Scala
|
||||
```scala
|
||||
object Solution {
|
||||
def canJump(nums: Array[Int]): Boolean = {
|
||||
var cover = 0
|
||||
if (nums.length == 1) return true // 如果只有一个元素,那么必定到达
|
||||
var i = 0
|
||||
while (i <= cover) { // i表示下标,当前只能够走cover步
|
||||
cover = math.max(i + nums(i), cover)
|
||||
if (cover >= nums.length - 1) return true // 说明可以覆盖到终点,直接返回
|
||||
i += 1
|
||||
}
|
||||
false // 如果上面没有返回就是跳不到
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
-----------------------
|
||||
|
||||
@@ -133,24 +133,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
|
||||
|
||||
@@ -374,6 +374,30 @@ function uniquePaths(m: number, n: number): number {
|
||||
};
|
||||
```
|
||||
|
||||
### Rust
|
||||
|
||||
```Rust
|
||||
impl Solution {
|
||||
pub fn unique_paths(m: i32, n: i32) -> i32 {
|
||||
let m = m as usize;
|
||||
let n = n as usize;
|
||||
let mut dp = vec![vec![0; n]; m];
|
||||
for i in 0..m {
|
||||
dp[i][0] = 1;
|
||||
}
|
||||
for j in 0..n {
|
||||
dp[0][j] = 1;
|
||||
}
|
||||
for i in 1..m {
|
||||
for j in 1..n {
|
||||
dp[i][j] = dp[i-1][j] + dp[i][j-1];
|
||||
}
|
||||
}
|
||||
dp[m-1][n-1]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### C
|
||||
|
||||
```c
|
||||
|
||||
@@ -384,6 +384,42 @@ function uniquePathsWithObstacles(obstacleGrid: number[][]): number {
|
||||
};
|
||||
```
|
||||
|
||||
### Rust
|
||||
|
||||
```Rust
|
||||
impl Solution {
|
||||
pub fn unique_paths_with_obstacles(obstacle_grid: Vec<Vec<i32>>) -> i32 {
|
||||
let m: usize = obstacle_grid.len();
|
||||
let n: usize = obstacle_grid[0].len();
|
||||
if obstacle_grid[0][0] == 1 || obstacle_grid[m-1][n-1] == 1 {
|
||||
return 0;
|
||||
}
|
||||
let mut dp = vec![vec![0; n]; m];
|
||||
for i in 0..m {
|
||||
if obstacle_grid[i][0] == 1 {
|
||||
break;
|
||||
}
|
||||
else { dp[i][0] = 1; }
|
||||
}
|
||||
for j in 0..n {
|
||||
if obstacle_grid[0][j] == 1 {
|
||||
break;
|
||||
}
|
||||
else { dp[0][j] = 1; }
|
||||
}
|
||||
for i in 1..m {
|
||||
for j in 1..n {
|
||||
if obstacle_grid[i][j] == 1 {
|
||||
continue;
|
||||
}
|
||||
dp[i][j] = dp[i-1][j] + dp[i][j-1];
|
||||
}
|
||||
}
|
||||
dp[m-1][n-1]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### C
|
||||
|
||||
```c
|
||||
|
||||
@@ -535,6 +535,56 @@ func backtrack(n,k,start int,track []int){
|
||||
}
|
||||
```
|
||||
|
||||
### Rust
|
||||
|
||||
```Rust
|
||||
impl Solution {
|
||||
fn backtracking(result: &mut Vec<Vec<i32>>, path: &mut Vec<i32>, n: i32, k: i32, startIndex: i32) {
|
||||
let len= path.len() as i32;
|
||||
if len == k{
|
||||
result.push(path.to_vec());
|
||||
return;
|
||||
}
|
||||
for i in startIndex..= n {
|
||||
path.push(i);
|
||||
Self::backtracking(result, path, n, k, i+1);
|
||||
path.pop();
|
||||
}
|
||||
}
|
||||
pub fn combine(n: i32, k: i32) -> Vec<Vec<i32>> {
|
||||
let mut result: Vec<Vec<i32>> = Vec::new();
|
||||
let mut path: Vec<i32> = Vec::new();
|
||||
Self::backtracking(&mut result, &mut path, n, k, 1);
|
||||
result
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
剪枝
|
||||
```Rust
|
||||
impl Solution {
|
||||
fn backtracking(result: &mut Vec<Vec<i32>>, path: &mut Vec<i32>, n: i32, k: i32, startIndex: i32) {
|
||||
let len= path.len() as i32;
|
||||
if len == k{
|
||||
result.push(path.to_vec());
|
||||
return;
|
||||
}
|
||||
// 此处剪枝
|
||||
for i in startIndex..= n - (k - len) + 1 {
|
||||
path.push(i);
|
||||
Self::backtracking(result, path, n, k, i+1);
|
||||
path.pop();
|
||||
}
|
||||
}
|
||||
pub fn combine(n: i32, k: i32) -> Vec<Vec<i32>> {
|
||||
let mut result: Vec<Vec<i32>> = Vec::new();
|
||||
let mut path: Vec<i32> = Vec::new();
|
||||
Self::backtracking(&mut result, &mut path, n, k, 1);
|
||||
result
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### C
|
||||
```c
|
||||
int* path;
|
||||
@@ -673,5 +723,63 @@ func combine(_ n: Int, _ k: Int) -> [[Int]] {
|
||||
}
|
||||
```
|
||||
|
||||
### Scala
|
||||
|
||||
暴力:
|
||||
```scala
|
||||
object Solution {
|
||||
import scala.collection.mutable // 导包
|
||||
def combine(n: Int, k: Int): List[List[Int]] = {
|
||||
var result = mutable.ListBuffer[List[Int]]() // 存放结果集
|
||||
var path = mutable.ListBuffer[Int]() //存放符合条件的结果
|
||||
|
||||
def backtracking(n: Int, k: Int, startIndex: Int): Unit = {
|
||||
if (path.size == k) {
|
||||
// 如果path的size == k就达到题目要求,添加到结果集,并返回
|
||||
result.append(path.toList)
|
||||
return
|
||||
}
|
||||
for (i <- startIndex to n) { // 遍历从startIndex到n
|
||||
path.append(i) // 先把数字添加进去
|
||||
backtracking(n, k, i + 1) // 进行下一步回溯
|
||||
path = path.take(path.size - 1) // 回溯完再删除掉刚刚添加的数字
|
||||
}
|
||||
}
|
||||
|
||||
backtracking(n, k, 1) // 执行回溯
|
||||
result.toList // 最终返回result的List形式,return关键字可以省略
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
剪枝:
|
||||
|
||||
```scala
|
||||
object Solution {
|
||||
import scala.collection.mutable // 导包
|
||||
def combine(n: Int, k: Int): List[List[Int]] = {
|
||||
var result = mutable.ListBuffer[List[Int]]() // 存放结果集
|
||||
var path = mutable.ListBuffer[Int]() //存放符合条件的结果
|
||||
|
||||
def backtracking(n: Int, k: Int, startIndex: Int): Unit = {
|
||||
if (path.size == k) {
|
||||
// 如果path的size == k就达到题目要求,添加到结果集,并返回
|
||||
result.append(path.toList)
|
||||
return
|
||||
}
|
||||
// 剪枝优化
|
||||
for (i <- startIndex to (n - (k - path.size) + 1)) {
|
||||
path.append(i) // 先把数字添加进去
|
||||
backtracking(n, k, i + 1) // 进行下一步回溯
|
||||
path = path.take(path.size - 1) // 回溯完再删除掉刚刚添加的数字
|
||||
}
|
||||
}
|
||||
|
||||
backtracking(n, k, 1) // 执行回溯
|
||||
result.toList // 最终返回result的List形式,return关键字可以省略
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
||||
@@ -261,6 +261,32 @@ function combine(n: number, k: number): number[][] {
|
||||
};
|
||||
```
|
||||
|
||||
Rust:
|
||||
|
||||
```Rust
|
||||
impl Solution {
|
||||
fn backtracking(result: &mut Vec<Vec<i32>>, path: &mut Vec<i32>, n: i32, k: i32, startIndex: i32) {
|
||||
let len= path.len() as i32;
|
||||
if len == k{
|
||||
result.push(path.to_vec());
|
||||
return;
|
||||
}
|
||||
// 此处剪枝
|
||||
for i in startIndex..= n - (k - len) + 1 {
|
||||
path.push(i);
|
||||
Self::backtracking(result, path, n, k, i+1);
|
||||
path.pop();
|
||||
}
|
||||
}
|
||||
pub fn combine(n: i32, k: i32) -> Vec<Vec<i32>> {
|
||||
let mut result: Vec<Vec<i32>> = Vec::new();
|
||||
let mut path: Vec<i32> = Vec::new();
|
||||
Self::backtracking(&mut result, &mut path, n, k, 1);
|
||||
result
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
C:
|
||||
|
||||
```c
|
||||
@@ -346,5 +372,34 @@ func combine(_ n: Int, _ k: Int) -> [[Int]] {
|
||||
}
|
||||
```
|
||||
|
||||
Scala:
|
||||
|
||||
```scala
|
||||
object Solution {
|
||||
import scala.collection.mutable // 导包
|
||||
def combine(n: Int, k: Int): List[List[Int]] = {
|
||||
var result = mutable.ListBuffer[List[Int]]() // 存放结果集
|
||||
var path = mutable.ListBuffer[Int]() //存放符合条件的结果
|
||||
|
||||
def backtracking(n: Int, k: Int, startIndex: Int): Unit = {
|
||||
if (path.size == k) {
|
||||
// 如果path的size == k就达到题目要求,添加到结果集,并返回
|
||||
result.append(path.toList)
|
||||
return
|
||||
}
|
||||
// 剪枝优化
|
||||
for (i <- startIndex to (n - (k - path.size) + 1)) {
|
||||
path.append(i) // 先把数字添加进去
|
||||
backtracking(n, k, i + 1) // 进行下一步回溯
|
||||
path = path.take(path.size - 1) // 回溯完再删除掉刚刚添加的数字
|
||||
}
|
||||
}
|
||||
|
||||
backtracking(n, k, 1) // 执行回溯
|
||||
result.toList // 最终返回result的List形式,return关键字可以省略
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -659,6 +659,48 @@ func restoreIpAddresses(_ s: String) -> [String] {
|
||||
}
|
||||
```
|
||||
|
||||
## Scala
|
||||
|
||||
```scala
|
||||
object Solution {
|
||||
import scala.collection.mutable
|
||||
def restoreIpAddresses(s: String): List[String] = {
|
||||
var result = mutable.ListBuffer[String]()
|
||||
if (s.size < 4 || s.length > 12) return result.toList
|
||||
var path = mutable.ListBuffer[String]()
|
||||
|
||||
// 判断IP中的一个字段是否为正确的
|
||||
def isIP(sub: String): Boolean = {
|
||||
if (sub.size > 1 && sub(0) == '0') return false
|
||||
if (sub.toInt > 255) return false
|
||||
true
|
||||
}
|
||||
|
||||
def backtracking(startIndex: Int): Unit = {
|
||||
if (startIndex >= s.size) {
|
||||
if (path.size == 4) {
|
||||
result.append(path.mkString(".")) // mkString方法可以把集合里的数据以指定字符串拼接
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
// subString
|
||||
for (i <- startIndex until startIndex + 3 if i < s.size) {
|
||||
var subString = s.substring(startIndex, i + 1)
|
||||
if (isIP(subString)) { // 如果合法则进行下一轮
|
||||
path.append(subString)
|
||||
backtracking(i + 1)
|
||||
path = path.take(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>
|
||||
|
||||
@@ -589,7 +589,50 @@ function isValidBST(root: TreeNode | null): boolean {
|
||||
};
|
||||
```
|
||||
|
||||
## Scala
|
||||
|
||||
辅助数组解决:
|
||||
```scala
|
||||
object Solution {
|
||||
import scala.collection.mutable
|
||||
def isValidBST(root: TreeNode): Boolean = {
|
||||
var arr = new mutable.ArrayBuffer[Int]()
|
||||
// 递归中序遍历二叉树,将节点添加到arr
|
||||
def traversal(node: TreeNode): Unit = {
|
||||
if (node == null) return
|
||||
traversal(node.left)
|
||||
arr.append(node.value)
|
||||
traversal(node.right)
|
||||
}
|
||||
traversal(root)
|
||||
// 这个数组如果是升序就代表是二叉搜索树
|
||||
for (i <- 1 until arr.size) {
|
||||
if (arr(i) <= arr(i - 1)) return false
|
||||
}
|
||||
true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
递归中解决:
|
||||
```scala
|
||||
object Solution {
|
||||
def isValidBST(root: TreeNode): Boolean = {
|
||||
var flag = true
|
||||
var preValue:Long = Long.MinValue // 这里要使用Long类型
|
||||
|
||||
def traversal(node: TreeNode): Unit = {
|
||||
if (node == null || flag == false) return
|
||||
traversal(node.left)
|
||||
if (node.value > preValue) preValue = node.value
|
||||
else flag = false
|
||||
traversal(node.right)
|
||||
}
|
||||
traversal(root)
|
||||
flag
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
||||
@@ -240,6 +240,46 @@ Go:
|
||||
|
||||
JavaScript:
|
||||
|
||||
TypeScript:
|
||||
|
||||
> 递归法-先序遍历
|
||||
|
||||
```typescript
|
||||
function isSameTree(p: TreeNode | null, q: TreeNode | null): boolean {
|
||||
if (p === null && q === null) return true;
|
||||
if (p === null || q === null) return false;
|
||||
if (p.val !== q.val) return false;
|
||||
return isSameTree(p.left, q.left) && isSameTree(p.right, q.right);
|
||||
};
|
||||
```
|
||||
|
||||
> 迭代法-层序遍历
|
||||
|
||||
```typescript
|
||||
function isSameTree(p: TreeNode | null, q: TreeNode | null): boolean {
|
||||
const queue1: (TreeNode | null)[] = [],
|
||||
queue2: (TreeNode | null)[] = [];
|
||||
queue1.push(p);
|
||||
queue2.push(q);
|
||||
while (queue1.length > 0 && queue2.length > 0) {
|
||||
const node1 = queue1.shift(),
|
||||
node2 = queue2.shift();
|
||||
if (node1 === null && node2 === null) continue;
|
||||
if (
|
||||
(node1 === null || node2 === null) ||
|
||||
node1!.val !== node2!.val
|
||||
) return false;
|
||||
queue1.push(node1!.left);
|
||||
queue1.push(node1!.right);
|
||||
queue2.push(node2!.left);
|
||||
queue2.push(node2!.right);
|
||||
}
|
||||
return true;
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
||||
@@ -437,6 +437,31 @@ class Solution:
|
||||
return True
|
||||
```
|
||||
|
||||
层次遍历
|
||||
```python
|
||||
class Solution:
|
||||
def isSymmetric(self, root: Optional[TreeNode]) -> bool:
|
||||
if not root:
|
||||
return True
|
||||
|
||||
que = [root]
|
||||
while que:
|
||||
this_level_length = len(que)
|
||||
for i in range(this_level_length // 2):
|
||||
# 要么其中一个是None但另外一个不是
|
||||
if (not que[i] and que[this_level_length - 1 - i]) or (que[i] and not que[this_level_length - 1 - i]):
|
||||
return False
|
||||
# 要么两个都不是None
|
||||
if que[i] and que[i].val != que[this_level_length - 1 - i].val:
|
||||
return False
|
||||
for i in range(this_level_length):
|
||||
if not que[i]: continue
|
||||
que.append(que[i].left)
|
||||
que.append(que[i].right)
|
||||
que = que[this_level_length:]
|
||||
return True
|
||||
```
|
||||
|
||||
## Go
|
||||
|
||||
```go
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -584,35 +584,29 @@ tree2 的前序遍历是[1 2 3], 后序遍历是[3 2 1]。
|
||||
|
||||
```java
|
||||
class Solution {
|
||||
Map<Integer, Integer> map; // 方便根据数值查找位置
|
||||
public TreeNode buildTree(int[] inorder, int[] postorder) {
|
||||
return buildTree1(inorder, 0, inorder.length, postorder, 0, postorder.length);
|
||||
map = new HashMap<>();
|
||||
for (int i = 0; i < inorder.length; i++) { // 用map保存中序序列的数值对应位置
|
||||
map.put(inorder[i], i);
|
||||
}
|
||||
|
||||
return findNode(inorder, 0, inorder.length, postorder,0, postorder.length); // 前闭后开
|
||||
}
|
||||
public TreeNode buildTree1(int[] inorder, int inLeft, int inRight,
|
||||
int[] postorder, int postLeft, int postRight) {
|
||||
// 没有元素了
|
||||
if (inRight - inLeft < 1) {
|
||||
|
||||
public TreeNode findNode(int[] inorder, int inBegin, int inEnd, int[] postorder, int postBegin, int postEnd) {
|
||||
// 参数里的范围都是前闭后开
|
||||
if (inBegin >= inEnd || postBegin >= postEnd) { // 不满足左闭右开,说明没有元素,返回空树
|
||||
return null;
|
||||
}
|
||||
// 只有一个元素了
|
||||
if (inRight - inLeft == 1) {
|
||||
return new TreeNode(inorder[inLeft]);
|
||||
}
|
||||
// 后序数组postorder里最后一个即为根结点
|
||||
int rootVal = postorder[postRight - 1];
|
||||
TreeNode root = new TreeNode(rootVal);
|
||||
int rootIndex = 0;
|
||||
// 根据根结点的值找到该值在中序数组inorder里的位置
|
||||
for (int i = inLeft; i < inRight; i++) {
|
||||
if (inorder[i] == rootVal) {
|
||||
rootIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// 根据rootIndex划分左右子树
|
||||
root.left = buildTree1(inorder, inLeft, rootIndex,
|
||||
postorder, postLeft, postLeft + (rootIndex - inLeft));
|
||||
root.right = buildTree1(inorder, rootIndex + 1, inRight,
|
||||
postorder, postLeft + (rootIndex - inLeft), postRight - 1);
|
||||
int rootIndex = map.get(postorder[postEnd - 1]); // 找到后序遍历的最后一个元素在中序遍历中的位置
|
||||
TreeNode root = new TreeNode(inorder[rootIndex]); // 构造结点
|
||||
int lenOfLeft = rootIndex - inBegin; // 保存中序左子树个数,用来确定后序数列的个数
|
||||
root.left = findNode(inorder, inBegin, rootIndex,
|
||||
postorder, postBegin, postBegin + lenOfLeft);
|
||||
root.right = findNode(inorder, rootIndex + 1, inEnd,
|
||||
postorder, postBegin + lenOfLeft, postEnd - 1);
|
||||
|
||||
return root;
|
||||
}
|
||||
}
|
||||
@@ -622,31 +616,29 @@ class Solution {
|
||||
|
||||
```java
|
||||
class Solution {
|
||||
Map<Integer, Integer> map;
|
||||
public TreeNode buildTree(int[] preorder, int[] inorder) {
|
||||
return helper(preorder, 0, preorder.length - 1, inorder, 0, inorder.length - 1);
|
||||
}
|
||||
|
||||
public TreeNode helper(int[] preorder, int preLeft, int preRight,
|
||||
int[] inorder, int inLeft, int inRight) {
|
||||
// 递归终止条件
|
||||
if (inLeft > inRight || preLeft > preRight) return null;
|
||||
|
||||
// val 为前序遍历第一个的值,也即是根节点的值
|
||||
// idx 为根据根节点的值来找中序遍历的下标
|
||||
int idx = inLeft, val = preorder[preLeft];
|
||||
TreeNode root = new TreeNode(val);
|
||||
for (int i = inLeft; i <= inRight; i++) {
|
||||
if (inorder[i] == val) {
|
||||
idx = i;
|
||||
break;
|
||||
}
|
||||
map = new HashMap<>();
|
||||
for (int i = 0; i < inorder.length; i++) { // 用map保存中序序列的数值对应位置
|
||||
map.put(inorder[i], i);
|
||||
}
|
||||
|
||||
// 根据 idx 来递归找左右子树
|
||||
root.left = helper(preorder, preLeft + 1, preLeft + (idx - inLeft),
|
||||
inorder, inLeft, idx - 1);
|
||||
root.right = helper(preorder, preLeft + (idx - inLeft) + 1, preRight,
|
||||
inorder, idx + 1, inRight);
|
||||
return findNode(preorder, 0, preorder.length, inorder, 0, inorder.length); // 前闭后开
|
||||
}
|
||||
|
||||
public TreeNode findNode(int[] preorder, int preBegin, int preEnd, int[] inorder, int inBegin, int inEnd) {
|
||||
// 参数里的范围都是前闭后开
|
||||
if (preBegin >= preEnd || inBegin >= inEnd) { // 不满足左闭右开,说明没有元素,返回空树
|
||||
return null;
|
||||
}
|
||||
int rootIndex = map.get(preorder[preBegin]); // 找到前序遍历的第一个元素在中序遍历中的位置
|
||||
TreeNode root = new TreeNode(inorder[rootIndex]); // 构造结点
|
||||
int lenOfLeft = rootIndex - inBegin; // 保存中序左子树个数,用来确定前序数列的个数
|
||||
root.left = findNode(preorder, preBegin + 1, preBegin + lenOfLeft + 1,
|
||||
inorder, inBegin, rootIndex);
|
||||
root.right = findNode(preorder, preBegin + lenOfLeft + 1, preEnd,
|
||||
inorder, rootIndex + 1, inEnd);
|
||||
|
||||
return root;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -448,5 +448,27 @@ struct TreeNode* sortedArrayToBST(int* nums, int numsSize) {
|
||||
}
|
||||
```
|
||||
|
||||
## Scala
|
||||
|
||||
递归:
|
||||
|
||||
```scala
|
||||
object Solution {
|
||||
def sortedArrayToBST(nums: Array[Int]): TreeNode = {
|
||||
def buildTree(left: Int, right: Int): TreeNode = {
|
||||
if (left > right) return null // 当left大于right的时候,返回空
|
||||
// 最中间的节点是当前节点
|
||||
var mid = left + (right - left) / 2
|
||||
var curNode = new TreeNode(nums(mid))
|
||||
curNode.left = buildTree(left, mid - 1)
|
||||
curNode.right = buildTree(mid + 1, right)
|
||||
curNode
|
||||
}
|
||||
buildTree(0, nums.size - 1)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
||||
@@ -531,40 +531,26 @@ class Solution:
|
||||
迭代法:
|
||||
```python
|
||||
class Solution:
|
||||
def isBalanced(self, root: TreeNode) -> bool:
|
||||
st = []
|
||||
def isBalanced(self, root: Optional[TreeNode]) -> bool:
|
||||
if not root:
|
||||
return True
|
||||
st.append(root)
|
||||
while st:
|
||||
node = st.pop() #中
|
||||
if abs(self.getDepth(node.left) - self.getDepth(node.right)) > 1:
|
||||
return False
|
||||
if node.right:
|
||||
st.append(node.right) #右(空节点不入栈)
|
||||
if node.left:
|
||||
st.append(node.left) #左(空节点不入栈)
|
||||
return True
|
||||
|
||||
def getDepth(self, cur):
|
||||
st = []
|
||||
if cur:
|
||||
st.append(cur)
|
||||
depth = 0
|
||||
result = 0
|
||||
while st:
|
||||
node = st.pop()
|
||||
|
||||
height_map = {}
|
||||
stack = [root]
|
||||
while stack:
|
||||
node = stack.pop()
|
||||
if node:
|
||||
st.append(node) #中
|
||||
st.append(None)
|
||||
depth += 1
|
||||
if node.right: st.append(node.right) #右
|
||||
if node.left: st.append(node.left) #左
|
||||
stack.append(node)
|
||||
stack.append(None)
|
||||
if node.left: stack.append(node.left)
|
||||
if node.right: stack.append(node.right)
|
||||
else:
|
||||
node = st.pop()
|
||||
depth -= 1
|
||||
result = max(result, depth)
|
||||
return result
|
||||
real_node = stack.pop()
|
||||
left, right = height_map.get(real_node.left, 0), height_map.get(real_node.right, 0)
|
||||
if abs(left - right) > 1:
|
||||
return False
|
||||
height_map[real_node] = 1 + max(left, right)
|
||||
return True
|
||||
```
|
||||
|
||||
|
||||
|
||||
@@ -287,6 +287,79 @@ const connect = root => {
|
||||
};
|
||||
```
|
||||
|
||||
## TypeScript
|
||||
|
||||
(注:命名空间‘Node’与typescript中内置类型冲突,这里改成了‘NodePro’)
|
||||
|
||||
> 递归法:
|
||||
|
||||
```typescript
|
||||
class NodePro {
|
||||
val: number
|
||||
left: NodePro | null
|
||||
right: NodePro | null
|
||||
next: NodePro | null
|
||||
constructor(val?: number, left?: NodePro, right?: NodePro, next?: NodePro) {
|
||||
this.val = (val === undefined ? 0 : val)
|
||||
this.left = (left === undefined ? null : left)
|
||||
this.right = (right === undefined ? null : right)
|
||||
this.next = (next === undefined ? null : next)
|
||||
}
|
||||
}
|
||||
|
||||
function connect(root: NodePro | null): NodePro | null {
|
||||
if (root === null) return null;
|
||||
root.next = null;
|
||||
recur(root);
|
||||
return root;
|
||||
};
|
||||
function recur(node: NodePro): void {
|
||||
if (node.left === null || node.right === null) return;
|
||||
node.left.next = node.right;
|
||||
node.right.next = node.next && node.next.left;
|
||||
recur(node.left);
|
||||
recur(node.right);
|
||||
}
|
||||
```
|
||||
|
||||
> 迭代法:
|
||||
|
||||
```typescript
|
||||
class NodePro {
|
||||
val: number
|
||||
left: NodePro | null
|
||||
right: NodePro | null
|
||||
next: NodePro | null
|
||||
constructor(val?: number, left?: NodePro, right?: NodePro, next?: NodePro) {
|
||||
this.val = (val === undefined ? 0 : val)
|
||||
this.left = (left === undefined ? null : left)
|
||||
this.right = (right === undefined ? null : right)
|
||||
this.next = (next === undefined ? null : next)
|
||||
}
|
||||
}
|
||||
|
||||
function connect(root: NodePro | null): NodePro | null {
|
||||
if (root === null) return null;
|
||||
const queue: NodePro[] = [];
|
||||
queue.push(root);
|
||||
while (queue.length > 0) {
|
||||
for (let i = 0, length = queue.length; i < length; i++) {
|
||||
const curNode: NodePro = queue.shift()!;
|
||||
if (i === length - 1) {
|
||||
curNode.next = null;
|
||||
} else {
|
||||
curNode.next = queue[0];
|
||||
}
|
||||
if (curNode.left !== null) queue.push(curNode.left);
|
||||
if (curNode.right !== null) queue.push(curNode.right);
|
||||
}
|
||||
}
|
||||
return root;
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
||||
@@ -133,8 +133,9 @@ public:
|
||||
|
||||
## 其他语言版本
|
||||
|
||||
Java:
|
||||
### Java:
|
||||
|
||||
贪心:
|
||||
```java
|
||||
// 贪心思路
|
||||
class Solution {
|
||||
@@ -148,6 +149,7 @@ class Solution {
|
||||
}
|
||||
```
|
||||
|
||||
动态规划:
|
||||
```java
|
||||
class Solution { // 动态规划
|
||||
public int maxProfit(int[] prices) {
|
||||
@@ -169,8 +171,8 @@ class Solution { // 动态规划
|
||||
}
|
||||
```
|
||||
|
||||
Python:
|
||||
|
||||
### Python:
|
||||
贪心:
|
||||
```python
|
||||
class Solution:
|
||||
def maxProfit(self, prices: List[int]) -> int:
|
||||
@@ -180,7 +182,7 @@ class Solution:
|
||||
return result
|
||||
```
|
||||
|
||||
python动态规划
|
||||
动态规划:
|
||||
```python
|
||||
class Solution:
|
||||
def maxProfit(self, prices: List[int]) -> int:
|
||||
@@ -194,7 +196,7 @@ class Solution:
|
||||
return dp[-1][1]
|
||||
```
|
||||
|
||||
Go:
|
||||
### Go:
|
||||
|
||||
```golang
|
||||
//贪心算法
|
||||
@@ -231,7 +233,7 @@ func maxProfit(prices []int) int {
|
||||
}
|
||||
```
|
||||
|
||||
Javascript:
|
||||
### Javascript:
|
||||
|
||||
贪心
|
||||
```Javascript
|
||||
@@ -268,7 +270,7 @@ const maxProfit = (prices) => {
|
||||
};
|
||||
```
|
||||
|
||||
TypeScript:
|
||||
### TypeScript:
|
||||
|
||||
```typescript
|
||||
function maxProfit(prices: number[]): number {
|
||||
@@ -280,7 +282,7 @@ function maxProfit(prices: number[]): number {
|
||||
};
|
||||
```
|
||||
|
||||
C:
|
||||
### C:
|
||||
贪心:
|
||||
```c
|
||||
int maxProfit(int* prices, int pricesSize){
|
||||
@@ -318,5 +320,22 @@ int maxProfit(int* prices, int pricesSize){
|
||||
}
|
||||
```
|
||||
|
||||
### Scala
|
||||
|
||||
贪心:
|
||||
```scala
|
||||
object Solution {
|
||||
def maxProfit(prices: Array[Int]): Int = {
|
||||
var result = 0
|
||||
for (i <- 1 until prices.length) {
|
||||
if (prices(i) > prices(i - 1)) {
|
||||
result += prices(i) - prices(i - 1)
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
||||
@@ -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) {
|
||||
@@ -289,7 +315,40 @@ var sumNumbers = function(root) {
|
||||
};
|
||||
```
|
||||
|
||||
TypeScript:
|
||||
|
||||
```typescript
|
||||
function sumNumbers(root: TreeNode | null): number {
|
||||
if (root === null) return 0;
|
||||
let resTotal: number = 0;
|
||||
const route: number[] = [];
|
||||
route.push(root.val);
|
||||
recur(root, route);
|
||||
return resTotal;
|
||||
function recur(node: TreeNode, route: number[]): void {
|
||||
if (node.left === null && node.right === null) {
|
||||
resTotal += listToSum(route);
|
||||
return;
|
||||
}
|
||||
if (node.left !== null) {
|
||||
route.push(node.left.val);
|
||||
recur(node.left, route);
|
||||
route.pop();
|
||||
};
|
||||
if (node.right !== null) {
|
||||
route.push(node.right.val);
|
||||
recur(node.right, route);
|
||||
route.pop();
|
||||
};
|
||||
}
|
||||
function listToSum(nums: number[]): number {
|
||||
return Number(nums.join(''));
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
C:
|
||||
|
||||
```c
|
||||
//sum记录总和
|
||||
int sum;
|
||||
|
||||
@@ -676,5 +676,50 @@ impl Solution {
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Scala
|
||||
|
||||
```scala
|
||||
object Solution {
|
||||
|
||||
import scala.collection.mutable
|
||||
|
||||
def partition(s: String): List[List[String]] = {
|
||||
var result = mutable.ListBuffer[List[String]]()
|
||||
var path = mutable.ListBuffer[String]()
|
||||
|
||||
// 判断字符串是否回文
|
||||
def isPalindrome(start: Int, end: Int): Boolean = {
|
||||
var (left, right) = (start, end)
|
||||
while (left < right) {
|
||||
if (s(left) != s(right)) return false
|
||||
left += 1
|
||||
right -= 1
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
// 回溯算法
|
||||
def backtracking(startIndex: Int): Unit = {
|
||||
if (startIndex >= s.size) {
|
||||
result.append(path.toList)
|
||||
return
|
||||
}
|
||||
// 添加循环守卫,如果当前分割是回文子串则进入回溯
|
||||
for (i <- startIndex until s.size if isPalindrome(startIndex, i)) {
|
||||
path.append(s.substring(startIndex, i + 1))
|
||||
backtracking(i + 1)
|
||||
path = path.take(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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
|
||||
# 141. 环形链表
|
||||
|
||||
[力扣题目链接](https://leetcode.cn/problems/linked-list-cycle/submissions/)
|
||||
|
||||
给定一个链表,判断链表中是否有环。
|
||||
|
||||
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。
|
||||
@@ -103,7 +105,7 @@ class Solution:
|
||||
return False
|
||||
```
|
||||
|
||||
## Go
|
||||
### Go
|
||||
|
||||
```go
|
||||
func hasCycle(head *ListNode) bool {
|
||||
@@ -139,6 +141,23 @@ var hasCycle = function(head) {
|
||||
};
|
||||
```
|
||||
|
||||
### TypeScript
|
||||
|
||||
```typescript
|
||||
function hasCycle(head: ListNode | null): boolean {
|
||||
let slowNode: ListNode | null = head,
|
||||
fastNode: ListNode | null = head;
|
||||
while (fastNode !== null && fastNode.next !== null) {
|
||||
slowNode = slowNode!.next;
|
||||
fastNode = fastNode.next.next;
|
||||
if (slowNode === fastNode) return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
||||
@@ -303,13 +303,13 @@ function detectCycle(head: ListNode | null): ListNode | null {
|
||||
let slowNode: ListNode | null = head,
|
||||
fastNode: ListNode | null = head;
|
||||
while (fastNode !== null && fastNode.next !== null) {
|
||||
slowNode = (slowNode as ListNode).next;
|
||||
slowNode = slowNode!.next;
|
||||
fastNode = fastNode.next.next;
|
||||
if (slowNode === fastNode) {
|
||||
slowNode = head;
|
||||
while (slowNode !== fastNode) {
|
||||
slowNode = (slowNode as ListNode).next;
|
||||
fastNode = (fastNode as ListNode).next;
|
||||
slowNode = slowNode!.next;
|
||||
fastNode = fastNode!.next;
|
||||
}
|
||||
return slowNode;
|
||||
}
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
|
||||
# 143.重排链表
|
||||
|
||||
[力扣题目链接](https://leetcode.cn/problems/reorder-list/submissions/)
|
||||
|
||||

|
||||
|
||||
## 思路
|
||||
@@ -465,7 +467,81 @@ var reorderList = function(head, s = [], tmp) {
|
||||
}
|
||||
```
|
||||
|
||||
### TypeScript
|
||||
|
||||
> 辅助数组法:
|
||||
|
||||
```typescript
|
||||
function reorderList(head: ListNode | null): void {
|
||||
if (head === null) return;
|
||||
const helperArr: ListNode[] = [];
|
||||
let curNode: ListNode | null = head;
|
||||
while (curNode !== null) {
|
||||
helperArr.push(curNode);
|
||||
curNode = curNode.next;
|
||||
}
|
||||
let node: ListNode = head;
|
||||
let left: number = 1,
|
||||
right: number = helperArr.length - 1;
|
||||
let count: number = 0;
|
||||
while (left <= right) {
|
||||
if (count % 2 === 0) {
|
||||
node.next = helperArr[right--];
|
||||
} else {
|
||||
node.next = helperArr[left++];
|
||||
}
|
||||
count++;
|
||||
node = node.next;
|
||||
}
|
||||
node.next = null;
|
||||
};
|
||||
```
|
||||
|
||||
> 分割链表法:
|
||||
|
||||
```typescript
|
||||
function reorderList(head: ListNode | null): void {
|
||||
if (head === null || head.next === null) return;
|
||||
let fastNode: ListNode = head,
|
||||
slowNode: ListNode = head;
|
||||
while (fastNode.next !== null && fastNode.next.next !== null) {
|
||||
slowNode = slowNode.next!;
|
||||
fastNode = fastNode.next.next;
|
||||
}
|
||||
let head1: ListNode | null = head;
|
||||
// 反转后半部分链表
|
||||
let head2: ListNode | null = reverseList(slowNode.next);
|
||||
// 分割链表
|
||||
slowNode.next = null;
|
||||
/**
|
||||
直接在head1链表上进行插入
|
||||
head1 链表长度一定大于或等于head2,
|
||||
因此在下面的循环中,只要head2不为null, head1 一定不为null
|
||||
*/
|
||||
while (head2 !== null) {
|
||||
const tempNode1: ListNode | null = head1!.next,
|
||||
tempNode2: ListNode | null = head2.next;
|
||||
head1!.next = head2;
|
||||
head2.next = tempNode1;
|
||||
head1 = tempNode1;
|
||||
head2 = tempNode2;
|
||||
}
|
||||
};
|
||||
function reverseList(head: ListNode | null): ListNode | null {
|
||||
let curNode: ListNode | null = head,
|
||||
preNode: ListNode | null = null;
|
||||
while (curNode !== null) {
|
||||
const tempNode: ListNode | null = curNode.next;
|
||||
curNode.next = preNode;
|
||||
preNode = curNode;
|
||||
curNode = tempNode;
|
||||
}
|
||||
return preNode;
|
||||
}
|
||||
```
|
||||
|
||||
### C
|
||||
|
||||
方法三:反转链表
|
||||
```c
|
||||
//翻转链表
|
||||
|
||||
@@ -325,6 +325,33 @@ func evalRPN(_ tokens: [String]) -> Int {
|
||||
return stack.last!
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
PHP:
|
||||
```php
|
||||
class Solution {
|
||||
function evalRPN($tokens) {
|
||||
$st = new SplStack();
|
||||
for($i = 0;$i<count($tokens);$i++){
|
||||
// 是数字直接入栈
|
||||
if(is_numeric($tokens[$i])){
|
||||
$st->push($tokens[$i]);
|
||||
}else{
|
||||
// 是符号进行运算
|
||||
$num1 = $st->pop();
|
||||
$num2 = $st->pop();
|
||||
if ($tokens[$i] == "+") $st->push($num2 + $num1);
|
||||
if ($tokens[$i] == "-") $st->push($num2 - $num1);
|
||||
if ($tokens[$i] == "*") $st->push($num2 * $num1);
|
||||
// 注意处理小数部分
|
||||
if ($tokens[$i] == "/") $st->push(intval($num2 / $num1));
|
||||
}
|
||||
}
|
||||
return $st->pop();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Scala:
|
||||
```scala
|
||||
object Solution {
|
||||
@@ -351,6 +378,7 @@ object Solution {
|
||||
// 最后返回栈顶,不需要加return关键字
|
||||
stack.pop()
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
-----------------------
|
||||
|
||||
@@ -79,7 +79,7 @@ void removeExtraSpaces(string& s) {
|
||||
|
||||
逻辑很简单,从前向后遍历,遇到空格了就erase。
|
||||
|
||||
如果不仔细琢磨一下erase的时间复杂读,还以为以上的代码是O(n)的时间复杂度呢。
|
||||
如果不仔细琢磨一下erase的时间复杂度,还以为以上的代码是O(n)的时间复杂度呢。
|
||||
|
||||
想一下真正的时间复杂度是多少,一个erase本来就是O(n)的操作,erase实现原理题目:[数组:就移除个元素很难么?](https://programmercarl.com/0027.移除元素.html),最优的算法来移除元素也要O(n)。
|
||||
|
||||
@@ -864,7 +864,58 @@ function reverseString(&$s, $start, $end) {
|
||||
return ;
|
||||
}
|
||||
```
|
||||
Rust:
|
||||
|
||||
```Rust
|
||||
// 根据C++版本二思路进行实现
|
||||
// 函数名根据Rust编译器建议由驼峰命名法改为蛇形命名法
|
||||
impl Solution {
|
||||
pub fn reverse(s: &mut Vec<char>, mut begin: usize, mut end: usize){
|
||||
while begin < end {
|
||||
let temp = s[begin];
|
||||
s[begin] = s[end];
|
||||
s[end] = temp;
|
||||
begin += 1;
|
||||
end -= 1;
|
||||
}
|
||||
}
|
||||
pub fn remove_extra_spaces(s: &mut Vec<char>) {
|
||||
let mut slow: usize = 0;
|
||||
let len = s.len();
|
||||
// 注意这里不能用for循环,不然在里面那个while循环中对i的递增会失效
|
||||
let mut i: usize = 0;
|
||||
while i < len {
|
||||
if !s[i].is_ascii_whitespace() {
|
||||
if slow != 0 {
|
||||
s[slow] = ' ';
|
||||
slow += 1;
|
||||
}
|
||||
while i < len && !s[i].is_ascii_whitespace() {
|
||||
s[slow] = s[i];
|
||||
slow += 1;
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
s.resize(slow, ' ');
|
||||
}
|
||||
pub fn reverse_words(s: String) -> String {
|
||||
let mut s = s.chars().collect::<Vec<char>>();
|
||||
Self::remove_extra_spaces(&mut s);
|
||||
let len = s.len();
|
||||
Self::reverse(&mut s, 0, len - 1);
|
||||
let mut start = 0;
|
||||
for i in 0..=len {
|
||||
if i == len || s[i].is_ascii_whitespace() {
|
||||
Self::reverse(&mut s, start, i - 1);
|
||||
start = i + 1;
|
||||
}
|
||||
}
|
||||
s.iter().collect::<String>()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
|
||||
# 189. 旋转数组
|
||||
|
||||
[力扣题目链接](https://leetcode.cn/problems/rotate-array/)
|
||||
|
||||
给定一个数组,将数组中的元素向右移动 k 个位置,其中 k 是非负数。
|
||||
|
||||
进阶:
|
||||
@@ -160,6 +162,27 @@ var rotate = function (nums, k) {
|
||||
};
|
||||
```
|
||||
|
||||
## TypeScript
|
||||
|
||||
```typescript
|
||||
function rotate(nums: number[], k: number): void {
|
||||
const length: number = nums.length;
|
||||
k %= length;
|
||||
reverseByRange(nums, 0, length - 1);
|
||||
reverseByRange(nums, 0, k - 1);
|
||||
reverseByRange(nums, k, length - 1);
|
||||
};
|
||||
function reverseByRange(nums: number[], left: number, right: number): void {
|
||||
while (left < right) {
|
||||
const temp = nums[left];
|
||||
nums[left] = nums[right];
|
||||
nums[right] = temp;
|
||||
left++;
|
||||
right--;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
-----------------------
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -397,18 +397,18 @@ function removeElements(head: ListNode | null, val: number): ListNode | null {
|
||||
|
||||
```typescript
|
||||
function removeElements(head: ListNode | null, val: number): ListNode | null {
|
||||
let dummyHead = new ListNode(0, head);
|
||||
let pre: ListNode = dummyHead, cur: ListNode | null = dummyHead.next;
|
||||
// 删除非头部节点
|
||||
// 添加虚拟节点
|
||||
const data = new ListNode(0, head);
|
||||
let pre = data, cur = data.next;
|
||||
while (cur) {
|
||||
if (cur.val === val) {
|
||||
pre.next = cur.next;
|
||||
pre.next = cur.next
|
||||
} else {
|
||||
pre = cur;
|
||||
}
|
||||
cur = cur.next;
|
||||
}
|
||||
return head.next;
|
||||
return data.next;
|
||||
};
|
||||
```
|
||||
|
||||
@@ -487,17 +487,19 @@ RUST:
|
||||
// }
|
||||
impl Solution {
|
||||
pub fn remove_elements(head: Option<Box<ListNode>>, val: i32) -> Option<Box<ListNode>> {
|
||||
let mut head = head;
|
||||
let mut dummy_head = ListNode::new(0);
|
||||
let mut cur = &mut dummy_head;
|
||||
while let Some(mut node) = head {
|
||||
head = std::mem::replace(&mut node.next, None);
|
||||
if node.val != val {
|
||||
cur.next = Some(node);
|
||||
let mut dummyHead = Box::new(ListNode::new(0));
|
||||
dummyHead.next = head;
|
||||
let mut cur = dummyHead.as_mut();
|
||||
// 使用take()替换std::men::replace(&mut node.next, None)达到相同的效果,并且更普遍易读
|
||||
while let Some(nxt) = cur.next.take() {
|
||||
if nxt.val == val {
|
||||
cur.next = nxt.next;
|
||||
} else {
|
||||
cur.next = Some(nxt);
|
||||
cur = cur.next.as_mut().unwrap();
|
||||
}
|
||||
}
|
||||
dummy_head.next
|
||||
dummyHead.next
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -532,5 +534,39 @@ object Solution {
|
||||
}
|
||||
}
|
||||
```
|
||||
Kotlin:
|
||||
```kotlin
|
||||
/**
|
||||
* Example:
|
||||
* var li = ListNode(5)
|
||||
* var v = li.`val`
|
||||
* Definition for singly-linked list.
|
||||
* class ListNode(var `val`: Int) {
|
||||
* var next: ListNode? = null
|
||||
* }
|
||||
*/
|
||||
class Solution {
|
||||
fun removeElements(head: ListNode?, `val`: Int): ListNode? {
|
||||
// 使用虚拟节点,令该节点指向head
|
||||
var dummyNode = ListNode(-1)
|
||||
dummyNode.next = head
|
||||
// 使用cur遍历链表各个节点
|
||||
var cur = dummyNode
|
||||
// 判断下个节点是否为空
|
||||
while (cur.next != null) {
|
||||
// 符合条件,移除节点
|
||||
if (cur.next.`val` == `val`) {
|
||||
cur.next = cur.next.next
|
||||
}
|
||||
// 不符合条件,遍历下一节点
|
||||
else {
|
||||
cur = cur.next
|
||||
}
|
||||
}
|
||||
// 注意:返回的不是虚拟节点
|
||||
return dummyNode.next
|
||||
}
|
||||
}
|
||||
```
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -422,6 +422,41 @@ fun reverseList(head: ListNode?): ListNode? {
|
||||
return pre
|
||||
}
|
||||
```
|
||||
```kotlin
|
||||
/**
|
||||
* Example:
|
||||
* var li = ListNode(5)
|
||||
* var v = li.`val`
|
||||
* Definition for singly-linked list.
|
||||
* class ListNode(var `val`: Int) {
|
||||
* var next: ListNode? = null
|
||||
* }
|
||||
*/
|
||||
class Solution {
|
||||
fun reverseList(head: ListNode?): ListNode? {
|
||||
// temp用来存储临时的节点
|
||||
var temp: ListNode?
|
||||
// cur用来遍历链表
|
||||
var cur: ListNode? = head
|
||||
// pre用来作为链表反转的工具
|
||||
// pre是比pre前一位的节点
|
||||
var pre: ListNode? = null
|
||||
while (cur != null) {
|
||||
// 临时存储原本cur的下一个节点
|
||||
temp = cur.next
|
||||
// 使cur下一节点地址为它之前的
|
||||
cur.next = pre
|
||||
// 之后随着cur的遍历移动pre
|
||||
pre = cur;
|
||||
// 移动cur遍历链表各个节点
|
||||
cur = temp;
|
||||
}
|
||||
// 由于开头使用pre为null,所以cur等于链表本身长度+1,
|
||||
// 此时pre在cur前一位,所以此时pre为头节点
|
||||
return pre;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Swift:
|
||||
```swift
|
||||
|
||||
@@ -417,6 +417,38 @@ class Solution {
|
||||
}
|
||||
}
|
||||
```
|
||||
滑动窗口
|
||||
```kotlin
|
||||
class Solution {
|
||||
fun minSubArrayLen(target: Int, nums: IntArray): Int {
|
||||
// 左边界 和 右边界
|
||||
var left: Int = 0
|
||||
var right: Int = 0
|
||||
// sum 用来记录和
|
||||
var sum: Int = 0
|
||||
// result记录一个固定值,便于判断是否存在的这样的数组
|
||||
var result: Int = Int.MAX_VALUE
|
||||
// subLenth记录长度
|
||||
var subLength = Int.MAX_VALUE
|
||||
|
||||
|
||||
while (right < nums.size) {
|
||||
// 从数组首元素开始逐次求和
|
||||
sum += nums[right++]
|
||||
// 判断
|
||||
while (sum >= target) {
|
||||
var temp = right - left
|
||||
// 每次和上一次比较求出最小数组长度
|
||||
subLength = if (subLength > temp) temp else subLength
|
||||
// sum减少,左边界右移
|
||||
sum -= nums[left++]
|
||||
}
|
||||
}
|
||||
// 如果subLength为初始值,则说明长度为0,否则返回subLength
|
||||
return if(subLength == result) 0 else subLength
|
||||
}
|
||||
}
|
||||
```
|
||||
Scala:
|
||||
|
||||
滑动窗口:
|
||||
@@ -465,6 +497,27 @@ object Solution {
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
C#:
|
||||
```csharp
|
||||
public class Solution {
|
||||
public int MinSubArrayLen(int s, int[] nums) {
|
||||
int n = nums.Length;
|
||||
int ans = int.MaxValue;
|
||||
int start = 0, end = 0;
|
||||
int sum = 0;
|
||||
while (end < n) {
|
||||
sum += nums[end];
|
||||
while (sum >= s)
|
||||
{
|
||||
ans = Math.Min(ans, end - start + 1);
|
||||
sum -= nums[start];
|
||||
start++;
|
||||
}
|
||||
end++;
|
||||
}
|
||||
return ans == int.MaxValue ? 0 : ans;
|
||||
}
|
||||
}
|
||||
```
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
||||
@@ -411,6 +411,35 @@ function combinationSum3(k: number, n: number): number[][] {
|
||||
};
|
||||
```
|
||||
|
||||
## Rust
|
||||
|
||||
```Rust
|
||||
impl Solution {
|
||||
fn backtracking(result: &mut Vec<Vec<i32>>, path:&mut Vec<i32>, targetSum:i32, k: i32, mut sum: i32, startIndex: i32) {
|
||||
let len = path.len() as i32;
|
||||
if len == k {
|
||||
if sum == targetSum {
|
||||
result.push(path.to_vec());
|
||||
}
|
||||
return;
|
||||
}
|
||||
for i in startIndex..=9 {
|
||||
sum += i;
|
||||
path.push(i);
|
||||
Self::backtracking(result, path, targetSum, k, sum, i+1);
|
||||
sum -= i;
|
||||
path.pop();
|
||||
}
|
||||
}
|
||||
pub fn combination_sum3(k: i32, n: i32) -> Vec<Vec<i32>> {
|
||||
let mut result: Vec<Vec<i32>> = Vec::new();
|
||||
let mut path: Vec<i32> = Vec::new();
|
||||
Self::backtracking(&mut result, &mut path, n, k, 0, 1);
|
||||
result
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## C
|
||||
|
||||
```c
|
||||
@@ -502,5 +531,35 @@ func combinationSum3(_ count: Int, _ targetSum: Int) -> [[Int]] {
|
||||
}
|
||||
```
|
||||
|
||||
## Scala
|
||||
|
||||
```scala
|
||||
object Solution {
|
||||
import scala.collection.mutable
|
||||
def combinationSum3(k: Int, n: Int): List[List[Int]] = {
|
||||
var result = mutable.ListBuffer[List[Int]]()
|
||||
var path = mutable.ListBuffer[Int]()
|
||||
|
||||
def backtracking(k: Int, n: Int, sum: Int, startIndex: Int): Unit = {
|
||||
if (sum > n) return // 剪枝,如果sum>目标和,就返回
|
||||
if (sum == n && path.size == k) {
|
||||
result.append(path.toList)
|
||||
return
|
||||
}
|
||||
// 剪枝
|
||||
for (i <- startIndex to (9 - (k - path.size) + 1)) {
|
||||
path.append(i)
|
||||
backtracking(k, n, sum + i, i + 1)
|
||||
path = path.take(path.size - 1)
|
||||
}
|
||||
}
|
||||
|
||||
backtracking(k, n, 0, 1) // 调用递归方法
|
||||
result.toList // 最终返回结果集的List形式
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
||||
@@ -816,7 +816,6 @@ class MyStack {
|
||||
}
|
||||
```
|
||||
Scala:
|
||||
|
||||
使用两个队列模拟栈:
|
||||
```scala
|
||||
import scala.collection.mutable
|
||||
@@ -897,6 +896,86 @@ class MyStack() {
|
||||
def empty(): Boolean = {
|
||||
queue.isEmpty
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
PHP
|
||||
> 双对列
|
||||
```php
|
||||
// SplQueue 类通过使用一个双向链表来提供队列的主要功能。(PHP 5 >= 5.3.0, PHP 7, PHP 8)
|
||||
// https://www.php.net/manual/zh/class.splqueue.php
|
||||
class MyStack {
|
||||
public $queueMain; // 保存数据
|
||||
public $queueTmp; // 辅助作用
|
||||
|
||||
function __construct() {
|
||||
$this->queueMain=new SplQueue();
|
||||
$this->queueTmp=new SplQueue();
|
||||
}
|
||||
|
||||
// queueMain: 1,2,3 <= add
|
||||
function push($x) {
|
||||
$this->queueMain->enqueue($x);
|
||||
}
|
||||
|
||||
function pop() {
|
||||
$qmSize = $this->queueMain->Count();
|
||||
$qmSize --;
|
||||
// queueMain: 3,2,1 => pop =>2,1 => add => 2,1 :queueTmp
|
||||
while($qmSize --){
|
||||
$this->queueTmp->enqueue($this->queueMain->dequeue());
|
||||
}
|
||||
// queueMain: 3
|
||||
$val = $this->queueMain->dequeue();
|
||||
// queueMain <= queueTmp
|
||||
$this->queueMain = $this->queueTmp;
|
||||
// 清空queueTmp,下次使用
|
||||
$this->queueTmp = new SplQueue();
|
||||
return $val;
|
||||
}
|
||||
|
||||
function top() {
|
||||
// 底层是双链表实现:从双链表的末尾查看节点
|
||||
return $this->queueMain->top();
|
||||
}
|
||||
|
||||
function empty() {
|
||||
return $this->queueMain->isEmpty();
|
||||
}
|
||||
}
|
||||
```
|
||||
> 单对列
|
||||
```php
|
||||
class MyStack {
|
||||
public $queue;
|
||||
|
||||
function __construct() {
|
||||
$this->queue=new SplQueue();
|
||||
}
|
||||
|
||||
function push($x) {
|
||||
$this->queue->enqueue($x);
|
||||
}
|
||||
|
||||
function pop() {
|
||||
$qmSize = $this->queue->Count();
|
||||
$qmSize --;
|
||||
//queue: 3,2,1 => pop =>2,1 => add => 2,1,3 :queue
|
||||
while($qmSize --){
|
||||
$this->queue->enqueue($this->queue->dequeue());
|
||||
}
|
||||
$val = $this->queue->dequeue();
|
||||
return $val;
|
||||
}
|
||||
|
||||
function top() {
|
||||
return $this->queue->top();
|
||||
}
|
||||
|
||||
function empty() {
|
||||
return $this->queue->isEmpty();
|
||||
}
|
||||
}
|
||||
```
|
||||
-----------------------
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
```
|
||||
|
||||
@@ -495,6 +495,53 @@ void myQueueFree(MyQueue* obj) {
|
||||
obj->stackOutTop = 0;
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
PHP:
|
||||
```php
|
||||
// SplStack 类通过使用一个双向链表来提供栈的主要功能。[PHP 5 >= 5.3.0, PHP 7, PHP 8]
|
||||
// https://www.php.net/manual/zh/class.splstack.php
|
||||
class MyQueue {
|
||||
// 双栈模拟队列:In栈存储数据;Out栈辅助处理
|
||||
private $stackIn;
|
||||
private $stackOut;
|
||||
|
||||
function __construct() {
|
||||
$this->stackIn = new SplStack();
|
||||
$this->stackOut = new SplStack();
|
||||
}
|
||||
|
||||
// In: 1 2 3 <= push
|
||||
function push($x) {
|
||||
$this->stackIn->push($x);
|
||||
}
|
||||
|
||||
function pop() {
|
||||
$this->peek();
|
||||
return $this->stackOut->pop();
|
||||
}
|
||||
|
||||
function peek() {
|
||||
if($this->stackOut->isEmpty()){
|
||||
$this->shift();
|
||||
}
|
||||
return $this->stackOut->top();
|
||||
}
|
||||
|
||||
function empty() {
|
||||
return $this->stackOut->isEmpty() && $this->stackIn->isEmpty();
|
||||
}
|
||||
|
||||
// 如果Out栈为空,把In栈数据压入Out栈
|
||||
// In: 1 2 3 => pop push => 1 2 3 :Out
|
||||
private function shift(){
|
||||
while(!$this->stackIn->isEmpty()){
|
||||
$this->stackOut->push($this->stackIn->pop());
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Scala:
|
||||
```scala
|
||||
class MyQueue() {
|
||||
@@ -533,6 +580,7 @@ class MyQueue() {
|
||||
def empty(): Boolean = {
|
||||
stackIn.isEmpty && stackOut.isEmpty
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
-----------------------
|
||||
|
||||
@@ -273,7 +273,7 @@ class Solution:
|
||||
return pre
|
||||
```
|
||||
|
||||
## Go
|
||||
### Go
|
||||
|
||||
```go
|
||||
|
||||
@@ -319,6 +319,63 @@ var isPalindrome = function(head) {
|
||||
};
|
||||
```
|
||||
|
||||
### TypeScript
|
||||
|
||||
> 数组模拟
|
||||
|
||||
```typescript
|
||||
function isPalindrome(head: ListNode | null): boolean {
|
||||
const helperArr: number[] = [];
|
||||
let curNode: ListNode | null = head;
|
||||
while (curNode !== null) {
|
||||
helperArr.push(curNode.val);
|
||||
curNode = curNode.next;
|
||||
}
|
||||
let left: number = 0,
|
||||
right: number = helperArr.length - 1;
|
||||
while (left < right) {
|
||||
if (helperArr[left++] !== helperArr[right--]) return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
```
|
||||
|
||||
> 反转后半部分链表
|
||||
|
||||
```typescript
|
||||
function isPalindrome(head: ListNode | null): boolean {
|
||||
if (head === null || head.next === null) return true;
|
||||
let fastNode: ListNode | null = head,
|
||||
slowNode: ListNode = head,
|
||||
preNode: ListNode = head;
|
||||
while (fastNode !== null && fastNode.next !== null) {
|
||||
preNode = slowNode;
|
||||
slowNode = slowNode.next!;
|
||||
fastNode = fastNode.next.next;
|
||||
}
|
||||
preNode.next = null;
|
||||
let cur1: ListNode | null = head;
|
||||
let cur2: ListNode | null = reverseList(slowNode);
|
||||
while (cur1 !== null) {
|
||||
if (cur1.val !== cur2!.val) return false;
|
||||
cur1 = cur1.next;
|
||||
cur2 = cur2!.next;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
function reverseList(head: ListNode | null): ListNode | null {
|
||||
let curNode: ListNode | null = head,
|
||||
preNode: ListNode | null = null;
|
||||
while (curNode !== null) {
|
||||
let tempNode: ListNode | null = curNode.next;
|
||||
curNode.next = preNode;
|
||||
preNode = curNode;
|
||||
curNode = tempNode;
|
||||
}
|
||||
return preNode;
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
-----------------------
|
||||
|
||||
@@ -381,7 +381,36 @@ function lowestCommonAncestor(root: TreeNode | null, p: TreeNode | null, q: Tree
|
||||
};
|
||||
```
|
||||
|
||||
## Scala
|
||||
|
||||
递归:
|
||||
|
||||
```scala
|
||||
object Solution {
|
||||
def lowestCommonAncestor(root: TreeNode, p: TreeNode, q: TreeNode): TreeNode = {
|
||||
// scala中每个关键字都有其返回值,于是可以不写return
|
||||
if (root.value > p.value && root.value > q.value) lowestCommonAncestor(root.left, p, q)
|
||||
else if (root.value < p.value && root.value < q.value) lowestCommonAncestor(root.right, p, q)
|
||||
else root
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
迭代:
|
||||
|
||||
```scala
|
||||
object Solution {
|
||||
def lowestCommonAncestor(root: TreeNode, p: TreeNode, q: TreeNode): TreeNode = {
|
||||
var curNode = root // 因为root是不可变量,所以要赋值给curNode一个可变量
|
||||
while(curNode != null){
|
||||
if(curNode.value > p.value && curNode.value > q.value) curNode = curNode.left
|
||||
else if(curNode.value < p.value && curNode.value < q.value) curNode = curNode.right
|
||||
else return curNode
|
||||
}
|
||||
null
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
-----------------------
|
||||
|
||||
@@ -343,7 +343,25 @@ function lowestCommonAncestor(root: TreeNode | null, p: TreeNode | null, q: Tree
|
||||
};
|
||||
```
|
||||
|
||||
## Scala
|
||||
|
||||
```scala
|
||||
object Solution {
|
||||
def lowestCommonAncestor(root: TreeNode, p: TreeNode, q: TreeNode): TreeNode = {
|
||||
// 递归结束条件
|
||||
if (root == null || root == p || root == q) {
|
||||
return root
|
||||
}
|
||||
|
||||
var left = lowestCommonAncestor(root.left, p, q)
|
||||
var right = lowestCommonAncestor(root.right, p, q)
|
||||
|
||||
if (left != null && right != null) return root
|
||||
if (left == null) return right
|
||||
left
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
||||
@@ -654,8 +654,7 @@ object Solution {
|
||||
// 最终返回res,return关键字可以省略
|
||||
res
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
class MyQueue {
|
||||
var queue = ArrayBuffer[Int]()
|
||||
@@ -678,5 +677,84 @@ class MyQueue {
|
||||
def peek(): Int = queue.head
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
PHP:
|
||||
```php
|
||||
class Solution {
|
||||
/**
|
||||
* @param Integer[] $nums
|
||||
* @param Integer $k
|
||||
* @return Integer[]
|
||||
*/
|
||||
function maxSlidingWindow($nums, $k) {
|
||||
$myQueue = new MyQueue();
|
||||
// 先将前k的元素放进队列
|
||||
for ($i = 0; $i < $k; $i++) {
|
||||
$myQueue->push($nums[$i]);
|
||||
}
|
||||
|
||||
$result = [];
|
||||
$result[] = $myQueue->max(); // result 记录前k的元素的最大值
|
||||
|
||||
for ($i = $k; $i < count($nums); $i++) {
|
||||
$myQueue->pop($nums[$i - $k]); // 滑动窗口移除最前面元素
|
||||
$myQueue->push($nums[$i]); // 滑动窗口前加入最后面的元素
|
||||
$result[]= $myQueue->max(); // 记录对应的最大值
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 单调对列构建
|
||||
class MyQueue{
|
||||
private $queue;
|
||||
|
||||
public function __construct(){
|
||||
$this->queue = new SplQueue(); //底层是双向链表实现。
|
||||
}
|
||||
|
||||
public function pop($v){
|
||||
// 判断当前对列是否为空
|
||||
// 比较当前要弹出的数值是否等于队列出口元素的数值,如果相等则弹出。
|
||||
// bottom 从链表前端查看元素, dequeue 从双向链表的开头移动一个节点
|
||||
if(!$this->queue->isEmpty() && $v == $this->queue->bottom()){
|
||||
$this->queue->dequeue(); //弹出队列
|
||||
}
|
||||
}
|
||||
|
||||
public function push($v){
|
||||
// 判断当前对列是否为空
|
||||
// 如果push的数值大于入口元素的数值,那么就将队列后端的数值弹出,直到push的数值小于等于队列入口元素的数值为止。
|
||||
// 这样就保持了队列里的数值是单调从大到小的了。
|
||||
while (!$this->queue->isEmpty() && $v > $this->queue->top()) {
|
||||
$this->queue->pop(); // pop从链表末尾弹出一个元素,
|
||||
}
|
||||
$this->queue->enqueue($v);
|
||||
}
|
||||
|
||||
// 查询当前队列里的最大值 直接返回队首
|
||||
public function max(){
|
||||
// bottom 从链表前端查看元素, top从链表末尾查看元素
|
||||
return $this->queue->bottom();
|
||||
}
|
||||
|
||||
// 辅助理解: 打印队列元素
|
||||
public function println(){
|
||||
// "迭代器移动到链表头部": 可理解为从头遍历链表元素做准备。
|
||||
// 【PHP中没有指针概念,所以就没说指针。从数据结构上理解,就是把指针指向链表头部】
|
||||
$this->queue->rewind();
|
||||
|
||||
echo "Println: ";
|
||||
while($this->queue->valid()){
|
||||
echo $this->queue->current()," -> ";
|
||||
$this->queue->next();
|
||||
}
|
||||
echo "\n";
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
||||
@@ -133,6 +133,27 @@ var moveZeroes = function(nums) {
|
||||
};
|
||||
```
|
||||
|
||||
TypeScript:
|
||||
|
||||
```typescript
|
||||
function moveZeroes(nums: number[]): void {
|
||||
const length: number = nums.length;
|
||||
let slowIndex: number = 0,
|
||||
fastIndex: number = 0;
|
||||
while (fastIndex < length) {
|
||||
if (nums[fastIndex] !== 0) {
|
||||
nums[slowIndex++] = nums[fastIndex];
|
||||
};
|
||||
fastIndex++;
|
||||
}
|
||||
while (slowIndex < length) {
|
||||
nums[slowIndex++] = 0;
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
||||
@@ -190,13 +190,13 @@ javaScript:
|
||||
* @return {void} Do not return anything, modify s in-place instead.
|
||||
*/
|
||||
var reverseString = function(s) {
|
||||
return s.reverse();
|
||||
//Do not return anything, modify s in-place instead.
|
||||
reverse(s)
|
||||
};
|
||||
|
||||
var reverseString = function(s) {
|
||||
var reverse = function(s) {
|
||||
let l = -1, r = s.length;
|
||||
while(++l < --r) [s[l], s[r]] = [s[r], s[l]];
|
||||
return s;
|
||||
};
|
||||
```
|
||||
|
||||
@@ -238,6 +238,22 @@ func reverseString(_ s: inout [Character]) {
|
||||
|
||||
```
|
||||
|
||||
Rust:
|
||||
```Rust
|
||||
impl Solution {
|
||||
pub fn reverse_string(s: &mut Vec<char>) {
|
||||
let (mut left, mut right) = (0, s.len()-1);
|
||||
while left < right {
|
||||
let temp = s[left];
|
||||
s[left] = s[right];
|
||||
s[right] = temp;
|
||||
left += 1;
|
||||
right -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
C:
|
||||
```c
|
||||
void reverseString(char* s, int sSize){
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -137,13 +137,8 @@ class Solution {
|
||||
resSet.add(i);
|
||||
}
|
||||
}
|
||||
int[] resArr = new int[resSet.size()];
|
||||
int index = 0;
|
||||
//将结果几何转为数组
|
||||
for (int i : resSet) {
|
||||
resArr[index++] = i;
|
||||
}
|
||||
return resArr;
|
||||
return resSet.stream().mapToInt(x -> x).toArray();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -228,6 +228,8 @@ class Solution {
|
||||
|
||||
### Python
|
||||
|
||||
**贪心**
|
||||
|
||||
```python
|
||||
class Solution:
|
||||
def wiggleMaxLength(self, nums: List[int]) -> int:
|
||||
@@ -240,7 +242,30 @@ class Solution:
|
||||
return res
|
||||
```
|
||||
|
||||
**动态规划**
|
||||
|
||||
```python
|
||||
class Solution:
|
||||
def wiggleMaxLength(self, nums: List[int]) -> int:
|
||||
# 0 i 作为波峰的最大长度
|
||||
# 1 i 作为波谷的最大长度
|
||||
# dp是一个列表,列表中每个元素是长度为 2 的列表
|
||||
dp = []
|
||||
for i in range(len(nums)):
|
||||
# 初始为[1, 1]
|
||||
dp.append([1, 1])
|
||||
for j in range(i):
|
||||
# nums[i] 为波谷
|
||||
if nums[j] > nums[i]:
|
||||
dp[i][1] = max(dp[i][1], dp[j][0] + 1)
|
||||
# nums[i] 为波峰
|
||||
if nums[j] < nums[i]:
|
||||
dp[i][0] = max(dp[i][0], dp[j][1] + 1)
|
||||
return max(dp[-1][0], dp[-1][1])
|
||||
```
|
||||
|
||||
### Go
|
||||
|
||||
```golang
|
||||
func wiggleMaxLength(nums []int) int {
|
||||
var count,preDiff,curDiff int
|
||||
@@ -298,9 +323,33 @@ var wiggleMaxLength = function(nums) {
|
||||
};
|
||||
```
|
||||
|
||||
### Rust
|
||||
**贪心**
|
||||
```Rust
|
||||
impl Solution {
|
||||
pub fn wiggle_max_length(nums: Vec<i32>) -> i32 {
|
||||
let len = nums.len() as usize;
|
||||
if len <= 1 {
|
||||
return len as i32;
|
||||
}
|
||||
let mut preDiff = 0;
|
||||
let mut curDiff = 0;
|
||||
let mut result = 1;
|
||||
for i in 0..len-1 {
|
||||
curDiff = nums[i+1] - nums[i];
|
||||
if (preDiff <= 0 && curDiff > 0) || (preDiff >= 0 && curDiff < 0) {
|
||||
result += 1;
|
||||
preDiff = curDiff;
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### C
|
||||
**贪心**
|
||||
|
||||
```c
|
||||
int wiggleMaxLength(int* nums, int numsSize){
|
||||
if(numsSize <= 1)
|
||||
@@ -326,6 +375,44 @@ int wiggleMaxLength(int* nums, int numsSize){
|
||||
}
|
||||
```
|
||||
|
||||
**动态规划**
|
||||
|
||||
```c
|
||||
int max(int left, int right)
|
||||
{
|
||||
return left > right ? left : right;
|
||||
}
|
||||
int wiggleMaxLength(int* nums, int numsSize){
|
||||
if(numsSize <= 1)
|
||||
{
|
||||
return numsSize;
|
||||
}
|
||||
// 0 i 作为波峰的最大长度
|
||||
// 1 i 作为波谷的最大长度
|
||||
int dp[numsSize][2];
|
||||
for(int i = 0; i < numsSize; i++)
|
||||
{
|
||||
dp[i][0] = 1;
|
||||
dp[i][1] = 1;
|
||||
for(int j = 0; j < i; j++)
|
||||
{
|
||||
// nums[i] 为山谷
|
||||
if(nums[j] > nums[i])
|
||||
{
|
||||
dp[i][1] = max(dp[i][1], dp[j][0] + 1);
|
||||
}
|
||||
// nums[i] 为山峰
|
||||
if(nums[j] < nums[i])
|
||||
{
|
||||
dp[i][0] = max(dp[i][0], dp[j][1] + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
return max(dp[numsSize - 1][0], dp[numsSize - 1][1]);
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
### TypeScript
|
||||
|
||||
@@ -375,7 +462,31 @@ function wiggleMaxLength(nums: number[]): number {
|
||||
};
|
||||
```
|
||||
|
||||
### Scala
|
||||
|
||||
```scala
|
||||
object Solution {
|
||||
def wiggleMaxLength(nums: Array[Int]): Int = {
|
||||
if (nums.length <= 1) return nums.length
|
||||
var result = 1
|
||||
var curDiff = 0 // 当前一对的差值
|
||||
var preDiff = 0 // 前一对的差值
|
||||
|
||||
for (i <- 1 until nums.length) {
|
||||
curDiff = nums(i) - nums(i - 1) // 计算当前这一对的差值
|
||||
// 当 curDiff > 0 的情况,preDiff <= 0
|
||||
// 当 curDiff < 0 的情况,preDiff >= 0
|
||||
// 这两种情况算是两个峰值
|
||||
if ((curDiff > 0 && preDiff <= 0) || (curDiff < 0 && preDiff >= 0)) {
|
||||
result += 1 // 结果集加 1
|
||||
preDiff = curDiff // 当前差值赋值给上一轮
|
||||
}
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
```
|
||||
|
||||
迭代
|
||||
@@ -582,7 +593,35 @@ function deleteNode(root: TreeNode | null, key: number): TreeNode | null {
|
||||
};
|
||||
```
|
||||
|
||||
## Scala
|
||||
|
||||
```scala
|
||||
object Solution {
|
||||
def deleteNode(root: TreeNode, key: Int): TreeNode = {
|
||||
if (root == null) return root // 第一种情况,没找到删除的节点,遍历到空节点直接返回
|
||||
if (root.value == key) {
|
||||
// 第二种情况: 左右孩子都为空,直接删除节点,返回null
|
||||
if (root.left == null && root.right == null) return null
|
||||
// 第三种情况: 左孩子为空,右孩子不为空,右孩子补位
|
||||
else if (root.left == null && root.right != null) return root.right
|
||||
// 第四种情况: 左孩子不为空,右孩子为空,左孩子补位
|
||||
else if (root.left != null && root.right == null) return root.left
|
||||
// 第五种情况: 左右孩子都不为空,将删除节点的左子树头节点(左孩子)放到
|
||||
// 右子树的最左边节点的左孩子上,返回删除节点的右孩子
|
||||
else {
|
||||
var tmp = root.right
|
||||
while (tmp.left != null) tmp = tmp.left
|
||||
tmp.left = root.left
|
||||
return root.right
|
||||
}
|
||||
}
|
||||
if (root.value > key) root.left = deleteNode(root.left, key)
|
||||
if (root.value < key) root.right = deleteNode(root.right, key)
|
||||
|
||||
root // 返回根节点,return关键字可以省略
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -296,5 +296,26 @@ int findContentChildren(int* g, int gSize, int* s, int sSize){
|
||||
}
|
||||
```
|
||||
|
||||
### Scala
|
||||
|
||||
```scala
|
||||
object Solution {
|
||||
def findContentChildren(g: Array[Int], s: Array[Int]): Int = {
|
||||
var result = 0
|
||||
var children = g.sorted
|
||||
var cookie = s.sorted
|
||||
// 遍历饼干
|
||||
var j = 0
|
||||
for (i <- cookie.indices) {
|
||||
if (j < children.size && cookie(i) >= children(j)) {
|
||||
j += 1
|
||||
result += 1
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
||||
@@ -505,5 +505,37 @@ Swift:
|
||||
}
|
||||
```
|
||||
|
||||
Rust:
|
||||
|
||||
>前缀表统一不减一
|
||||
```Rust
|
||||
impl Solution {
|
||||
pub fn get_next(next: &mut Vec<usize>, s: &Vec<char>) {
|
||||
let len = s.len();
|
||||
let mut j = 0;
|
||||
for i in 1..len {
|
||||
while j > 0 && s[i] != s[j] {
|
||||
j = next[j - 1];
|
||||
}
|
||||
if s[i] == s[j] {
|
||||
j += 1;
|
||||
}
|
||||
next[i] = j;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn repeated_substring_pattern(s: String) -> bool {
|
||||
let s = s.chars().collect::<Vec<char>>();
|
||||
let len = s.len();
|
||||
if len == 0 { return false; };
|
||||
let mut next = vec![0; len];
|
||||
Self::get_next(&mut next, &s);
|
||||
if next[len - 1] != 0 && len % (len - (next[len - 1] )) == 0 { return true; }
|
||||
return false;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -9,7 +9,9 @@
|
||||
|
||||
# 501.二叉搜索树中的众数
|
||||
|
||||
[力扣题目链接](https://leetcode.cn/problems/find-mode-in-binary-search-tree/solution/)
|
||||
|
||||
[力扣题目链接](https://leetcode.cn/problems/find-mode-in-binary-search-tree/)
|
||||
|
||||
|
||||
给定一个有相同值的二叉搜索树(BST),找出 BST 中的所有众数(出现频率最高的元素)。
|
||||
|
||||
@@ -798,7 +800,76 @@ function findMode(root: TreeNode | null): number[] {
|
||||
};
|
||||
```
|
||||
|
||||
## Scala
|
||||
|
||||
暴力:
|
||||
```scala
|
||||
object Solution {
|
||||
// 导包
|
||||
import scala.collection.mutable // 集合包
|
||||
import scala.util.control.Breaks.{break, breakable} // 流程控制包
|
||||
def findMode(root: TreeNode): Array[Int] = {
|
||||
var map = mutable.HashMap[Int, Int]() // 存储节点的值,和该值出现的次数
|
||||
def searchBST(curNode: TreeNode): Unit = {
|
||||
if (curNode == null) return
|
||||
var value = map.getOrElse(curNode.value, 0)
|
||||
map.put(curNode.value, value + 1)
|
||||
searchBST(curNode.left)
|
||||
searchBST(curNode.right)
|
||||
}
|
||||
searchBST(root) // 前序遍历把每个节点的值加入到里面
|
||||
// 将map转换为list,随后根据元组的第二个值进行排序
|
||||
val list = map.toList.sortWith((map1, map2) => {
|
||||
if (map1._2 > map2._2) true else false
|
||||
})
|
||||
var res = mutable.ArrayBuffer[Int]()
|
||||
res.append(list(0)._1) // 将第一个加入结果集
|
||||
breakable {
|
||||
for (i <- 1 until list.size) {
|
||||
// 如果值相同就加入结果集合,反之break
|
||||
if (list(i)._2 == list(0)._2) res.append(list(i)._1)
|
||||
else break
|
||||
}
|
||||
}
|
||||
res.toArray // 最终返回res的Array格式,return关键字可以省略
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
递归(利用二叉搜索树的性质):
|
||||
```scala
|
||||
object Solution {
|
||||
import scala.collection.mutable
|
||||
def findMode(root: TreeNode): Array[Int] = {
|
||||
var maxCount = 0 // 最大频率
|
||||
var count = 0 // 统计频率
|
||||
var pre: TreeNode = null
|
||||
var result = mutable.ArrayBuffer[Int]()
|
||||
|
||||
def searchBST(cur: TreeNode): Unit = {
|
||||
if (cur == null) return
|
||||
searchBST(cur.left)
|
||||
if (pre == null) count = 1 // 等于空置为1
|
||||
else if (pre.value == cur.value) count += 1 // 与上一个节点的值相同加1
|
||||
else count = 1 // 与上一个节点的值不同
|
||||
pre = cur
|
||||
|
||||
// 如果和最大值相同,则放入结果集
|
||||
if (count == maxCount) result.append(cur.value)
|
||||
|
||||
// 如果当前计数大于最大值频率,更新最大值,清空结果集
|
||||
if (count > maxCount) {
|
||||
maxCount = count
|
||||
result.clear()
|
||||
result.append(cur.value)
|
||||
}
|
||||
searchBST(cur.right)
|
||||
}
|
||||
searchBST(root)
|
||||
result.toArray // return关键字可以省略
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
-----------------------
|
||||
|
||||
@@ -234,6 +234,7 @@ func fib(n int) int {
|
||||
}
|
||||
```
|
||||
### Javascript
|
||||
解法一
|
||||
```Javascript
|
||||
var fib = function(n) {
|
||||
let dp = [0, 1]
|
||||
@@ -244,6 +245,23 @@ var fib = function(n) {
|
||||
return dp[n]
|
||||
};
|
||||
```
|
||||
解法二:时间复杂度O(N),空间复杂度O(1)
|
||||
```Javascript
|
||||
var fib = function(n) {
|
||||
// 动规状态转移中,当前结果只依赖前两个元素的结果,所以只要两个变量代替dp数组记录状态过程。将空间复杂度降到O(1)
|
||||
let pre1 = 1
|
||||
let pre2 = 0
|
||||
let temp
|
||||
if (n === 0) return 0
|
||||
if (n === 1) return 1
|
||||
for(let i = 2; i <= n; i++) {
|
||||
temp = pre1
|
||||
pre1 = pre1 + pre2
|
||||
pre2 = temp
|
||||
}
|
||||
return pre1
|
||||
};
|
||||
```
|
||||
|
||||
TypeScript
|
||||
|
||||
|
||||
@@ -431,7 +431,84 @@ function getMinimumDifference(root: TreeNode | null): number {
|
||||
};
|
||||
```
|
||||
|
||||
## Scala
|
||||
|
||||
构建二叉树的有序数组:
|
||||
|
||||
```scala
|
||||
object Solution {
|
||||
import scala.collection.mutable
|
||||
def getMinimumDifference(root: TreeNode): Int = {
|
||||
val arr = mutable.ArrayBuffer[Int]()
|
||||
def traversal(node: TreeNode): Unit = {
|
||||
if (node == null) return
|
||||
traversal(node.left)
|
||||
arr.append(node.value)
|
||||
traversal(node.right)
|
||||
}
|
||||
traversal(root)
|
||||
// 在有序数组上求最小差值
|
||||
var result = Int.MaxValue
|
||||
for (i <- 1 until arr.size) {
|
||||
result = math.min(result, arr(i) - arr(i - 1))
|
||||
}
|
||||
result // 返回最小差值
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
递归记录前一个节点:
|
||||
|
||||
```scala
|
||||
object Solution {
|
||||
def getMinimumDifference(root: TreeNode): Int = {
|
||||
var result = Int.MaxValue // 初始化为最大值
|
||||
var pre: TreeNode = null // 记录前一个节点
|
||||
|
||||
def traversal(cur: TreeNode): Unit = {
|
||||
if (cur == null) return
|
||||
traversal(cur.left)
|
||||
if (pre != null) {
|
||||
// 对比result与节点之间的差值
|
||||
result = math.min(result, cur.value - pre.value)
|
||||
}
|
||||
pre = cur
|
||||
traversal(cur.right)
|
||||
}
|
||||
|
||||
traversal(root)
|
||||
result // return关键字可以省略
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
迭代解决:
|
||||
|
||||
```scala
|
||||
object Solution {
|
||||
import scala.collection.mutable
|
||||
def getMinimumDifference(root: TreeNode): Int = {
|
||||
var result = Int.MaxValue // 初始化为最大值
|
||||
var pre: TreeNode = null // 记录前一个节点
|
||||
var cur = root
|
||||
var stack = mutable.Stack[TreeNode]()
|
||||
while (cur != null || !stack.isEmpty) {
|
||||
if (cur != null) {
|
||||
stack.push(cur)
|
||||
cur = cur.left
|
||||
} else {
|
||||
cur = stack.pop()
|
||||
if (pre != null) {
|
||||
result = math.min(result, cur.value - pre.value)
|
||||
}
|
||||
pre = cur
|
||||
cur = cur.right
|
||||
}
|
||||
}
|
||||
result // return关键字可以省略
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
||||
@@ -352,6 +352,24 @@ function convertBST(root: TreeNode | null): TreeNode | null {
|
||||
};
|
||||
```
|
||||
|
||||
## Scala
|
||||
|
||||
```scala
|
||||
object Solution {
|
||||
def convertBST(root: TreeNode): TreeNode = {
|
||||
var sum = 0
|
||||
def convert(node: TreeNode): Unit = {
|
||||
if (node == null) return
|
||||
convert(node.right)
|
||||
sum += node.value
|
||||
node.value = sum
|
||||
convert(node.left)
|
||||
}
|
||||
convert(root)
|
||||
root
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
-----------------------
|
||||
|
||||
@@ -53,10 +53,10 @@ public:
|
||||
// 2. 剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符
|
||||
if (i + k <= s.size()) {
|
||||
reverse(s.begin() + i, s.begin() + i + k );
|
||||
continue;
|
||||
} else {
|
||||
// 3. 剩余字符少于 k 个,则将剩余字符全部反转。
|
||||
reverse(s.begin() + i, s.end());
|
||||
}
|
||||
// 3. 剩余字符少于 k 个,则将剩余字符全部反转。
|
||||
reverse(s.begin() + i, s.begin() + s.size());
|
||||
}
|
||||
return s;
|
||||
}
|
||||
@@ -389,5 +389,36 @@ object Solution {
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Rust:
|
||||
|
||||
```Rust
|
||||
impl Solution {
|
||||
pub fn reverse(s: &mut Vec<char>, mut begin: usize, mut end: usize){
|
||||
while begin < end {
|
||||
let temp = s[begin];
|
||||
s[begin] = s[end];
|
||||
s[end] = temp;
|
||||
begin += 1;
|
||||
end -= 1;
|
||||
}
|
||||
}
|
||||
pub fn reverse_str(s: String, k: i32) -> String {
|
||||
let len = s.len();
|
||||
let k = k as usize;
|
||||
let mut s = s.chars().collect::<Vec<_>>();
|
||||
for i in (0..len).step_by(2 * k) {
|
||||
if i + k < len {
|
||||
Self::reverse(&mut s, i, i + k - 1);
|
||||
}
|
||||
else {
|
||||
Self::reverse(&mut s, i, len - 1);
|
||||
}
|
||||
}
|
||||
s.iter().collect::<String>()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
||||
@@ -631,7 +631,60 @@ function mergeTrees(root1: TreeNode | null, root2: TreeNode | null): TreeNode |
|
||||
};
|
||||
```
|
||||
|
||||
## Scala
|
||||
|
||||
递归:
|
||||
```scala
|
||||
object Solution {
|
||||
def mergeTrees(root1: TreeNode, root2: TreeNode): TreeNode = {
|
||||
if (root1 == null) return root2 // 如果root1为空,返回root2
|
||||
if (root2 == null) return root1 // 如果root2为空,返回root1
|
||||
// 新建一个节点,值为两个节点的和
|
||||
var node = new TreeNode(root1.value + root2.value)
|
||||
// 往下递归
|
||||
node.left = mergeTrees(root1.left, root2.left)
|
||||
node.right = mergeTrees(root1.right, root2.right)
|
||||
node // 返回node,return关键字可以省略
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
迭代:
|
||||
```scala
|
||||
object Solution {
|
||||
import scala.collection.mutable
|
||||
def mergeTrees(root1: TreeNode, root2: TreeNode): TreeNode = {
|
||||
if (root1 == null) return root2
|
||||
if (root2 == null) return root1
|
||||
var stack = mutable.Stack[TreeNode]()
|
||||
// 先放node2再放node1
|
||||
stack.push(root2)
|
||||
stack.push(root1)
|
||||
while (!stack.isEmpty) {
|
||||
var node1 = stack.pop()
|
||||
var node2 = stack.pop()
|
||||
node1.value += node2.value
|
||||
if (node1.right != null && node2.right != null) {
|
||||
stack.push(node2.right)
|
||||
stack.push(node1.right)
|
||||
} else {
|
||||
if(node1.right == null){
|
||||
node1.right = node2.right
|
||||
}
|
||||
}
|
||||
if (node1.left != null && node2.left != null) {
|
||||
stack.push(node2.left)
|
||||
stack.push(node1.left)
|
||||
} else {
|
||||
if(node1.left == null){
|
||||
node1.left = node2.left
|
||||
}
|
||||
}
|
||||
}
|
||||
root1
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
-----------------------
|
||||
|
||||
@@ -476,7 +476,33 @@ func traversal(_ nums: inout [Int], _ left: Int, _ right: Int) -> TreeNode? {
|
||||
}
|
||||
```
|
||||
|
||||
## Scala
|
||||
|
||||
```scala
|
||||
object Solution {
|
||||
def constructMaximumBinaryTree(nums: Array[Int]): TreeNode = {
|
||||
if (nums.size == 0) return null
|
||||
// 找到数组最大值
|
||||
var maxIndex = 0
|
||||
var maxValue = Int.MinValue
|
||||
for (i <- nums.indices) {
|
||||
if (nums(i) > maxValue) {
|
||||
maxIndex = i
|
||||
maxValue = nums(i)
|
||||
}
|
||||
}
|
||||
|
||||
// 构建一棵树
|
||||
var root = new TreeNode(maxValue, null, null)
|
||||
|
||||
// 递归寻找左右子树
|
||||
root.left = constructMaximumBinaryTree(nums.slice(0, maxIndex))
|
||||
root.right = constructMaximumBinaryTree(nums.slice(maxIndex + 1, nums.length))
|
||||
|
||||
root // 返回root
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
||||
@@ -453,7 +453,21 @@ function trimBST(root: TreeNode | null, low: number, high: number): TreeNode | n
|
||||
};
|
||||
```
|
||||
|
||||
## Scala
|
||||
|
||||
递归法:
|
||||
```scala
|
||||
object Solution {
|
||||
def trimBST(root: TreeNode, low: Int, high: Int): TreeNode = {
|
||||
if (root == null) return null
|
||||
if (root.value < low) return trimBST(root.right, low, high)
|
||||
if (root.value > high) return trimBST(root.left, low, high)
|
||||
root.left = trimBST(root.left, low, high)
|
||||
root.right = trimBST(root.right, low, high)
|
||||
root
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
-----------------------
|
||||
|
||||
@@ -363,7 +363,34 @@ function searchBST(root: TreeNode | null, val: number): TreeNode | null {
|
||||
};
|
||||
```
|
||||
|
||||
## Scala
|
||||
|
||||
递归:
|
||||
```scala
|
||||
object Solution {
|
||||
def searchBST(root: TreeNode, value: Int): TreeNode = {
|
||||
if (root == null || value == root.value) return root
|
||||
// 相当于三元表达式,在Scala中if...else有返回值
|
||||
if (value < root.value) searchBST(root.left, value) else searchBST(root.right, value)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
迭代:
|
||||
```scala
|
||||
object Solution {
|
||||
def searchBST(root: TreeNode, value: Int): TreeNode = {
|
||||
// 因为root是不可变量,所以需要赋值给一个可变量
|
||||
var node = root
|
||||
while (node != null) {
|
||||
if (value < node.value) node = node.left
|
||||
else if (value > node.value) node = node.right
|
||||
else return node
|
||||
}
|
||||
null // 没有返回就返回空
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
||||
@@ -585,6 +585,43 @@ function insertIntoBST(root: TreeNode | null, val: number): TreeNode | null {
|
||||
```
|
||||
|
||||
|
||||
## Scala
|
||||
|
||||
递归:
|
||||
|
||||
```scala
|
||||
object Solution {
|
||||
def insertIntoBST(root: TreeNode, `val`: Int): TreeNode = {
|
||||
if (root == null) return new TreeNode(`val`)
|
||||
if (`val` < root.value) root.left = insertIntoBST(root.left, `val`)
|
||||
else root.right = insertIntoBST(root.right, `val`)
|
||||
root // 返回根节点
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
迭代:
|
||||
|
||||
```scala
|
||||
object Solution {
|
||||
def insertIntoBST(root: TreeNode, `val`: Int): TreeNode = {
|
||||
if (root == null) {
|
||||
return new TreeNode(`val`)
|
||||
}
|
||||
var parent = root // 记录当前节点的父节点
|
||||
var curNode = root
|
||||
while (curNode != null) {
|
||||
parent = curNode
|
||||
if(`val` < curNode.value) curNode = curNode.left
|
||||
else curNode = curNode.right
|
||||
}
|
||||
if(`val` < parent.value) parent.left = new TreeNode(`val`)
|
||||
else parent.right = new TreeNode(`val`)
|
||||
root // 最终返回根节点
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
||||
@@ -613,6 +613,36 @@ public class Solution{
|
||||
}
|
||||
```
|
||||
|
||||
**Kotlin:**
|
||||
```kotlin
|
||||
class Solution {
|
||||
fun search(nums: IntArray, target: Int): Int {
|
||||
// leftBorder
|
||||
var left:Int = 0
|
||||
// rightBorder
|
||||
var right:Int = nums.size - 1
|
||||
// 使用左闭右闭区间
|
||||
while (left <= right) {
|
||||
var middle:Int = left + (right - left)/2
|
||||
// taget 在左边
|
||||
if (nums[middle] > target) {
|
||||
right = middle - 1
|
||||
}
|
||||
else {
|
||||
// target 在右边
|
||||
if (nums[middle] < target) {
|
||||
left = middle + 1
|
||||
}
|
||||
// 找到了,返回
|
||||
else return middle
|
||||
}
|
||||
}
|
||||
// 没找到,返回
|
||||
return -1
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
**Kotlin:**
|
||||
|
||||
@@ -106,8 +106,9 @@ public:
|
||||
// 在第index个节点之前插入一个新节点,例如index为0,那么新插入的节点为链表的新头节点。
|
||||
// 如果index 等于链表的长度,则说明是新插入的节点为链表的尾结点
|
||||
// 如果index大于链表的长度,则返回空
|
||||
// 如果index小于0,则置为0,作为链表的新头节点。
|
||||
void addAtIndex(int index, int val) {
|
||||
if (index > _size) {
|
||||
if (index > _size || index < 0) {
|
||||
return;
|
||||
}
|
||||
LinkedNode* newNode = new LinkedNode(val);
|
||||
|
||||
@@ -140,6 +140,24 @@ var pivotIndex = function(nums) {
|
||||
};
|
||||
```
|
||||
|
||||
### TypeScript
|
||||
|
||||
```typescript
|
||||
function pivotIndex(nums: number[]): number {
|
||||
const length: number = nums.length;
|
||||
const sum: number = nums.reduce((a, b) => a + b);
|
||||
let leftSum: number = 0;
|
||||
for (let i = 0; i < length; i++) {
|
||||
const rightSum: number = sum - leftSum - nums[i];
|
||||
if (leftSum === rightSum) return i;
|
||||
leftSum += nums[i];
|
||||
}
|
||||
return -1;
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
||||
@@ -288,6 +288,24 @@ function minCostClimbingStairs(cost: number[]): number {
|
||||
};
|
||||
```
|
||||
|
||||
### Rust
|
||||
|
||||
```Rust
|
||||
use std::cmp::min;
|
||||
impl Solution {
|
||||
pub fn min_cost_climbing_stairs(cost: Vec<i32>) -> i32 {
|
||||
let len = cost.len();
|
||||
let mut dp = vec![0; len];
|
||||
dp[0] = cost[0];
|
||||
dp[1] = cost[1];
|
||||
for i in 2..len {
|
||||
dp[i] = min(dp[i-1], dp[i-2]) + cost[i];
|
||||
}
|
||||
min(dp[len-1], dp[len-2])
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### C
|
||||
|
||||
```c
|
||||
|
||||
@@ -399,6 +399,71 @@ var backspaceCompare = function(s, t) {
|
||||
|
||||
```
|
||||
|
||||
### TypeScript
|
||||
|
||||
> 双栈法:
|
||||
|
||||
```typescript
|
||||
function backspaceCompare(s: string, t: string): boolean {
|
||||
const stack1: string[] = [],
|
||||
stack2: string[] = [];
|
||||
for (let c of s) {
|
||||
if (c === '#') {
|
||||
stack1.pop();
|
||||
} else {
|
||||
stack1.push(c);
|
||||
}
|
||||
}
|
||||
for (let c of t) {
|
||||
if (c === '#') {
|
||||
stack2.pop();
|
||||
} else {
|
||||
stack2.push(c);
|
||||
}
|
||||
}
|
||||
if (stack1.length !== stack2.length) return false;
|
||||
for (let i = 0, length = stack1.length; i < length; i++) {
|
||||
if (stack1[i] !== stack2[i]) return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
```
|
||||
|
||||
> 双指针法:
|
||||
|
||||
```typescript
|
||||
function backspaceCompare(s: string, t: string): boolean {
|
||||
let sIndex: number = s.length - 1,
|
||||
tIndex: number = t.length - 1;
|
||||
while (true) {
|
||||
sIndex = getIndexAfterDel(s, sIndex);
|
||||
tIndex = getIndexAfterDel(t, tIndex);
|
||||
if (sIndex < 0 || tIndex < 0) break;
|
||||
if (s[sIndex] !== t[tIndex]) return false;
|
||||
sIndex--;
|
||||
tIndex--;
|
||||
}
|
||||
return sIndex === -1 && tIndex === -1;
|
||||
};
|
||||
function getIndexAfterDel(s: string, startIndex: number): number {
|
||||
let backspaceNum: number = 0;
|
||||
while (startIndex >= 0) {
|
||||
// 不可消除
|
||||
if (s[startIndex] !== '#' && backspaceNum === 0) break;
|
||||
// 可消除
|
||||
if (s[startIndex] === '#') {
|
||||
backspaceNum++;
|
||||
} else {
|
||||
backspaceNum--;
|
||||
}
|
||||
startIndex--;
|
||||
}
|
||||
return startIndex;
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
||||
@@ -260,6 +260,75 @@ var sortArrayByParityII = function(nums) {
|
||||
};
|
||||
```
|
||||
|
||||
### TypeScript
|
||||
|
||||
> 方法一:
|
||||
|
||||
```typescript
|
||||
function sortArrayByParityII(nums: number[]): number[] {
|
||||
const evenArr: number[] = [],
|
||||
oddArr: number[] = [];
|
||||
for (let num of nums) {
|
||||
if (num % 2 === 0) {
|
||||
evenArr.push(num);
|
||||
} else {
|
||||
oddArr.push(num);
|
||||
}
|
||||
}
|
||||
const resArr: number[] = [];
|
||||
for (let i = 0, length = nums.length / 2; i < length; i++) {
|
||||
resArr.push(evenArr[i]);
|
||||
resArr.push(oddArr[i]);
|
||||
}
|
||||
return resArr;
|
||||
};
|
||||
```
|
||||
|
||||
> 方法二:
|
||||
|
||||
```typescript
|
||||
function sortArrayByParityII(nums: number[]): number[] {
|
||||
const length: number = nums.length;
|
||||
const resArr: number[] = [];
|
||||
let evenIndex: number = 0,
|
||||
oddIndex: number = 1;
|
||||
for (let i = 0; i < length; i++) {
|
||||
if (nums[i] % 2 === 0) {
|
||||
resArr[evenIndex] = nums[i];
|
||||
evenIndex += 2;
|
||||
} else {
|
||||
resArr[oddIndex] = nums[i];
|
||||
oddIndex += 2;
|
||||
}
|
||||
}
|
||||
return resArr;
|
||||
};
|
||||
```
|
||||
|
||||
> 方法三:
|
||||
|
||||
```typescript
|
||||
function sortArrayByParityII(nums: number[]): number[] {
|
||||
const length: number = nums.length;
|
||||
let oddIndex: number = 1;
|
||||
for (let evenIndex = 0; evenIndex < length; evenIndex += 2) {
|
||||
if (nums[evenIndex] % 2 === 1) {
|
||||
// 在偶数位遇到了奇数
|
||||
while (oddIndex < length && nums[oddIndex] % 2 === 1) {
|
||||
oddIndex += 2;
|
||||
}
|
||||
// 在奇数位遇到了偶数,交换
|
||||
let temp = nums[evenIndex];
|
||||
nums[evenIndex] = nums[oddIndex];
|
||||
nums[oddIndex] = temp;
|
||||
}
|
||||
}
|
||||
return nums;
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
||||
@@ -209,6 +209,31 @@ var isLongPressedName = function(name, typed) {
|
||||
};
|
||||
```
|
||||
|
||||
### TypeScript
|
||||
|
||||
```typescript
|
||||
function isLongPressedName(name: string, typed: string): boolean {
|
||||
const nameLength: number = name.length,
|
||||
typeLength: number = typed.length;
|
||||
let i: number = 0,
|
||||
j: number = 0;
|
||||
while (i < nameLength && j < typeLength) {
|
||||
if (name[i] !== typed[j]) return false;
|
||||
i++;
|
||||
j++;
|
||||
if (i === nameLength || name[i] !== name[i - 1]) {
|
||||
// 跳过typed中的连续相同字符
|
||||
while (j < typeLength && typed[j] === typed[j - 1]) {
|
||||
j++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return i === nameLength && j === typeLength;
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
-----------------------
|
||||
<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 {
|
||||
@@ -362,6 +363,8 @@ class Solution {
|
||||
```
|
||||
|
||||
Kotlin:
|
||||
|
||||
双指针法
|
||||
```kotlin
|
||||
class Solution {
|
||||
// 双指针法
|
||||
@@ -383,6 +386,32 @@ class Solution {
|
||||
}
|
||||
}
|
||||
```
|
||||
骚操作(暴力思路)
|
||||
```kotlin
|
||||
class Solution {
|
||||
fun sortedSquares(nums: IntArray): IntArray {
|
||||
// left 与 right 用来控制循环,类似于滑动窗口
|
||||
var left: Int = 0;
|
||||
var right: Int = nums.size - 1;
|
||||
// 将每个数字的平方经过排序后加入result数值
|
||||
var result: IntArray = IntArray(nums.size);
|
||||
var k: Int = nums.size - 1;
|
||||
while (left <= right) {
|
||||
// 从大到小,从后向前填满数组
|
||||
// [left, right] 控制循环
|
||||
if (nums[left] * nums[left] > nums[right] * nums[right]) {
|
||||
result[k--] = nums[left] * nums[left]
|
||||
left++
|
||||
}
|
||||
else {
|
||||
result[k--] = nums[right] * nums[right]
|
||||
right--
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Scala:
|
||||
|
||||
@@ -420,6 +449,24 @@ object Solution {
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
C#:
|
||||
```csharp
|
||||
public class Solution {
|
||||
public int[] SortedSquares(int[] nums) {
|
||||
int k = nums.Length - 1;
|
||||
int[] result = new int[nums.Length];
|
||||
for (int i = 0, j = nums.Length - 1;i <= j;){
|
||||
if (nums[i] * nums[i] < nums[j] * nums[j]) {
|
||||
result[k--] = nums[j] * nums[j];
|
||||
j--;
|
||||
} else {
|
||||
result[k--] = nums[i] * nums[i];
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
```
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
||||
@@ -374,6 +374,34 @@ func removeDuplicates(_ s: String) -> String {
|
||||
return String(stack)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
PHP:
|
||||
```php
|
||||
class Solution {
|
||||
function removeDuplicates($s) {
|
||||
$stack = new SplStack();
|
||||
for($i=0;$i<strlen($s);$i++){
|
||||
if($stack->isEmpty() || $s[$i] != $stack->top()){
|
||||
$stack->push($s[$i]);
|
||||
}else{
|
||||
$stack->pop();
|
||||
}
|
||||
}
|
||||
|
||||
$result = "";
|
||||
while(!$stack->isEmpty()){
|
||||
$result.= $stack->top();
|
||||
$stack->pop();
|
||||
}
|
||||
|
||||
// 此时字符串需要反转一下
|
||||
return strrev($result);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
Scala:
|
||||
```scala
|
||||
object Solution {
|
||||
@@ -396,5 +424,6 @@ object Solution {
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
||||
@@ -277,6 +277,37 @@ var lastStoneWeightII = function (stones) {
|
||||
};
|
||||
```
|
||||
|
||||
C版本
|
||||
```c
|
||||
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
|
||||
|
||||
int getSum(int *stones, int stoneSize) {
|
||||
int sum = 0, i;
|
||||
for (i = 0; i < stoneSize; ++i)
|
||||
sum += stones[i];
|
||||
return sum;
|
||||
}
|
||||
|
||||
int lastStoneWeightII(int* stones, int stonesSize){
|
||||
int sum = getSum(stones, stonesSize);
|
||||
int target = sum / 2;
|
||||
int i, j;
|
||||
|
||||
// 初始化dp数组
|
||||
int *dp = (int*)malloc(sizeof(int) * (target + 1));
|
||||
memset(dp, 0, sizeof(int) * (target + 1));
|
||||
for (j = stones[0]; j <= target; ++j)
|
||||
dp[j] = stones[0];
|
||||
|
||||
// 递推公式:dp[j] = max(dp[j], dp[j - stones[i]] + stones[i])
|
||||
for (i = 1; i < stonesSize; ++i) {
|
||||
for (j = target; j >= stones[i]; --j)
|
||||
dp[j] = MAX(dp[j], dp[j - stones[i]] + stones[i]);
|
||||
}
|
||||
return sum - dp[target] - dp[target];
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
TypeScript版本
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -123,6 +123,46 @@ class Solution:
|
||||
```
|
||||
Go:
|
||||
|
||||
```go
|
||||
/**
|
||||
* Definition for a binary tree node.
|
||||
* type TreeNode struct {
|
||||
* Val int
|
||||
* Left *TreeNode
|
||||
* Right *TreeNode
|
||||
* }
|
||||
*/
|
||||
func balanceBST(root *TreeNode) *TreeNode {
|
||||
// 二叉搜索树中序遍历得到有序数组
|
||||
nums := []int{}
|
||||
// 中序递归遍历二叉树
|
||||
var travel func(node *TreeNode)
|
||||
travel = func(node *TreeNode) {
|
||||
if node == nil {
|
||||
return
|
||||
}
|
||||
travel(node.Left)
|
||||
nums = append(nums, node.Val)
|
||||
travel(node.Right)
|
||||
}
|
||||
// 二分法保证左右子树高度差不超过一(题目要求返回的仍是二叉搜索树)
|
||||
var buildTree func(nums []int, left, right int) *TreeNode
|
||||
buildTree = func(nums []int, left, right int) *TreeNode {
|
||||
if left > right {
|
||||
return nil
|
||||
}
|
||||
mid := left + (right-left) >> 1
|
||||
root := &TreeNode{Val: nums[mid]}
|
||||
root.Left = buildTree(nums, left, mid-1)
|
||||
root.Right = buildTree(nums, mid+1, right)
|
||||
return root
|
||||
}
|
||||
travel(root)
|
||||
return buildTree(nums, 0, len(nums)-1)
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
JavaScript:
|
||||
```javascript
|
||||
var balanceBST = function(root) {
|
||||
@@ -148,6 +188,30 @@ var balanceBST = function(root) {
|
||||
};
|
||||
```
|
||||
|
||||
TypeScript:
|
||||
|
||||
```typescript
|
||||
function balanceBST(root: TreeNode | null): TreeNode | null {
|
||||
const inorderArr: number[] = [];
|
||||
inorderTraverse(root, inorderArr);
|
||||
return buildTree(inorderArr, 0, inorderArr.length - 1);
|
||||
};
|
||||
function inorderTraverse(node: TreeNode | null, arr: number[]): void {
|
||||
if (node === null) return;
|
||||
inorderTraverse(node.left, arr);
|
||||
arr.push(node.val);
|
||||
inorderTraverse(node.right, arr);
|
||||
}
|
||||
function buildTree(arr: number[], left: number, right: number): TreeNode | null {
|
||||
if (left > right) return null;
|
||||
const mid = (left + right) >> 1;
|
||||
const resNode: TreeNode = new TreeNode(arr[mid]);
|
||||
resNode.left = buildTree(arr, left, mid - 1);
|
||||
resNode.right = buildTree(arr, mid + 1, right);
|
||||
return resNode;
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
-----------------------
|
||||
|
||||
@@ -506,6 +506,37 @@ function spaceLen($s){
|
||||
}
|
||||
```
|
||||
|
||||
Rust
|
||||
|
||||
```Rust
|
||||
impl Solution {
|
||||
pub fn replace_space(s: String) -> String {
|
||||
let mut len: usize = s.len();
|
||||
let mut s = s.chars().collect::<Vec<char>>();
|
||||
let mut count = 0;
|
||||
for i in &s {
|
||||
if i.is_ascii_whitespace() {
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
let mut new_len = len + count * 2;
|
||||
s.resize(new_len, ' ');
|
||||
while len < new_len {
|
||||
len -= 1;
|
||||
new_len -= 1;
|
||||
if s[len].is_ascii_whitespace() {
|
||||
s[new_len] = '0';
|
||||
s[new_len - 1] = '2';
|
||||
s[new_len - 2] = '%';
|
||||
new_len -= 2;
|
||||
}
|
||||
else { s[new_len] = s[len] }
|
||||
}
|
||||
s.iter().collect::<String>()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
||||
@@ -341,7 +341,30 @@ object Solution {
|
||||
}
|
||||
```
|
||||
|
||||
Rust:
|
||||
|
||||
```Rust
|
||||
impl Solution {
|
||||
pub fn reverse(s: &mut Vec<char>, mut begin: usize, mut end: usize){
|
||||
while begin < end {
|
||||
let temp = s[begin];
|
||||
s[begin] = s[end];
|
||||
s[end] = temp;
|
||||
begin += 1;
|
||||
end -= 1;
|
||||
}
|
||||
}
|
||||
pub fn reverse_left_words(s: String, n: i32) -> String {
|
||||
let len = s.len();
|
||||
let mut s = s.chars().collect::<Vec<char>>();
|
||||
let n = n as usize;
|
||||
Self::reverse(&mut s, 0, n - 1);
|
||||
Self::reverse(&mut s, n, len - 1);
|
||||
Self::reverse(&mut s, 0, len - 1);
|
||||
s.iter().collect::<String>()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -356,9 +356,13 @@ func test_2_wei_bag_problem1(weight, value []int, bagweight int) int {
|
||||
// 递推公式
|
||||
for i := 1; i < len(weight); i++ {
|
||||
//正序,也可以倒序
|
||||
for j := weight[i];j<= bagweight ; j++ {
|
||||
dp[i][j] = max(dp[i-1][j], dp[i-1][j-weight[i]]+value[i])
|
||||
}
|
||||
for j := 0; j <= bagweight; j++ {
|
||||
if j < weight[i] {
|
||||
dp[i][j] = dp[i-1][j]
|
||||
} else {
|
||||
dp[i][j] = max(dp[i-1][j], dp[i-1][j-weight[i]]+value[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
return dp[len(weight)-1][bagweight]
|
||||
}
|
||||
|
||||
@@ -13,21 +13,21 @@
|
||||
|
||||
图示两个链表在节点 c1 开始相交:
|
||||
|
||||

|
||||

|
||||
|
||||
题目数据 保证 整个链式结构中不存在环。
|
||||
|
||||
注意,函数返回结果后,链表必须 保持其原始结构 。
|
||||
注意,函数返回结果后,链表必须 保持其原始结构 。
|
||||
|
||||
示例 1:
|
||||
示例 1:
|
||||
|
||||

|
||||

|
||||
|
||||
示例 2:
|
||||
|
||||

|
||||

|
||||
|
||||
示例 3:
|
||||
示例 3:
|
||||
|
||||

|
||||
|
||||
@@ -100,7 +100,7 @@ public:
|
||||
## 其他语言版本
|
||||
|
||||
|
||||
### Java
|
||||
### Java
|
||||
```Java
|
||||
public class Solution {
|
||||
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
|
||||
@@ -144,11 +144,11 @@ public class Solution {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
### Python
|
||||
### Python
|
||||
```python
|
||||
|
||||
class Solution:
|
||||
@@ -162,15 +162,15 @@ class Solution:
|
||||
"""
|
||||
cur_a, cur_b = headA, headB # 用两个指针代替a和b
|
||||
|
||||
|
||||
|
||||
while cur_a != cur_b:
|
||||
cur_a = cur_a.next if cur_a else headB # 如果a走完了,那么就切换到b走
|
||||
cur_b = cur_b.next if cur_b else headA # 同理,b走完了就切换到a
|
||||
|
||||
|
||||
return cur_a
|
||||
```
|
||||
|
||||
### Go
|
||||
### Go
|
||||
|
||||
```go
|
||||
func getIntersectionNode(headA, headB *ListNode) *ListNode {
|
||||
@@ -208,7 +208,30 @@ func getIntersectionNode(headA, headB *ListNode) *ListNode {
|
||||
}
|
||||
```
|
||||
|
||||
### javaScript
|
||||
双指针
|
||||
|
||||
```go
|
||||
func getIntersectionNode(headA, headB *ListNode) *ListNode {
|
||||
l1,l2 := headA, headB
|
||||
for l1 != l2 {
|
||||
if l1 != nil {
|
||||
l1 = l1.Next
|
||||
} else {
|
||||
l1 = headB
|
||||
}
|
||||
|
||||
if l2 != nil {
|
||||
l2 = l2.Next
|
||||
} else {
|
||||
l2 = headA
|
||||
}
|
||||
}
|
||||
|
||||
return l1
|
||||
}
|
||||
```
|
||||
|
||||
### javaScript
|
||||
|
||||
```js
|
||||
var getListLen = function(head) {
|
||||
@@ -218,9 +241,9 @@ var getListLen = function(head) {
|
||||
cur = cur.next;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
}
|
||||
var getIntersectionNode = function(headA, headB) {
|
||||
let curA = headA,curB = headB,
|
||||
let curA = headA,curB = headB,
|
||||
lenA = getListLen(headA),
|
||||
lenB = getListLen(headB);
|
||||
if(lenA < lenB) {
|
||||
|
||||
Reference in New Issue
Block a user