mirror of
https://github.com/youngyangyang04/leetcode-master.git
synced 2025-07-08 00:43:04 +08:00
Merge branch 'master' of github.com:youngyangyang04/leetcode-master
This commit is contained in:
@ -186,6 +186,24 @@ var twoSum = function (nums, target) {
|
||||
};
|
||||
```
|
||||
|
||||
TypeScript:
|
||||
|
||||
```typescript
|
||||
function twoSum(nums: number[], target: number): number[] {
|
||||
let helperMap: Map<number, number> = new Map();
|
||||
let index: number | undefined;
|
||||
let resArr: number[] = [];
|
||||
for (let i = 0, length = nums.length; i < length; i++) {
|
||||
index = helperMap.get(target - nums[i]);
|
||||
if (index !== undefined) {
|
||||
resArr = [i, index];
|
||||
}
|
||||
helperMap.set(nums[i], i);
|
||||
}
|
||||
return resArr;
|
||||
};
|
||||
```
|
||||
|
||||
php
|
||||
|
||||
```php
|
||||
|
@ -462,7 +462,92 @@ var longestPalindrome = function(s) {
|
||||
};
|
||||
```
|
||||
|
||||
## C
|
||||
动态规划:
|
||||
```c
|
||||
//初始化dp数组,全部初始为false
|
||||
bool **initDP(int strLen) {
|
||||
bool **dp = (bool **)malloc(sizeof(bool *) * strLen);
|
||||
int i, j;
|
||||
for(i = 0; i < strLen; ++i) {
|
||||
dp[i] = (bool *)malloc(sizeof(bool) * strLen);
|
||||
for(j = 0; j < strLen; ++j)
|
||||
dp[i][j] = false;
|
||||
}
|
||||
return dp;
|
||||
}
|
||||
|
||||
char * longestPalindrome(char * s){
|
||||
//求出字符串长度
|
||||
int strLen = strlen(s);
|
||||
//初始化dp数组,元素初始化为false
|
||||
bool **dp = initDP(strLen);
|
||||
int maxLength = 0, left = 0, right = 0;
|
||||
|
||||
//从下到上,从左到右遍历
|
||||
int i, j;
|
||||
for(i = strLen - 1; i >= 0; --i) {
|
||||
for(j = i; j < strLen; ++j) {
|
||||
//若当前i与j所指字符一样
|
||||
if(s[i] == s[j]) {
|
||||
//若i、j指向相邻字符或同一字符,则为回文字符串
|
||||
if(j - i <= 1)
|
||||
dp[i][j] = true;
|
||||
//若i+1与j-1所指字符串为回文字符串,则i、j所指字符串为回文字符串
|
||||
else if(dp[i + 1][j - 1])
|
||||
dp[i][j] = true;
|
||||
}
|
||||
//若新的字符串的长度大于之前的最大长度,进行更新
|
||||
if(dp[i][j] && j - i + 1 > maxLength) {
|
||||
maxLength = j - i + 1;
|
||||
left = i;
|
||||
right = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
//复制回文字符串,并返回
|
||||
char *ret = (char*)malloc(sizeof(char) * (maxLength + 1));
|
||||
memcpy(ret, s + left, maxLength);
|
||||
ret[maxLength] = 0;
|
||||
return ret;
|
||||
}
|
||||
```
|
||||
|
||||
双指针:
|
||||
```c
|
||||
int left, maxLength;
|
||||
void extend(char *str, int i, int j, int size) {
|
||||
while(i >= 0 && j < size && str[i] == str[j]) {
|
||||
//若当前子字符串长度大于最长的字符串长度,进行更新
|
||||
if(j - i + 1 > maxLength) {
|
||||
maxLength = j - i + 1;
|
||||
left = i;
|
||||
}
|
||||
//左指针左移,右指针右移。扩大搜索范围
|
||||
++j, --i;
|
||||
}
|
||||
}
|
||||
|
||||
char * longestPalindrome(char * s){
|
||||
left = right = maxLength = 0;
|
||||
int size = strlen(s);
|
||||
|
||||
int i;
|
||||
for(i = 0; i < size; ++i) {
|
||||
//长度为单数的子字符串
|
||||
extend(s, i, i, size);
|
||||
//长度为双数的子字符串
|
||||
extend(s, i, i + 1, size);
|
||||
}
|
||||
|
||||
//复制子字符串
|
||||
char *subStr = (char *)malloc(sizeof(char) * (maxLength + 1));
|
||||
memcpy(subStr, s + left, maxLength);
|
||||
subStr[maxLength] = 0;
|
||||
|
||||
return subStr;
|
||||
}
|
||||
```
|
||||
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
@ -332,7 +332,43 @@ var threeSum = function(nums) {
|
||||
return res;
|
||||
};
|
||||
```
|
||||
TypeScript:
|
||||
|
||||
```typescript
|
||||
function threeSum(nums: number[]): number[][] {
|
||||
nums.sort((a, b) => a - b);
|
||||
let length = nums.length;
|
||||
let left: number = 0,
|
||||
right: number = length - 1;
|
||||
let resArr: number[][] = [];
|
||||
for (let i = 0; i < length; i++) {
|
||||
if (i > 0 && nums[i] === nums[i - 1]) {
|
||||
continue;
|
||||
}
|
||||
left = i + 1;
|
||||
right = length - 1;
|
||||
while (left < right) {
|
||||
let total: number = nums[i] + nums[left] + nums[right];
|
||||
if (total === 0) {
|
||||
resArr.push([nums[i], nums[left], nums[right]]);
|
||||
left++;
|
||||
right--;
|
||||
while (nums[right] === nums[right + 1]) {
|
||||
right--;
|
||||
}
|
||||
while (nums[left] === nums[left - 1]) {
|
||||
left++;
|
||||
}
|
||||
} else if (total < 0) {
|
||||
left++;
|
||||
} else {
|
||||
right--;
|
||||
}
|
||||
}
|
||||
}
|
||||
return resArr;
|
||||
};
|
||||
```
|
||||
|
||||
ruby:
|
||||
```ruby
|
||||
@ -509,5 +545,64 @@ int** threeSum(int* nums, int numsSize, int* returnSize, int** returnColumnSizes
|
||||
}
|
||||
```
|
||||
|
||||
C#:
|
||||
```csharp
|
||||
public class Solution
|
||||
{
|
||||
public IList<IList<int>> ThreeSum(int[] nums)
|
||||
{
|
||||
var result = new List<IList<int>>();
|
||||
|
||||
Array.Sort(nums);
|
||||
|
||||
for (int i = 0; i < nums.Length - 2; i++)
|
||||
{
|
||||
int n1 = nums[i];
|
||||
|
||||
if (n1 > 0)
|
||||
break;
|
||||
|
||||
if (i > 0 && n1 == nums[i - 1])
|
||||
continue;
|
||||
|
||||
int left = i + 1;
|
||||
int right = nums.Length - 1;
|
||||
|
||||
while (left < right)
|
||||
{
|
||||
int n2 = nums[left];
|
||||
int n3 = nums[right];
|
||||
int sum = n1 + n2 + n3;
|
||||
|
||||
if (sum > 0)
|
||||
{
|
||||
right--;
|
||||
}
|
||||
else if (sum < 0)
|
||||
{
|
||||
left++;
|
||||
}
|
||||
else
|
||||
{
|
||||
result.Add(new List<int> { n1, n2, n3 });
|
||||
|
||||
while (left < right && nums[left] == n2)
|
||||
{
|
||||
left++;
|
||||
}
|
||||
|
||||
while (left < right && nums[right] == n3)
|
||||
{
|
||||
right--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
@ -311,7 +311,49 @@ var fourSum = function(nums, target) {
|
||||
};
|
||||
```
|
||||
|
||||
TypeScript:
|
||||
|
||||
```typescript
|
||||
function fourSum(nums: number[], target: number): number[][] {
|
||||
nums.sort((a, b) => a - b);
|
||||
let first: number = 0,
|
||||
second: number,
|
||||
third: number,
|
||||
fourth: number;
|
||||
let length: number = nums.length;
|
||||
let resArr: number[][] = [];
|
||||
for (; first < length; first++) {
|
||||
if (first > 0 && nums[first] === nums[first - 1]) {
|
||||
continue;
|
||||
}
|
||||
for (second = first + 1; second < length; second++) {
|
||||
if ((second - first) > 1 && nums[second] === nums[second - 1]) {
|
||||
continue;
|
||||
}
|
||||
third = second + 1;
|
||||
fourth = length - 1;
|
||||
while (third < fourth) {
|
||||
let total: number = nums[first] + nums[second] + nums[third] + nums[fourth];
|
||||
if (total === target) {
|
||||
resArr.push([nums[first], nums[second], nums[third], nums[fourth]]);
|
||||
third++;
|
||||
fourth--;
|
||||
while (nums[third] === nums[third - 1]) third++;
|
||||
while (nums[fourth] === nums[fourth + 1]) fourth--;
|
||||
} else if (total < target) {
|
||||
third++;
|
||||
} else {
|
||||
fourth--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return resArr;
|
||||
};
|
||||
```
|
||||
|
||||
PHP:
|
||||
|
||||
```php
|
||||
class Solution {
|
||||
/**
|
||||
@ -403,5 +445,67 @@ func fourSum(_ nums: [Int], _ target: Int) -> [[Int]] {
|
||||
}
|
||||
```
|
||||
|
||||
C#:
|
||||
```csharp
|
||||
public class Solution
|
||||
{
|
||||
public IList<IList<int>> FourSum(int[] nums, int target)
|
||||
{
|
||||
var result = new List<IList<int>>();
|
||||
|
||||
Array.Sort(nums);
|
||||
|
||||
for (int i = 0; i < nums.Length - 3; i++)
|
||||
{
|
||||
int n1 = nums[i];
|
||||
if (i > 0 && n1 == nums[i - 1])
|
||||
continue;
|
||||
|
||||
for (int j = i + 1; j < nums.Length - 2; j++)
|
||||
{
|
||||
int n2 = nums[j];
|
||||
if (j > i + 1 && n2 == nums[j - 1])
|
||||
continue;
|
||||
|
||||
int left = j + 1;
|
||||
int right = nums.Length - 1;
|
||||
|
||||
while (left < right)
|
||||
{
|
||||
int n3 = nums[left];
|
||||
int n4 = nums[right];
|
||||
int sum = n1 + n2 + n3 + n4;
|
||||
|
||||
if (sum > target)
|
||||
{
|
||||
right--;
|
||||
}
|
||||
else if (sum < target)
|
||||
{
|
||||
left++;
|
||||
}
|
||||
else
|
||||
{
|
||||
result.Add(new List<int> { n1, n2, n3, n4 });
|
||||
|
||||
while (left < right && nums[left] == n3)
|
||||
{
|
||||
left++;
|
||||
}
|
||||
|
||||
while (left < right && nums[right] == n4)
|
||||
{
|
||||
right--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
@ -181,7 +181,71 @@ var removeNthFromEnd = function(head, n) {
|
||||
return ret.next;
|
||||
};
|
||||
```
|
||||
TypeScript:
|
||||
|
||||
版本一(快慢指针法):
|
||||
|
||||
```typescript
|
||||
function removeNthFromEnd(head: ListNode | null, n: number): ListNode | null {
|
||||
let newHead: ListNode | null = new ListNode(0, head);
|
||||
let slowNode: ListNode | null = newHead,
|
||||
fastNode: ListNode | null = newHead;
|
||||
for (let i = 0; i < n; i++) {
|
||||
fastNode = fastNode.next;
|
||||
}
|
||||
while (fastNode.next) {
|
||||
fastNode = fastNode.next;
|
||||
slowNode = slowNode.next;
|
||||
}
|
||||
slowNode.next = slowNode.next.next;
|
||||
return newHead.next;
|
||||
};
|
||||
```
|
||||
|
||||
版本二(计算节点总数法):
|
||||
|
||||
```typescript
|
||||
function removeNthFromEnd(head: ListNode | null, n: number): ListNode | null {
|
||||
let curNode: ListNode | null = head;
|
||||
let listSize: number = 0;
|
||||
while (curNode) {
|
||||
curNode = curNode.next;
|
||||
listSize++;
|
||||
}
|
||||
if (listSize === n) {
|
||||
head = head.next;
|
||||
} else {
|
||||
curNode = head;
|
||||
for (let i = 0; i < listSize - n - 1; i++) {
|
||||
curNode = curNode.next;
|
||||
}
|
||||
curNode.next = curNode.next.next;
|
||||
}
|
||||
return head;
|
||||
};
|
||||
```
|
||||
|
||||
版本三(递归倒退n法):
|
||||
|
||||
```typescript
|
||||
function removeNthFromEnd(head: ListNode | null, n: number): ListNode | null {
|
||||
let newHead: ListNode | null = new ListNode(0, head);
|
||||
let cnt = 0;
|
||||
function recur(node) {
|
||||
if (node === null) return;
|
||||
recur(node.next);
|
||||
cnt++;
|
||||
if (cnt === n + 1) {
|
||||
node.next = node.next.next;
|
||||
}
|
||||
}
|
||||
recur(newHead);
|
||||
return newHead.next;
|
||||
};
|
||||
```
|
||||
|
||||
Kotlin:
|
||||
|
||||
```Kotlin
|
||||
fun removeNthFromEnd(head: ListNode?, n: Int): ListNode? {
|
||||
val pre = ListNode(0).apply {
|
||||
|
@ -283,8 +283,60 @@ var isValid = function(s) {
|
||||
};
|
||||
```
|
||||
|
||||
TypeScript:
|
||||
|
||||
版本一:普通版
|
||||
|
||||
```typescript
|
||||
function isValid(s: string): boolean {
|
||||
let helperStack: string[] = [];
|
||||
for (let i = 0, length = s.length; i < length; i++) {
|
||||
let x: string = s[i];
|
||||
switch (x) {
|
||||
case '(':
|
||||
helperStack.push(')');
|
||||
break;
|
||||
case '[':
|
||||
helperStack.push(']');
|
||||
break;
|
||||
case '{':
|
||||
helperStack.push('}');
|
||||
break;
|
||||
default:
|
||||
if (helperStack.pop() !== x) return false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return helperStack.length === 0;
|
||||
};
|
||||
```
|
||||
|
||||
版本二:优化版
|
||||
|
||||
```typescript
|
||||
function isValid(s: string): boolean {
|
||||
type BracketMap = {
|
||||
[index: string]: string;
|
||||
}
|
||||
let helperStack: string[] = [];
|
||||
let bracketMap: BracketMap = {
|
||||
'(': ')',
|
||||
'[': ']',
|
||||
'{': '}'
|
||||
}
|
||||
for (let i of s) {
|
||||
if (bracketMap.hasOwnProperty(i)) {
|
||||
helperStack.push(bracketMap[i]);
|
||||
} else if (i !== helperStack.pop()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return helperStack.length === 0;
|
||||
};
|
||||
```
|
||||
|
||||
Swift
|
||||
|
||||
```swift
|
||||
func isValid(_ s: String) -> Bool {
|
||||
var stack = [String.Element]()
|
||||
|
@ -250,6 +250,38 @@ var swapPairs = function (head) {
|
||||
};
|
||||
```
|
||||
|
||||
TypeScript:
|
||||
|
||||
```typescript
|
||||
function swapPairs(head: ListNode | null): ListNode | null {
|
||||
/**
|
||||
* 初始状态:
|
||||
* curNode -> node1 -> node2 -> tmepNode
|
||||
* 转换过程:
|
||||
* curNode -> node2
|
||||
* curNode -> node2 -> node1
|
||||
* curNode -> node2 -> node1 -> tempNode
|
||||
* curNode = node1
|
||||
*/
|
||||
let retNode: ListNode | null = new ListNode(0, head),
|
||||
curNode: ListNode | null = retNode,
|
||||
node1: ListNode | null = null,
|
||||
node2: ListNode | null = null,
|
||||
tempNode: ListNode | null = null;
|
||||
|
||||
while (curNode && curNode.next && curNode.next.next) {
|
||||
node1 = curNode.next;
|
||||
node2 = curNode.next.next;
|
||||
tempNode = node2.next;
|
||||
curNode.next = node2;
|
||||
node2.next = node1;
|
||||
node1.next = tempNode;
|
||||
curNode = node1;
|
||||
}
|
||||
return retNode.next;
|
||||
};
|
||||
```
|
||||
|
||||
Kotlin:
|
||||
|
||||
```kotlin
|
||||
|
@ -42,7 +42,7 @@
|
||||
|
||||

|
||||
|
||||
很明显暴力解法的时间复杂度是O(n^2),这道题目暴力解法在leetcode上是可以过的。
|
||||
很明显暴力解法的时间复杂度是$O(n^2)$,这道题目暴力解法在leetcode上是可以过的。
|
||||
|
||||
代码如下:
|
||||
|
||||
|
@ -259,7 +259,7 @@ void getNext(int* next, const string& s)
|
||||
|
||||
然后还要对next数组进行初始化赋值,如下:
|
||||
|
||||
```
|
||||
```cpp
|
||||
int j = -1;
|
||||
next[0] = j;
|
||||
```
|
||||
@ -278,8 +278,8 @@ next[i] 表示 i(包括i)之前最长相等的前后缀长度(其实就是
|
||||
|
||||
所以遍历模式串s的循环下标i 要从 1开始,代码如下:
|
||||
|
||||
```
|
||||
for(int i = 1; i < s.size(); i++) {
|
||||
```cpp
|
||||
for (int i = 1; i < s.size(); i++) {
|
||||
```
|
||||
|
||||
如果 s[i] 与 s[j+1]不相同,也就是遇到 前后缀末尾不相同的情况,就要向前回退。
|
||||
@ -292,7 +292,7 @@ next[j]就是记录着j(包括j)之前的子串的相同前后缀的长度
|
||||
|
||||
所以,处理前后缀不相同的情况代码如下:
|
||||
|
||||
```
|
||||
```cpp
|
||||
while (j >= 0 && s[i] != s[j + 1]) { // 前后缀不相同了
|
||||
j = next[j]; // 向前回退
|
||||
}
|
||||
@ -300,7 +300,7 @@ while (j >= 0 && s[i] != s[j + 1]) { // 前后缀不相同了
|
||||
|
||||
3. 处理前后缀相同的情况
|
||||
|
||||
如果s[i] 与 s[j + 1] 相同,那么就同时向后移动i 和j 说明找到了相同的前后缀,同时还要将j(前缀的长度)赋给next[i], 因为next[i]要记录相同前后缀的长度。
|
||||
如果 s[i] 与 s[j + 1] 相同,那么就同时向后移动i 和j 说明找到了相同的前后缀,同时还要将j(前缀的长度)赋给next[i], 因为next[i]要记录相同前后缀的长度。
|
||||
|
||||
代码如下:
|
||||
|
||||
@ -346,7 +346,7 @@ void getNext(int* next, const string& s){
|
||||
|
||||
i就从0开始,遍历文本串,代码如下:
|
||||
|
||||
```
|
||||
```cpp
|
||||
for (int i = 0; i < s.size(); i++)
|
||||
```
|
||||
|
||||
@ -356,7 +356,7 @@ for (int i = 0; i < s.size(); i++)
|
||||
|
||||
代码如下:
|
||||
|
||||
```
|
||||
```cpp
|
||||
while(j >= 0 && s[i] != t[j + 1]) {
|
||||
j = next[j];
|
||||
}
|
||||
@ -364,7 +364,7 @@ while(j >= 0 && s[i] != t[j + 1]) {
|
||||
|
||||
如果 s[i] 与 t[j + 1] 相同,那么i 和 j 同时向后移动, 代码如下:
|
||||
|
||||
```
|
||||
```cpp
|
||||
if (s[i] == t[j + 1]) {
|
||||
j++; // i的增加在for循环里
|
||||
}
|
||||
@ -376,7 +376,7 @@ if (s[i] == t[j + 1]) {
|
||||
|
||||
代码如下:
|
||||
|
||||
```
|
||||
```cpp
|
||||
if (j == (t.size() - 1) ) {
|
||||
return (i - t.size() + 1);
|
||||
}
|
||||
@ -929,6 +929,83 @@ var strStr = function (haystack, needle) {
|
||||
};
|
||||
```
|
||||
|
||||
TypeScript版本:
|
||||
|
||||
> 前缀表统一减一
|
||||
|
||||
```typescript
|
||||
function strStr(haystack: string, needle: string): number {
|
||||
function getNext(str: string): number[] {
|
||||
let next: number[] = [];
|
||||
let j: number = -1;
|
||||
next[0] = j;
|
||||
for (let i = 1, length = str.length; i < length; i++) {
|
||||
while (j >= 0 && str[i] !== str[j + 1]) {
|
||||
j = next[j];
|
||||
}
|
||||
if (str[i] === str[j + 1]) {
|
||||
j++;
|
||||
}
|
||||
next[i] = j;
|
||||
}
|
||||
return next;
|
||||
}
|
||||
if (needle.length === 0) return 0;
|
||||
let next: number[] = getNext(needle);
|
||||
let j: number = -1;
|
||||
for (let i = 0, length = haystack.length; i < length; i++) {
|
||||
while (j >= 0 && haystack[i] !== needle[j + 1]) {
|
||||
j = next[j];
|
||||
}
|
||||
if (haystack[i] === needle[j + 1]) {
|
||||
if (j === needle.length - 2) {
|
||||
return i - j - 1;
|
||||
}
|
||||
j++;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
};
|
||||
```
|
||||
|
||||
> 前缀表不减一
|
||||
|
||||
```typescript
|
||||
// 不减一版本
|
||||
function strStr(haystack: string, needle: string): number {
|
||||
function getNext(str: string): number[] {
|
||||
let next: number[] = [];
|
||||
let j: number = 0;
|
||||
next[0] = j;
|
||||
for (let i = 1, length = str.length; i < length; i++) {
|
||||
while (j > 0 && str[i] !== str[j]) {
|
||||
j = next[j - 1];
|
||||
}
|
||||
if (str[i] === str[j]) {
|
||||
j++;
|
||||
}
|
||||
next[i] = j;
|
||||
}
|
||||
return next;
|
||||
}
|
||||
if (needle.length === 0) return 0;
|
||||
let next: number[] = getNext(needle);
|
||||
let j: number = 0;
|
||||
for (let i = 0, length = haystack.length; i < length; i++) {
|
||||
while (j > 0 && haystack[i] !== needle[j]) {
|
||||
j = next[j - 1];
|
||||
}
|
||||
if (haystack[i] === needle[j]) {
|
||||
if (j === needle.length - 1) {
|
||||
return i - j;
|
||||
}
|
||||
j++;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
```
|
||||
|
||||
Swift 版本
|
||||
|
||||
> 前缀表统一减一
|
||||
|
@ -81,7 +81,7 @@ public:
|
||||
for (int j = nums.size() - 1; j > i; j--) {
|
||||
if (nums[j] > nums[i]) {
|
||||
swap(nums[j], nums[i]);
|
||||
sort(nums.begin() + i + 1, nums.end());
|
||||
reverse(nums.begin() + i + 1, nums.end());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -389,6 +389,51 @@ class Solution:
|
||||
### Go
|
||||
|
||||
```go
|
||||
func searchRange(nums []int, target int) []int {
|
||||
leftBorder := getLeft(nums, target)
|
||||
rightBorder := getRight(nums, target)
|
||||
// 情况一
|
||||
if leftBorder == -2 || rightBorder == -2 {
|
||||
return []int{-1, -1}
|
||||
}
|
||||
// 情况三
|
||||
if rightBorder - leftBorder > 1 {
|
||||
return []int{leftBorder + 1, rightBorder - 1}
|
||||
}
|
||||
// 情况二
|
||||
return []int{-1, -1}
|
||||
}
|
||||
|
||||
func getLeft(nums []int, target int) int {
|
||||
left, right := 0, len(nums)-1
|
||||
border := -2 // 记录border没有被赋值的情况;这里不能赋值-1,target = num[0]时,会无法区分情况一和情况二
|
||||
for left <= right { // []闭区间
|
||||
mid := left + ((right - left) >> 1)
|
||||
if nums[mid] >= target { // 找到第一个等于target的位置
|
||||
right = mid - 1
|
||||
border = right
|
||||
} else {
|
||||
left = mid + 1
|
||||
}
|
||||
}
|
||||
return border
|
||||
}
|
||||
|
||||
func getRight(nums []int, target int) int {
|
||||
left, right := 0, len(nums) - 1
|
||||
border := -2
|
||||
for left <= right {
|
||||
mid := left + ((right - left) >> 1)
|
||||
if nums[mid] > target {
|
||||
right = mid - 1
|
||||
} else { // 找到第一个大于target的位置
|
||||
left = mid + 1
|
||||
border = left
|
||||
}
|
||||
}
|
||||
return border
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
### JavaScript
|
||||
|
@ -346,69 +346,56 @@ class Solution {
|
||||
|
||||
### Go
|
||||
```Go
|
||||
import "strings"
|
||||
var res [][]string
|
||||
|
||||
func isValid(board [][]string, row, col int) (res bool){
|
||||
n := len(board)
|
||||
for i:=0; i < row; i++ {
|
||||
if board[i][col] == "Q" {
|
||||
return false
|
||||
}
|
||||
}
|
||||
for i := 0; i < n; i++{
|
||||
if board[row][i] == "Q" {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
for i ,j := row, col; i >= 0 && j >=0 ; i, j = i - 1, j- 1{
|
||||
if board[i][j] == "Q"{
|
||||
return false
|
||||
}
|
||||
}
|
||||
for i, j := row, col; i >=0 && j < n; i,j = i-1, j+1 {
|
||||
if board[i][j] == "Q" {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func backtrack(board [][]string, row int) {
|
||||
size := len(board)
|
||||
if row == size{
|
||||
temp := make([]string, size)
|
||||
for i := 0; i<size;i++{
|
||||
temp[i] = strings.Join(board[i],"")
|
||||
}
|
||||
res =append(res,temp)
|
||||
return
|
||||
}
|
||||
for col := 0; col < size; col++ {
|
||||
if !isValid(board, row, col){
|
||||
continue
|
||||
}
|
||||
board[row][col] = "Q"
|
||||
backtrack(board, row+1)
|
||||
board[row][col] = "."
|
||||
}
|
||||
}
|
||||
|
||||
func solveNQueens(n int) [][]string {
|
||||
res = [][]string{}
|
||||
board := make([][]string, n)
|
||||
for i := 0; i < n; i++{
|
||||
board[i] = make([]string, n)
|
||||
}
|
||||
for i := 0; i < n; i++{
|
||||
for j := 0; j<n;j++{
|
||||
board[i][j] = "."
|
||||
}
|
||||
}
|
||||
backtrack(board, 0)
|
||||
var res [][]string
|
||||
chessboard := make([][]string, n)
|
||||
for i := 0; i < n; i++ {
|
||||
chessboard[i] = make([]string, n)
|
||||
}
|
||||
for i := 0; i < n; i++ {
|
||||
for j := 0; j < n; j++ {
|
||||
chessboard[i][j] = "."
|
||||
}
|
||||
}
|
||||
var backtrack func(int)
|
||||
backtrack = func(row int) {
|
||||
if row == n {
|
||||
temp := make([]string, n)
|
||||
for i, rowStr := range chessboard {
|
||||
temp[i] = strings.Join(rowStr, "")
|
||||
}
|
||||
res = append(res, temp)
|
||||
return
|
||||
}
|
||||
for i := 0; i < n; i++ {
|
||||
if isValid(n, row, i, chessboard) {
|
||||
chessboard[row][i] = "Q"
|
||||
backtrack(row + 1)
|
||||
chessboard[row][i] = "."
|
||||
}
|
||||
}
|
||||
}
|
||||
backtrack(0)
|
||||
return res
|
||||
}
|
||||
|
||||
return res
|
||||
func isValid(n, row, col int, chessboard [][]string) bool {
|
||||
for i := 0; i < row; i++ {
|
||||
if chessboard[i][col] == "Q" {
|
||||
return false
|
||||
}
|
||||
}
|
||||
for i, j := row-1, col-1; i >= 0 && j >= 0; i, j = i-1, j-1 {
|
||||
if chessboard[i][j] == "Q" {
|
||||
return false
|
||||
}
|
||||
}
|
||||
for i, j := row-1, col+1; i >= 0 && j < n; i, j = i-1, j+1 {
|
||||
if chessboard[i][j] == "Q" {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
```
|
||||
### Javascript
|
||||
|
@ -143,5 +143,65 @@ var totalNQueens = function(n) {
|
||||
return count;
|
||||
};
|
||||
```
|
||||
|
||||
C
|
||||
```c
|
||||
//path[i]为在i行,path[i]列上存在皇后
|
||||
int *path;
|
||||
int pathTop;
|
||||
int answer;
|
||||
//检查当前level行index列放置皇后是否合法
|
||||
int isValid(int index, int level) {
|
||||
int i;
|
||||
//updater为若斜角存在皇后,其所应在的列
|
||||
//用来检查左上45度是否存在皇后
|
||||
int lCornerUpdater = index - level;
|
||||
//用来检查右上135度是否存在皇后
|
||||
int rCornerUpdater = index + level;
|
||||
for(i = 0; i < pathTop; ++i) {
|
||||
//path[i] == index检查index列是否存在皇后
|
||||
//检查斜角皇后:只要path[i] == updater,就说明当前位置不可放置皇后。
|
||||
//path[i] == lCornerUpdater检查左上角45度是否有皇后
|
||||
//path[i] == rCornerUpdater检查右上角135度是否有皇后
|
||||
if(path[i] == index || path[i] == lCornerUpdater || path[i] == rCornerUpdater)
|
||||
return 0;
|
||||
//更新updater指向下一行对应的位置
|
||||
++lCornerUpdater;
|
||||
--rCornerUpdater;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
//回溯算法:level为当前皇后行数
|
||||
void backTracking(int n, int level) {
|
||||
//若path中元素个数已经为n,则证明有一种解法。answer+1
|
||||
if(pathTop == n) {
|
||||
++answer;
|
||||
return;
|
||||
}
|
||||
|
||||
int i;
|
||||
for(i = 0; i < n; ++i) {
|
||||
//若当前level行,i列是合法的放置位置。就将i放入path中
|
||||
if(isValid(i, level)) {
|
||||
path[pathTop++] = i;
|
||||
backTracking(n, level + 1);
|
||||
//回溯
|
||||
--pathTop;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int totalNQueens(int n){
|
||||
answer = 0;
|
||||
pathTop = 0;
|
||||
path = (int *)malloc(sizeof(int) * n);
|
||||
|
||||
backTracking(n, 0);
|
||||
|
||||
return answer;
|
||||
}
|
||||
```
|
||||
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
@ -131,7 +131,46 @@ public:
|
||||
* [59.螺旋矩阵II](https://leetcode-cn.com/problems/spiral-matrix-ii/)
|
||||
* [剑指Offer 29.顺时针打印矩阵](https://leetcode-cn.com/problems/shun-shi-zhen-da-yin-ju-zhen-lcof/)
|
||||
|
||||
## 其他语言版本
|
||||
Python:
|
||||
```python
|
||||
class Solution:
|
||||
def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
|
||||
m, n = len(matrix), len(matrix[0])
|
||||
left, right, up, down = 0, n - 1, 0, m - 1 # 定位四个方向的边界,闭区间
|
||||
res = []
|
||||
|
||||
while True:
|
||||
for i in range(left, right + 1): # 上边,从左到右
|
||||
res.append(matrix[up][i])
|
||||
up += 1 # 上边界下移
|
||||
|
||||
if len(res) >= m * n: # 判断是否已经遍历完
|
||||
break
|
||||
|
||||
for i in range(up, down + 1): # 右边,从上到下
|
||||
res.append(matrix[i][right])
|
||||
right -= 1 # 右边界左移
|
||||
|
||||
if len(res) >= m * n:
|
||||
break
|
||||
|
||||
for i in range(right, left - 1, -1): # 下边,从右到左
|
||||
res.append(matrix[down][i])
|
||||
down -= 1 # 下边界上移
|
||||
|
||||
if len(res) >= m * n:
|
||||
break
|
||||
|
||||
for i in range(down, up - 1, -1): # 左边,从下到上
|
||||
res.append(matrix[i][left])
|
||||
left += 1 # 左边界右移
|
||||
|
||||
if len(res) >= m * n:
|
||||
break
|
||||
|
||||
return res
|
||||
```
|
||||
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
@ -287,6 +287,51 @@ var generateMatrix = function(n) {
|
||||
|
||||
```
|
||||
|
||||
TypeScript:
|
||||
|
||||
```typescript
|
||||
function generateMatrix(n: number): number[][] {
|
||||
let loopNum: number = Math.floor(n / 2);
|
||||
const resArr: number[][] = new Array(n).fill(1).map(i => new Array(n));
|
||||
let chunkNum: number = n - 1;
|
||||
let startX: number = 0;
|
||||
let startY: number = 0;
|
||||
let value: number = 1;
|
||||
let x: number, y: number;
|
||||
while (loopNum--) {
|
||||
x = startX;
|
||||
y = startY;
|
||||
while (x < startX + chunkNum) {
|
||||
resArr[y][x] = value;
|
||||
x++;
|
||||
value++;
|
||||
}
|
||||
while (y < startY + chunkNum) {
|
||||
resArr[y][x] = value;
|
||||
y++;
|
||||
value++;
|
||||
}
|
||||
while (x > startX) {
|
||||
resArr[y][x] = value;
|
||||
x--;
|
||||
value++;
|
||||
}
|
||||
while (y > startY) {
|
||||
resArr[y][x] = value;
|
||||
y--;
|
||||
value++;
|
||||
}
|
||||
startX++;
|
||||
startY++;
|
||||
chunkNum -= 2;
|
||||
}
|
||||
if (n % 2 === 1) {
|
||||
resArr[startX][startY] = value;
|
||||
}
|
||||
return resArr;
|
||||
};
|
||||
```
|
||||
|
||||
Go:
|
||||
|
||||
```go
|
||||
|
@ -347,6 +347,42 @@ var uniquePaths = function(m, n) {
|
||||
};
|
||||
```
|
||||
|
||||
### C
|
||||
```c
|
||||
//初始化dp数组
|
||||
int **initDP(int m, int n) {
|
||||
//动态开辟dp数组
|
||||
int **dp = (int**)malloc(sizeof(int *) * m);
|
||||
int i, j;
|
||||
for(i = 0; i < m; ++i) {
|
||||
dp[i] = (int *)malloc(sizeof(int) * n);
|
||||
}
|
||||
|
||||
//从0,0到i,0只有一种走法,所以dp[i][0]都是1,同理dp[0][j]也是1
|
||||
for(i = 0; i < m; ++i)
|
||||
dp[i][0] = 1;
|
||||
for(j = 0; j < n; ++j)
|
||||
dp[0][j] = 1;
|
||||
return dp;
|
||||
}
|
||||
|
||||
int uniquePaths(int m, int n){
|
||||
//dp数组,dp[i][j]代表从dp[0][0]到dp[i][j]有几种走法
|
||||
int **dp = initDP(m, n);
|
||||
|
||||
int i, j;
|
||||
//到达dp[i][j]只能从dp[i-1][j]和dp[i][j-1]出发
|
||||
//dp[i][j] = dp[i-1][j] + dp[i][j-1]
|
||||
for(i = 1; i < m; ++i) {
|
||||
for(j = 1; j < n; ++j) {
|
||||
dp[i][j] = dp[i-1][j] + dp[i][j-1];
|
||||
}
|
||||
}
|
||||
int result = dp[m-1][n-1];
|
||||
free(dp);
|
||||
return result;
|
||||
}
|
||||
```
|
||||
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
@ -265,46 +265,33 @@ class Solution:
|
||||
|
||||
```go
|
||||
func uniquePathsWithObstacles(obstacleGrid [][]int) int {
|
||||
m,n:= len(obstacleGrid),len(obstacleGrid[0])
|
||||
m, n := len(obstacleGrid), len(obstacleGrid[0])
|
||||
// 定义一个dp数组
|
||||
dp := make([][]int,m)
|
||||
for i,_ := range dp {
|
||||
dp[i] = make([]int,n)
|
||||
dp := make([][]int, m)
|
||||
for i, _ := range dp {
|
||||
dp[i] = make([]int, n)
|
||||
}
|
||||
// 初始化
|
||||
for i:=0;i<m;i++ {
|
||||
// 如果是障碍物, 后面的就都是0, 不用循环了
|
||||
if obstacleGrid[i][0] == 1 {
|
||||
break
|
||||
}
|
||||
dp[i][0]=1
|
||||
// 初始化, 如果是障碍物, 后面的就都是0, 不用循环了
|
||||
for i := 0; i < m && obstacleGrid[i][0] == 0; i++ {
|
||||
dp[i][0] = 1
|
||||
}
|
||||
for i:=0;i<n;i++ {
|
||||
if obstacleGrid[0][i] == 1 {
|
||||
break
|
||||
}
|
||||
dp[0][i]=1
|
||||
for i := 0; i < n && obstacleGrid[0][i] == 0; i++ {
|
||||
dp[0][i] = 1
|
||||
}
|
||||
// dp数组推导过程
|
||||
for i:=1;i<m;i++ {
|
||||
for j:=1;j<n;j++ {
|
||||
// 如果obstacleGrid[i][j]这个点是障碍物, 那么我们的dp[i][j]保持为0
|
||||
if obstacleGrid[i][j] != 1 {
|
||||
for i := 1; i < m; i++ {
|
||||
for j := 1; j < n; j++ {
|
||||
// 如果obstacleGrid[i][j]这个点是障碍物, 那么dp[i][j]保持为0
|
||||
if obstacleGrid[i][j] != 1 {
|
||||
// 否则我们需要计算当前点可以到达的路径数
|
||||
dp[i][j] = dp[i-1][j]+dp[i][j-1]
|
||||
dp[i][j] = dp[i-1][j] + dp[i][j-1]
|
||||
}
|
||||
}
|
||||
}
|
||||
// debug遍历dp
|
||||
//for i,_ := range dp {
|
||||
// for j,_ := range dp[i] {
|
||||
// fmt.Printf("%.2v,",dp[i][j])
|
||||
// }
|
||||
// fmt.Println()
|
||||
//}
|
||||
return dp[m-1][n-1]
|
||||
}
|
||||
|
||||
|
||||
```
|
||||
|
||||
### Javascript
|
||||
@ -332,6 +319,60 @@ var uniquePathsWithObstacles = function(obstacleGrid) {
|
||||
};
|
||||
```
|
||||
|
||||
C
|
||||
```c
|
||||
//初始化dp数组
|
||||
int **initDP(int m, int n, int** obstacleGrid) {
|
||||
int **dp = (int**)malloc(sizeof(int*) * m);
|
||||
int i, j;
|
||||
//初始化每一行数组
|
||||
for(i = 0; i < m; ++i) {
|
||||
dp[i] = (int*)malloc(sizeof(int) * n);
|
||||
}
|
||||
|
||||
//先将第一行第一列设为0
|
||||
for(i = 0; i < m; ++i) {
|
||||
dp[i][0] = 0;
|
||||
}
|
||||
for(j = 0; j < n; ++j) {
|
||||
dp[0][j] = 0;
|
||||
}
|
||||
|
||||
//若碰到障碍,之后的都走不了。退出循环
|
||||
for(i = 0; i < m; ++i) {
|
||||
if(obstacleGrid[i][0]) {
|
||||
break;
|
||||
}
|
||||
dp[i][0] = 1;
|
||||
}
|
||||
for(j = 0; j < n; ++j) {
|
||||
if(obstacleGrid[0][j])
|
||||
break;
|
||||
dp[0][j] = 1;
|
||||
}
|
||||
return dp;
|
||||
}
|
||||
|
||||
int uniquePathsWithObstacles(int** obstacleGrid, int obstacleGridSize, int* obstacleGridColSize){
|
||||
int m = obstacleGridSize, n = *obstacleGridColSize;
|
||||
//初始化dp数组
|
||||
int **dp = initDP(m, n, obstacleGrid);
|
||||
|
||||
int i, j;
|
||||
for(i = 1; i < m; ++i) {
|
||||
for(j = 1; j < n; ++j) {
|
||||
//若当前i,j位置有障碍
|
||||
if(obstacleGrid[i][j])
|
||||
//路线不同
|
||||
dp[i][j] = 0;
|
||||
else
|
||||
dp[i][j] = dp[i-1][j] + dp[i][j-1];
|
||||
}
|
||||
}
|
||||
//返回最后终点的路径个数
|
||||
return dp[m-1][n-1];
|
||||
}
|
||||
```
|
||||
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
@ -296,6 +296,48 @@ var climbStairs = function(n) {
|
||||
};
|
||||
```
|
||||
|
||||
### C
|
||||
```c
|
||||
int climbStairs(int n){
|
||||
//若n<=2,返回n
|
||||
if(n <= 2)
|
||||
return n;
|
||||
//初始化dp数组,数组大小为n+1
|
||||
int *dp = (int *)malloc(sizeof(int) * (n + 1));
|
||||
dp[0] = 0, dp[1] = 1, dp[2] = 2;
|
||||
|
||||
//从前向后遍历数组,dp[i] = dp[i-1] + dp[i-2]
|
||||
int i;
|
||||
for(i = 3; i <= n; ++i) {
|
||||
dp[i] = dp[i - 1] + dp[i - 2];
|
||||
}
|
||||
//返回dp[n]
|
||||
return dp[n];
|
||||
}
|
||||
```
|
||||
|
||||
优化空间复杂度:
|
||||
```c
|
||||
int climbStairs(int n){
|
||||
//若n<=2,返回n
|
||||
if(n <= 2)
|
||||
return n;
|
||||
//初始化dp数组,数组大小为3
|
||||
int *dp = (int *)malloc(sizeof(int) * 3);
|
||||
dp[1] = 1, dp[2] = 2;
|
||||
|
||||
//只记录前面两个台阶的状态
|
||||
int i;
|
||||
for(i = 3; i <= n; ++i) {
|
||||
int sum = dp[1] + dp[2];
|
||||
dp[1] = dp[2];
|
||||
dp[2] = sum;
|
||||
}
|
||||
//返回dp[2]
|
||||
return dp[2];
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
@ -227,7 +227,34 @@ const numTrees =(n) => {
|
||||
};
|
||||
```
|
||||
|
||||
C:
|
||||
```c
|
||||
//开辟dp数组
|
||||
int *initDP(int n) {
|
||||
int *dp = (int *)malloc(sizeof(int) * (n + 1));
|
||||
int i;
|
||||
for(i = 0; i <= n; ++i)
|
||||
dp[i] = 0;
|
||||
return dp;
|
||||
}
|
||||
|
||||
int numTrees(int n){
|
||||
//开辟dp数组
|
||||
int *dp = initDP(n);
|
||||
//将dp[0]设为1
|
||||
dp[0] = 1;
|
||||
|
||||
int i, j;
|
||||
for(i = 1; i <= n; ++i) {
|
||||
for(j = 1; j <= i; ++j) {
|
||||
//递推公式:dp[i] = dp[i] + 根为j时左子树种类个数 * 根为j时右子树种类个数
|
||||
dp[i] += dp[j - 1] * dp[i - j];
|
||||
}
|
||||
}
|
||||
|
||||
return dp[n];
|
||||
}
|
||||
```
|
||||
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
@ -730,5 +730,33 @@ bool isBalanced(struct TreeNode* root){
|
||||
}
|
||||
```
|
||||
|
||||
## Swift:
|
||||
|
||||
>递归
|
||||
```swift
|
||||
func isBalanced(_ root: TreeNode?) -> Bool {
|
||||
// -1 已经不是平衡二叉树
|
||||
return getHeight(root) == -1 ? false : true
|
||||
}
|
||||
func getHeight(_ root: TreeNode?) -> Int {
|
||||
guard let root = root else {
|
||||
return 0
|
||||
}
|
||||
let leftHeight = getHeight(root.left)
|
||||
if leftHeight == -1 {
|
||||
return -1
|
||||
}
|
||||
let rightHeight = getHeight(root.right)
|
||||
if rightHeight == -1 {
|
||||
return -1
|
||||
}
|
||||
if abs(leftHeight - rightHeight) > 1 {
|
||||
return -1
|
||||
} else {
|
||||
return 1 + max(leftHeight, rightHeight)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
@ -766,7 +766,124 @@ let pathSum = function(root, targetSum) {
|
||||
};
|
||||
```
|
||||
|
||||
## Swift
|
||||
|
||||
0112.路径总和
|
||||
|
||||
**递归**
|
||||
```swift
|
||||
func hasPathSum(_ root: TreeNode?, _ targetSum: Int) -> Bool {
|
||||
guard let root = root else {
|
||||
return false
|
||||
}
|
||||
|
||||
return traversal(root, targetSum - root.val)
|
||||
}
|
||||
|
||||
func traversal(_ cur: TreeNode?, _ count: Int) -> Bool {
|
||||
if cur?.left == nil && cur?.right == nil && count == 0 {
|
||||
return true
|
||||
}
|
||||
|
||||
if cur?.left == nil && cur?.right == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
if let leftNode = cur?.left {
|
||||
if traversal(leftNode, count - leftNode.val) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
if let rightNode = cur?.right {
|
||||
if traversal(rightNode, count - rightNode.val) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
```
|
||||
**迭代**
|
||||
```swift
|
||||
func hasPathSum(_ root: TreeNode?, _ targetSum: Int) -> Bool {
|
||||
guard let root = root else {
|
||||
return false
|
||||
}
|
||||
|
||||
var stack = Array<(TreeNode, Int)>()
|
||||
stack.append((root, root.val))
|
||||
|
||||
while !stack.isEmpty {
|
||||
let node = stack.removeLast()
|
||||
|
||||
if node.0.left == nil && node.0.right == nil && targetSum == node.1 {
|
||||
return true
|
||||
}
|
||||
|
||||
if let rightNode = node.0.right {
|
||||
stack.append((rightNode, node.1 + rightNode.val))
|
||||
}
|
||||
|
||||
if let leftNode = node.0.left {
|
||||
stack.append((leftNode, node.1 + leftNode.val))
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
```
|
||||
|
||||
0113.路径总和 II
|
||||
|
||||
**递归**
|
||||
|
||||
```swift
|
||||
var result = [[Int]]()
|
||||
var path = [Int]()
|
||||
func pathSum(_ root: TreeNode?, _ targetSum: Int) -> [[Int]] {
|
||||
result.removeAll()
|
||||
path.removeAll()
|
||||
guard let root = root else {
|
||||
return result
|
||||
}
|
||||
path.append(root.val)
|
||||
traversal(root, count: targetSum - root.val)
|
||||
return result
|
||||
|
||||
}
|
||||
|
||||
func traversal(_ cur: TreeNode?, count: Int) {
|
||||
var count = count
|
||||
// 遇到了叶子节点且找到了和为targetSum的路径
|
||||
if cur?.left == nil && cur?.right == nil && count == 0 {
|
||||
result.append(path)
|
||||
return
|
||||
}
|
||||
|
||||
// 遇到叶子节点而没有找到合适的边,直接返回
|
||||
if cur?.left == nil && cur?.right == nil{
|
||||
return
|
||||
}
|
||||
|
||||
if let leftNode = cur?.left {
|
||||
path.append(leftNode.val)
|
||||
count -= leftNode.val
|
||||
traversal(leftNode, count: count)// 递归
|
||||
count += leftNode.val// 回溯
|
||||
path.removeLast()// 回溯
|
||||
}
|
||||
|
||||
if let rightNode = cur?.right {
|
||||
path.append(rightNode.val)
|
||||
count -= rightNode.val
|
||||
traversal(rightNode, count: count)// 递归
|
||||
count += rightNode.val// 回溯
|
||||
path.removeLast()// 回溯
|
||||
}
|
||||
return
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
@ -289,7 +289,33 @@ var sumNumbers = function(root) {
|
||||
};
|
||||
```
|
||||
|
||||
C:
|
||||
```c
|
||||
//sum记录总和
|
||||
int sum;
|
||||
void traverse(struct TreeNode *node, int val) {
|
||||
//更新val为根节点到当前节点的和
|
||||
val = val * 10 + node->val;
|
||||
//若当前节点为叶子节点,记录val
|
||||
if(!node->left && !node->right) {
|
||||
sum+=val;
|
||||
return;
|
||||
}
|
||||
//若有左/右节点,遍历左/右节点
|
||||
if(node->left)
|
||||
traverse(node->left, val);
|
||||
if(node->right)
|
||||
traverse(node->right, val);
|
||||
}
|
||||
|
||||
int sumNumbers(struct TreeNode* root){
|
||||
sum = 0;
|
||||
|
||||
traverse(root, 0);
|
||||
|
||||
return sum;
|
||||
}
|
||||
```
|
||||
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
@ -294,7 +294,30 @@ var detectCycle = function(head) {
|
||||
};
|
||||
```
|
||||
|
||||
TypeScript:
|
||||
|
||||
```typescript
|
||||
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;
|
||||
fastNode = fastNode.next.next;
|
||||
if (slowNode === fastNode) {
|
||||
slowNode = head;
|
||||
while (slowNode !== fastNode) {
|
||||
slowNode = (slowNode as ListNode).next;
|
||||
fastNode = (fastNode as ListNode).next;
|
||||
}
|
||||
return slowNode;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
```
|
||||
|
||||
Swift:
|
||||
|
||||
```swift
|
||||
class Solution {
|
||||
func detectCycle(_ head: ListNode?) -> ListNode? {
|
||||
|
@ -439,7 +439,75 @@ var reorderList = function(head, s = [], tmp) {
|
||||
}
|
||||
```
|
||||
|
||||
### C
|
||||
方法三:反转链表
|
||||
```c
|
||||
//翻转链表
|
||||
struct ListNode *reverseList(struct ListNode *head) {
|
||||
if(!head)
|
||||
return NULL;
|
||||
struct ListNode *preNode = NULL, *curNode = head;
|
||||
while(curNode) {
|
||||
//创建tempNode记录curNode->next(即将被更新)
|
||||
struct ListNode* tempNode = curNode->next;
|
||||
//将curNode->next指向preNode
|
||||
curNode->next = preNode;
|
||||
//更新preNode为curNode
|
||||
preNode = curNode;
|
||||
//curNode更新为原链表中下一个元素
|
||||
curNode = tempNode;
|
||||
}
|
||||
return preNode;
|
||||
}
|
||||
|
||||
void reorderList(struct ListNode* head){
|
||||
//slow用来截取到链表的中间节点(第一个链表的最后节点),每次循环跳一个节点。fast用来辅助,每次循环跳两个节点
|
||||
struct ListNode *fast = head, *slow = head;
|
||||
while(fast && fast->next && fast->next->next) {
|
||||
//fast每次跳两个节点
|
||||
fast = fast->next->next;
|
||||
//slow每次跳一个节点
|
||||
slow = slow->next;
|
||||
}
|
||||
//将slow->next后的节点翻转
|
||||
struct ListNode *sndLst = reverseList(slow->next);
|
||||
//将第一个链表与第二个链表断开
|
||||
slow->next = NULL;
|
||||
//因为插入从curNode->next开始,curNode刚开始已经head。所以fstList要从head->next开始
|
||||
struct ListNode *fstLst = head->next;
|
||||
struct ListNode *curNode = head;
|
||||
|
||||
int count = 0;
|
||||
//当第一个链表和第二个链表中都有节点时循环
|
||||
while(sndLst && fstLst) {
|
||||
//count为奇数,插入fstLst中的节点
|
||||
if(count % 2) {
|
||||
curNode->next = fstLst;
|
||||
fstLst = fstLst->next;
|
||||
}
|
||||
//count为偶数,插入sndList的节点
|
||||
else {
|
||||
curNode->next = sndLst;
|
||||
sndLst = sndLst->next;
|
||||
}
|
||||
//设置下一个节点
|
||||
curNode = curNode->next;
|
||||
//更新count
|
||||
++count;
|
||||
}
|
||||
|
||||
//若两个链表fstList和sndLst中还有节点,将其放入链表
|
||||
if(fstLst) {
|
||||
curNode->next = fstLst;
|
||||
}
|
||||
if(sndLst) {
|
||||
curNode->next = sndLst;
|
||||
}
|
||||
|
||||
//返回链表
|
||||
return head;
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
-----------------------
|
||||
|
@ -210,6 +210,71 @@ var evalRPN = function(tokens) {
|
||||
};
|
||||
```
|
||||
|
||||
TypeScript:
|
||||
|
||||
普通版:
|
||||
|
||||
```typescript
|
||||
function evalRPN(tokens: string[]): number {
|
||||
let helperStack: number[] = [];
|
||||
let temp: number;
|
||||
let i: number = 0;
|
||||
while (i < tokens.length) {
|
||||
let t: string = tokens[i];
|
||||
switch (t) {
|
||||
case '+':
|
||||
temp = helperStack.pop()! + helperStack.pop()!;
|
||||
helperStack.push(temp);
|
||||
break;
|
||||
case '-':
|
||||
temp = helperStack.pop()!;
|
||||
temp = helperStack.pop()! - temp;
|
||||
helperStack.push(temp);
|
||||
break;
|
||||
case '*':
|
||||
temp = helperStack.pop()! * helperStack.pop()!;
|
||||
helperStack.push(temp);
|
||||
break;
|
||||
case '/':
|
||||
temp = helperStack.pop()!;
|
||||
temp = Math.trunc(helperStack.pop()! / temp);
|
||||
helperStack.push(temp);
|
||||
break;
|
||||
default:
|
||||
helperStack.push(Number(t));
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return helperStack.pop()!;
|
||||
};
|
||||
```
|
||||
|
||||
优化版:
|
||||
|
||||
```typescript
|
||||
function evalRPN(tokens: string[]): number {
|
||||
const helperStack: number[] = [];
|
||||
const operatorMap: Map<string, (a: number, b: number) => number> = new Map([
|
||||
['+', (a, b) => a + b],
|
||||
['-', (a, b) => a - b],
|
||||
['/', (a, b) => Math.trunc(a / b)],
|
||||
['*', (a, b) => a * b],
|
||||
]);
|
||||
let a: number, b: number;
|
||||
for (let t of tokens) {
|
||||
if (operatorMap.has(t)) {
|
||||
b = helperStack.pop()!;
|
||||
a = helperStack.pop()!;
|
||||
helperStack.push(operatorMap.get(t)!(a, b));
|
||||
} else {
|
||||
helperStack.push(Number(t));
|
||||
}
|
||||
}
|
||||
return helperStack.pop()!;
|
||||
};
|
||||
```
|
||||
|
||||
python3
|
||||
|
||||
```python
|
||||
|
@ -553,6 +553,65 @@ function reverse(strArr, start, end) {
|
||||
}
|
||||
```
|
||||
|
||||
TypeScript:
|
||||
|
||||
```typescript
|
||||
function reverseWords(s: string): string {
|
||||
/** Utils **/
|
||||
// 删除多余空格, 如' hello world ' => 'hello world'
|
||||
function delExtraSpace(arr: string[]): void {
|
||||
let left: number = 0,
|
||||
right: number = 0,
|
||||
length: number = arr.length;
|
||||
while (right < length && arr[right] === ' ') {
|
||||
right++;
|
||||
}
|
||||
while (right < length) {
|
||||
if (arr[right] === ' ' && arr[right - 1] === ' ') {
|
||||
right++;
|
||||
continue;
|
||||
}
|
||||
arr[left++] = arr[right++];
|
||||
}
|
||||
if (arr[left - 1] === ' ') {
|
||||
arr.length = left - 1;
|
||||
} else {
|
||||
arr.length = left;
|
||||
}
|
||||
}
|
||||
// 翻转字符串,如:'hello' => 'olleh'
|
||||
function reverseWords(strArr: string[], start: number, end: number) {
|
||||
let temp: string;
|
||||
while (start < end) {
|
||||
temp = strArr[start];
|
||||
strArr[start] = strArr[end];
|
||||
strArr[end] = temp;
|
||||
start++;
|
||||
end--;
|
||||
}
|
||||
}
|
||||
|
||||
/** Main code **/
|
||||
let strArr: string[] = s.split('');
|
||||
delExtraSpace(strArr);
|
||||
let length: number = strArr.length;
|
||||
// 翻转整个字符串
|
||||
reverseWords(strArr, 0, length - 1);
|
||||
let start: number = 0,
|
||||
end: number = 0;
|
||||
while (start < length) {
|
||||
end = start;
|
||||
while (strArr[end] !== ' ' && end < length) {
|
||||
end++;
|
||||
}
|
||||
// 翻转单个单词
|
||||
reverseWords(strArr, start, end - 1);
|
||||
start = end + 1;
|
||||
}
|
||||
return strArr.join('');
|
||||
};
|
||||
```
|
||||
|
||||
Swift:
|
||||
|
||||
```swift
|
||||
|
@ -232,7 +232,27 @@ var isHappy = function(n) {
|
||||
};
|
||||
```
|
||||
|
||||
TypeScript:
|
||||
|
||||
```typescript
|
||||
function isHappy(n: number): boolean {
|
||||
// Utils
|
||||
// 计算val各位的平方和
|
||||
function calcSum(val: number): number {
|
||||
return String(val).split("").reduce((pre, cur) => (pre + Number(cur) * Number(cur)), 0);
|
||||
}
|
||||
|
||||
let storeSet: Set<number> = new Set();
|
||||
while (n !== 1 && !storeSet.has(n)) {
|
||||
storeSet.add(n);
|
||||
n = calcSum(n);
|
||||
}
|
||||
return n === 1;
|
||||
};
|
||||
```
|
||||
|
||||
Swift:
|
||||
|
||||
```swift
|
||||
// number 每个位置上的数字的平方和
|
||||
func getSum(_ number: Int) -> Int {
|
||||
|
@ -330,5 +330,55 @@ def min_sub_array_len(target, nums)
|
||||
end
|
||||
```
|
||||
|
||||
C:
|
||||
暴力解法:
|
||||
```c
|
||||
int minSubArrayLen(int target, int* nums, int numsSize){
|
||||
//初始化最小长度为INT_MAX
|
||||
int minLength = INT_MAX;
|
||||
int sum;
|
||||
|
||||
int left, right;
|
||||
for(left = 0; left < numsSize; ++left) {
|
||||
//每次遍历都清零sum,计算当前位置后和>=target的子数组的长度
|
||||
sum = 0;
|
||||
//从left开始,sum中添加元素
|
||||
for(right = left; right < numsSize; ++right) {
|
||||
sum += nums[right];
|
||||
//若加入当前元素后,和大于target,则更新minLength
|
||||
if(sum >= target) {
|
||||
int subLength = right - left + 1;
|
||||
minLength = minLength < subLength ? minLength : subLength;
|
||||
}
|
||||
}
|
||||
}
|
||||
//若minLength不为INT_MAX,则返回minLnegth
|
||||
return minLength == INT_MAX ? 0 : minLength;
|
||||
}
|
||||
```
|
||||
|
||||
滑动窗口:
|
||||
```c
|
||||
int minSubArrayLen(int target, int* nums, int numsSize){
|
||||
//初始化最小长度为INT_MAX
|
||||
int minLength = INT_MAX;
|
||||
int sum = 0;
|
||||
|
||||
int left = 0, right = 0;
|
||||
//右边界向右扩展
|
||||
for(; right < numsSize; ++right) {
|
||||
sum += nums[right];
|
||||
//当sum的值大于等于target时,保存长度,并且收缩左边界
|
||||
while(sum >= target) {
|
||||
int subLength = right - left + 1;
|
||||
minLength = minLength < subLength ? minLength : subLength;
|
||||
sum -= nums[left++];
|
||||
}
|
||||
}
|
||||
//若minLength不为INT_MAX,则返回minLnegth
|
||||
return minLength == INT_MAX ? 0 : minLength;
|
||||
}
|
||||
```
|
||||
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
@ -46,7 +46,7 @@
|
||||
|
||||
模拟的队列执行语句如下:
|
||||
|
||||
```
|
||||
```cpp
|
||||
queue.push(1);
|
||||
queue.push(2);
|
||||
queue.pop(); // 注意弹出的操作
|
||||
@ -598,7 +598,80 @@ MyStack.prototype.empty = function() {
|
||||
|
||||
```
|
||||
|
||||
TypeScript:
|
||||
|
||||
版本一:使用两个队列模拟栈
|
||||
|
||||
```typescript
|
||||
class MyStack {
|
||||
private queue: number[];
|
||||
private tempQueue: number[];
|
||||
constructor() {
|
||||
this.queue = [];
|
||||
this.tempQueue = [];
|
||||
}
|
||||
|
||||
push(x: number): void {
|
||||
this.queue.push(x);
|
||||
}
|
||||
|
||||
pop(): number {
|
||||
for (let i = 0, length = this.queue.length - 1; i < length; i++) {
|
||||
this.tempQueue.push(this.queue.shift()!);
|
||||
}
|
||||
let res: number = this.queue.pop()!;
|
||||
let temp: number[] = this.queue;
|
||||
this.queue = this.tempQueue;
|
||||
this.tempQueue = temp;
|
||||
return res;
|
||||
}
|
||||
|
||||
top(): number {
|
||||
let res: number = this.pop();
|
||||
this.push(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
empty(): boolean {
|
||||
return this.queue.length === 0;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
版本二:使用一个队列模拟栈
|
||||
|
||||
```typescript
|
||||
class MyStack {
|
||||
private queue: number[];
|
||||
constructor() {
|
||||
this.queue = [];
|
||||
}
|
||||
|
||||
push(x: number): void {
|
||||
this.queue.push(x);
|
||||
}
|
||||
|
||||
pop(): number {
|
||||
for (let i = 0, length = this.queue.length - 1; i < length; i++) {
|
||||
this.queue.push(this.queue.shift()!);
|
||||
}
|
||||
return this.queue.shift()!;
|
||||
}
|
||||
|
||||
top(): number {
|
||||
let res: number = this.pop();
|
||||
this.push(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
empty(): boolean {
|
||||
return this.queue.length === 0;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Swift
|
||||
|
||||
```Swift
|
||||
// 定义一个队列数据结构
|
||||
class Queue {
|
||||
|
@ -21,7 +21,7 @@ empty() -- 返回队列是否为空。
|
||||
|
||||
示例:
|
||||
|
||||
```
|
||||
```cpp
|
||||
MyQueue queue = new MyQueue();
|
||||
queue.push(1);
|
||||
queue.push(2);
|
||||
@ -348,7 +348,44 @@ MyQueue.prototype.empty = function() {
|
||||
};
|
||||
```
|
||||
|
||||
TypeScript:
|
||||
|
||||
```typescript
|
||||
class MyQueue {
|
||||
private stackIn: number[]
|
||||
private stackOut: number[]
|
||||
constructor() {
|
||||
this.stackIn = [];
|
||||
this.stackOut = [];
|
||||
}
|
||||
|
||||
push(x: number): void {
|
||||
this.stackIn.push(x);
|
||||
}
|
||||
|
||||
pop(): number {
|
||||
if (this.stackOut.length === 0) {
|
||||
while (this.stackIn.length > 0) {
|
||||
this.stackOut.push(this.stackIn.pop()!);
|
||||
}
|
||||
}
|
||||
return this.stackOut.pop()!;
|
||||
}
|
||||
|
||||
peek(): number {
|
||||
let temp: number = this.pop();
|
||||
this.stackOut.push(temp);
|
||||
return temp;
|
||||
}
|
||||
|
||||
empty(): boolean {
|
||||
return this.stackIn.length === 0 && this.stackOut.length === 0;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Swift:
|
||||
|
||||
```swift
|
||||
class MyQueue {
|
||||
|
||||
|
@ -395,30 +395,102 @@ func maxSlidingWindow(nums []int, k int) []int {
|
||||
|
||||
Javascript:
|
||||
```javascript
|
||||
/**
|
||||
* @param {number[]} nums
|
||||
* @param {number} k
|
||||
* @return {number[]}
|
||||
*/
|
||||
var maxSlidingWindow = function (nums, k) {
|
||||
// 队列数组(存放的是元素下标,为了取值方便)
|
||||
const q = [];
|
||||
// 结果数组
|
||||
const ans = [];
|
||||
for (let i = 0; i < nums.length; i++) {
|
||||
// 若队列不为空,且当前元素大于等于队尾所存下标的元素,则弹出队尾
|
||||
while (q.length && nums[i] >= nums[q[q.length - 1]]) {
|
||||
q.pop();
|
||||
class MonoQueue {
|
||||
queue;
|
||||
constructor() {
|
||||
this.queue = [];
|
||||
}
|
||||
enqueue(value) {
|
||||
let back = this.queue[this.queue.length - 1];
|
||||
while (back !== undefined && back < value) {
|
||||
this.queue.pop();
|
||||
back = this.queue[this.queue.length - 1];
|
||||
}
|
||||
this.queue.push(value);
|
||||
}
|
||||
dequeue(value) {
|
||||
let front = this.front();
|
||||
if (front === value) {
|
||||
this.queue.shift();
|
||||
}
|
||||
}
|
||||
front() {
|
||||
return this.queue[0];
|
||||
}
|
||||
}
|
||||
// 入队当前元素下标
|
||||
q.push(i);
|
||||
// 判断当前最大值(即队首元素)是否在窗口中,若不在便将其出队
|
||||
if (q[0] <= i - k) {
|
||||
q.shift();
|
||||
let helperQueue = new MonoQueue();
|
||||
let i = 0, j = 0;
|
||||
let resArr = [];
|
||||
while (j < k) {
|
||||
helperQueue.enqueue(nums[j++]);
|
||||
}
|
||||
// 当达到窗口大小时便开始向结果中添加数据
|
||||
if (i >= k - 1) ans.push(nums[q[0]]);
|
||||
}
|
||||
return ans;
|
||||
resArr.push(helperQueue.front());
|
||||
while (j < nums.length) {
|
||||
helperQueue.enqueue(nums[j]);
|
||||
helperQueue.dequeue(nums[i]);
|
||||
resArr.push(helperQueue.front());
|
||||
i++, j++;
|
||||
}
|
||||
return resArr;
|
||||
};
|
||||
```
|
||||
|
||||
TypeScript:
|
||||
|
||||
```typescript
|
||||
function maxSlidingWindow(nums: number[], k: number): number[] {
|
||||
/** 单调递减队列 */
|
||||
class MonoQueue {
|
||||
private queue: number[];
|
||||
constructor() {
|
||||
this.queue = [];
|
||||
};
|
||||
/** 入队:value如果大于队尾元素,则将队尾元素删除,直至队尾元素大于value,或者队列为空 */
|
||||
public enqueue(value: number): void {
|
||||
let back: number | undefined = this.queue[this.queue.length - 1];
|
||||
while (back !== undefined && back < value) {
|
||||
this.queue.pop();
|
||||
back = this.queue[this.queue.length - 1];
|
||||
}
|
||||
this.queue.push(value);
|
||||
};
|
||||
/** 出队:只有当队头元素等于value,才出队 */
|
||||
public dequeue(value: number): void {
|
||||
let top: number | undefined = this.top();
|
||||
if (top !== undefined && top === value) {
|
||||
this.queue.shift();
|
||||
}
|
||||
}
|
||||
public top(): number | undefined {
|
||||
return this.queue[0];
|
||||
}
|
||||
}
|
||||
const helperQueue: MonoQueue = new MonoQueue();
|
||||
let i: number = 0,
|
||||
j: number = 0;
|
||||
let resArr: number[] = [];
|
||||
while (j < k) {
|
||||
helperQueue.enqueue(nums[j++]);
|
||||
}
|
||||
resArr.push(helperQueue.top()!);
|
||||
while (j < nums.length) {
|
||||
helperQueue.enqueue(nums[j]);
|
||||
helperQueue.dequeue(nums[i]);
|
||||
resArr.push(helperQueue.top()!);
|
||||
j++, i++;
|
||||
}
|
||||
return resArr;
|
||||
};
|
||||
```
|
||||
|
||||
Swift:
|
||||
|
||||
```Swift
|
||||
/// 双向链表
|
||||
class DoublyListNode {
|
||||
|
@ -214,7 +214,23 @@ var isAnagram = function(s, t) {
|
||||
};
|
||||
```
|
||||
|
||||
TypeScript:
|
||||
|
||||
```typescript
|
||||
function isAnagram(s: string, t: string): boolean {
|
||||
if (s.length !== t.length) return false;
|
||||
let helperArr: number[] = new Array(26).fill(0);
|
||||
let pivot: number = 'a'.charCodeAt(0);
|
||||
for (let i = 0, length = s.length; i < length; i++) {
|
||||
helperArr[s.charCodeAt(i) - pivot]++;
|
||||
helperArr[t.charCodeAt(i) - pivot]--;
|
||||
}
|
||||
return helperArr.every(i => i === 0);
|
||||
};
|
||||
```
|
||||
|
||||
Swift:
|
||||
|
||||
```Swift
|
||||
func isAnagram(_ s: String, _ t: String) -> Bool {
|
||||
if s.count != t.count {
|
||||
|
@ -581,7 +581,71 @@ var binaryTreePaths = function(root) {
|
||||
};
|
||||
```
|
||||
|
||||
Swift:
|
||||
> 递归/回溯
|
||||
```swift
|
||||
func binaryTreePaths(_ root: TreeNode?) -> [String] {
|
||||
var res = [String]()
|
||||
guard let root = root else {
|
||||
return res
|
||||
}
|
||||
var path = [Int]()
|
||||
_binaryTreePaths(root, path: &path, res: &res)
|
||||
return res
|
||||
}
|
||||
func _binaryTreePaths(_ root: TreeNode, path: inout [Int], res: inout [String]) {
|
||||
path.append(root.val)
|
||||
if root.left == nil && root.right == nil {
|
||||
var str = ""
|
||||
for i in 0 ..< path.count - 1 {
|
||||
str.append("\(path[i])->")
|
||||
}
|
||||
str.append("\(path.last!)")
|
||||
res.append(str)
|
||||
return
|
||||
}
|
||||
if let left = root.left {
|
||||
_binaryTreePaths(left, path: &path, res: &res)
|
||||
path.removeLast()
|
||||
}
|
||||
if let right = root.right {
|
||||
_binaryTreePaths(right, path: &path, res: &res)
|
||||
path.removeLast()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
> 迭代
|
||||
```swift
|
||||
func binaryTreePaths(_ root: TreeNode?) -> [String] {
|
||||
var res = [String]()
|
||||
guard let root = root else {
|
||||
return res
|
||||
}
|
||||
var stackNode = [TreeNode]()
|
||||
stackNode.append(root)
|
||||
|
||||
var stackStr = [String]()
|
||||
stackStr.append("\(root.val)")
|
||||
|
||||
while !stackNode.isEmpty {
|
||||
let node = stackNode.popLast()!
|
||||
let str = stackStr.popLast()!
|
||||
if node.left == nil && node.right == nil {
|
||||
res.append(str)
|
||||
}
|
||||
if let left = node.left {
|
||||
stackNode.append(left)
|
||||
stackStr.append("\(str)->\(left.val)")
|
||||
}
|
||||
if let right = node.right {
|
||||
stackNode.append(right)
|
||||
stackStr.append("\(str)->\(right.val)")
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
```
|
||||
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
@ -89,9 +89,33 @@ Python:
|
||||
for i in range(slow, len(nums)):
|
||||
nums[i] = 0
|
||||
```
|
||||
交换前后变量,避免补零
|
||||
```python
|
||||
def moveZeroes(self, nums: List[int]) -> None:
|
||||
slow, fast = 0, 0
|
||||
while fast < len(nums):
|
||||
if nums[fast] != 0:
|
||||
nums[slow], nums[fast] = nums[fast], nums[slow]
|
||||
slow += 1 # 保持[0, slow)区间是没有0的
|
||||
fast += 1
|
||||
```
|
||||
|
||||
Go:
|
||||
|
||||
```go
|
||||
func moveZeroes(nums []int) {
|
||||
slow := 0
|
||||
for fast := 0; fast < len(nums); fast ++ {
|
||||
if nums[fast] != 0 {
|
||||
temp := nums[slow]
|
||||
nums[slow] = nums[fast]
|
||||
nums[fast] = temp
|
||||
slow++
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
JavaScript:
|
||||
```javascript
|
||||
var moveZeroes = function(nums) {
|
||||
|
@ -271,5 +271,40 @@ var integerBreak = function(n) {
|
||||
};
|
||||
```
|
||||
|
||||
C:
|
||||
```c
|
||||
//初始化DP数组
|
||||
int *initDP(int num) {
|
||||
int* dp = (int*)malloc(sizeof(int) * (num + 1));
|
||||
int i;
|
||||
for(i = 0; i < num + 1; ++i) {
|
||||
dp[i] = 0;
|
||||
}
|
||||
return dp;
|
||||
}
|
||||
|
||||
//取三数最大值
|
||||
int max(int num1, int num2, int num3) {
|
||||
int tempMax = num1 > num2 ? num1 : num2;
|
||||
return tempMax > num3 ? tempMax : num3;
|
||||
}
|
||||
|
||||
int integerBreak(int n){
|
||||
int *dp = initDP(n);
|
||||
//初始化dp[2]为1
|
||||
dp[2] = 1;
|
||||
|
||||
int i;
|
||||
for(i = 3; i <= n; ++i) {
|
||||
int j;
|
||||
for(j = 1; j < i - 1; ++j) {
|
||||
//取得上次循环:dp[i],原数相乘,或j*dp[]i-j] 三数中的最大值
|
||||
dp[i] = max(dp[i], j * (i - j), j * dp[i - j]);
|
||||
}
|
||||
}
|
||||
return dp[n];
|
||||
}
|
||||
```
|
||||
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
@ -200,6 +200,27 @@ var reverseString = function(s) {
|
||||
};
|
||||
```
|
||||
|
||||
TypeScript:
|
||||
|
||||
```typescript
|
||||
/**
|
||||
Do not return anything, modify s in-place instead.
|
||||
*/
|
||||
function reverseString(s: string[]): void {
|
||||
let length: number = s.length;
|
||||
let left: number = 0,
|
||||
right: number = length - 1;
|
||||
let tempStr: string;
|
||||
while (left < right) {
|
||||
tempStr = s[left];
|
||||
s[left] = s[right];
|
||||
s[right] = tempStr;
|
||||
left++;
|
||||
right--;
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
Swift:
|
||||
|
||||
```swift
|
||||
@ -232,6 +253,19 @@ void reverseString(char* s, int sSize){
|
||||
}
|
||||
```
|
||||
|
||||
C#:
|
||||
```csharp
|
||||
public class Solution
|
||||
{
|
||||
public void ReverseString(char[] s)
|
||||
{
|
||||
for (int i = 0, j = s.Length - 1; i < j; i++, j--)
|
||||
{
|
||||
(s[i], s[j]) = (s[j], s[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
@ -142,7 +142,7 @@ class Solution {
|
||||
|
||||
Set<Map.Entry<Integer, Integer>> entries = map.entrySet();
|
||||
// 根据map的value值正序排,相当于一个小顶堆
|
||||
PriorityQueue<Map.Entry<Integer, Integer>> queue = new PriorityQueue<>((o1, o2) -> o2.getValue() - o1.getValue());
|
||||
PriorityQueue<Map.Entry<Integer, Integer>> queue = new PriorityQueue<>((o1, o2) -> o1.getValue() - o2.getValue());
|
||||
for (Map.Entry<Integer, Integer> entry : entries) {
|
||||
queue.offer(entry);
|
||||
if (queue.size() > k) {
|
||||
|
@ -190,7 +190,33 @@ var intersection = function(nums1, nums2) {
|
||||
};
|
||||
```
|
||||
|
||||
TypeScript:
|
||||
|
||||
版本一(正常解法):
|
||||
|
||||
```typescript
|
||||
function intersection(nums1: number[], nums2: number[]): number[] {
|
||||
let resSet: Set<number> = new Set(),
|
||||
nums1Set: Set<number> = new Set(nums1);
|
||||
for (let i of nums2) {
|
||||
if (nums1Set.has(i)) {
|
||||
resSet.add(i);
|
||||
}
|
||||
}
|
||||
return Array.from(resSet);
|
||||
};
|
||||
```
|
||||
|
||||
版本二(秀操作):
|
||||
|
||||
```typescript
|
||||
function intersection(nums1: number[], nums2: number[]): number[] {
|
||||
return Array.from(new Set(nums1.filter(i => nums2.includes(i))))
|
||||
};
|
||||
```
|
||||
|
||||
Swift:
|
||||
|
||||
```swift
|
||||
func intersection(_ nums1: [Int], _ nums2: [Int]) -> [Int] {
|
||||
var set1 = Set<Int>()
|
||||
|
@ -264,6 +264,27 @@ var canConstruct = function(ransomNote, magazine) {
|
||||
};
|
||||
```
|
||||
|
||||
TypeScript:
|
||||
|
||||
```typescript
|
||||
function canConstruct(ransomNote: string, magazine: string): boolean {
|
||||
let helperArr: number[] = new Array(26).fill(0);
|
||||
let base: number = 'a'.charCodeAt(0);
|
||||
let index: number;
|
||||
for (let i = 0, length = magazine.length; i < length; i++) {
|
||||
helperArr[magazine[i].charCodeAt(0) - base]++;
|
||||
}
|
||||
for (let i = 0, length = ransomNote.length; i < length; i++) {
|
||||
index = ransomNote[i].charCodeAt(0) - base;
|
||||
helperArr[index]--;
|
||||
if (helperArr[index] < 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
PHP:
|
||||
```php
|
||||
|
@ -373,6 +373,54 @@ var sumOfLeftLeaves = function(root) {
|
||||
```
|
||||
|
||||
|
||||
## Swift
|
||||
|
||||
**递归法**
|
||||
```swift
|
||||
func sumOfLeftLeaves(_ root: TreeNode?) -> Int {
|
||||
guard let root = root else {
|
||||
return 0
|
||||
}
|
||||
|
||||
let leftValue = sumOfLeftLeaves(root.left)
|
||||
let rightValue = sumOfLeftLeaves(root.right)
|
||||
|
||||
var midValue: Int = 0
|
||||
if root.left != nil && root.left?.left == nil && root.left?.right == nil {
|
||||
midValue = root.left!.val
|
||||
}
|
||||
|
||||
let sum = midValue + leftValue + rightValue
|
||||
return sum
|
||||
}
|
||||
```
|
||||
**迭代法**
|
||||
```swift
|
||||
func sumOfLeftLeaves(_ root: TreeNode?) -> Int {
|
||||
guard let root = root else {
|
||||
return 0
|
||||
}
|
||||
|
||||
var stack = Array<TreeNode>()
|
||||
stack.append(root)
|
||||
var sum = 0
|
||||
|
||||
while !stack.isEmpty {
|
||||
let lastNode = stack.removeLast()
|
||||
|
||||
if lastNode.left != nil && lastNode.left?.left == nil && lastNode.left?.right == nil {
|
||||
sum += lastNode.left!.val
|
||||
}
|
||||
if let right = lastNode.right {
|
||||
stack.append(right)
|
||||
}
|
||||
if let left = lastNode.left {
|
||||
stack.append(left)
|
||||
}
|
||||
}
|
||||
return sum
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
@ -183,28 +183,22 @@ public:
|
||||
```java
|
||||
class Solution {
|
||||
public int eraseOverlapIntervals(int[][] intervals) {
|
||||
if (intervals.length < 2) return 0;
|
||||
|
||||
Arrays.sort(intervals, new Comparator<int[]>() {
|
||||
@Override
|
||||
public int compare(int[] o1, int[] o2) {
|
||||
if (o1[1] != o2[1]) {
|
||||
return Integer.compare(o1[1],o2[1]);
|
||||
} else {
|
||||
return Integer.compare(o1[0],o2[0]);
|
||||
}
|
||||
}
|
||||
Arrays.sort(intervals, (a, b) -> {
|
||||
if (a[0] == a[0]) return a[1] - b[1];
|
||||
return a[0] - b[0];
|
||||
});
|
||||
|
||||
int count = 1;
|
||||
int edge = intervals[0][1];
|
||||
for (int i = 1; i < intervals.length; i++) {
|
||||
if (edge <= intervals[i][0]){
|
||||
count ++; //non overlap + 1
|
||||
int count = 0;
|
||||
int edge = Integer.MIN_VALUE;
|
||||
for (int i = 0; i < intervals.length; i++) {
|
||||
if (edge <= intervals[i][0]) {
|
||||
edge = intervals[i][1];
|
||||
} else {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return intervals.length - count;
|
||||
|
||||
return count;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
@ -239,5 +239,30 @@ int findMinArrowShots(int** points, int pointsSize, int* pointsColSize){
|
||||
}
|
||||
```
|
||||
|
||||
### Rust
|
||||
```Rust
|
||||
use std::cmp;
|
||||
impl Solution {
|
||||
pub fn find_min_arrow_shots(mut points: Vec<Vec<i32>>) -> i32 {
|
||||
if points.is_empty() {
|
||||
return 0;
|
||||
}
|
||||
points.sort_by_key(|point| point[0]);
|
||||
|
||||
let size = points.len();
|
||||
let mut count = 1;
|
||||
|
||||
for i in 1..size {
|
||||
if points[i][0] > points[i-1][1] {
|
||||
count += 1;
|
||||
} else {
|
||||
points[i][1] = cmp::min(points[i][1], points[i-1][1]);
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
}
|
||||
```
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
@ -192,8 +192,33 @@ var fourSumCount = function(nums1, nums2, nums3, nums4) {
|
||||
};
|
||||
```
|
||||
|
||||
TypeScript:
|
||||
|
||||
```typescript
|
||||
function fourSumCount(nums1: number[], nums2: number[], nums3: number[], nums4: number[]): number {
|
||||
let helperMap: Map<number, number> = new Map();
|
||||
let resNum: number = 0;
|
||||
let tempVal: number | undefined;
|
||||
for (let i of nums1) {
|
||||
for (let j of nums2) {
|
||||
tempVal = helperMap.get(i + j);
|
||||
helperMap.set(i + j, tempVal ? tempVal + 1 : 1);
|
||||
}
|
||||
}
|
||||
for (let k of nums3) {
|
||||
for (let l of nums4) {
|
||||
tempVal = helperMap.get(0 - (k + l));
|
||||
if (tempVal) {
|
||||
resNum += tempVal;
|
||||
}
|
||||
}
|
||||
}
|
||||
return resNum;
|
||||
};
|
||||
```
|
||||
|
||||
PHP:
|
||||
|
||||
```php
|
||||
class Solution {
|
||||
/**
|
||||
|
@ -361,7 +361,65 @@ var repeatedSubstringPattern = function (s) {
|
||||
};
|
||||
```
|
||||
|
||||
TypeScript:
|
||||
|
||||
> 前缀表统一减一
|
||||
|
||||
```typescript
|
||||
function repeatedSubstringPattern(s: string): boolean {
|
||||
function getNext(str: string): number[] {
|
||||
let next: number[] = [];
|
||||
let j: number = -1;
|
||||
next[0] = j;
|
||||
for (let i = 1, length = str.length; i < length; i++) {
|
||||
while (j >= 0 && str[i] !== str[j + 1]) {
|
||||
j = next[j];
|
||||
}
|
||||
if (str[i] === str[j + 1]) {
|
||||
j++;
|
||||
}
|
||||
next[i] = j;
|
||||
}
|
||||
return next;
|
||||
}
|
||||
|
||||
let next: number[] = getNext(s);
|
||||
let sLength: number = s.length;
|
||||
let nextLength: number = next.length;
|
||||
let suffixLength: number = next[nextLength - 1] + 1;
|
||||
if (suffixLength > 0 && sLength % (sLength - suffixLength) === 0) return true;
|
||||
return false;
|
||||
};
|
||||
```
|
||||
|
||||
> 前缀表不减一
|
||||
|
||||
```typescript
|
||||
function repeatedSubstringPattern(s: string): boolean {
|
||||
function getNext(str: string): number[] {
|
||||
let next: number[] = [];
|
||||
let j: number = 0;
|
||||
next[0] = j;
|
||||
for (let i = 1, length = str.length; i < length; i++) {
|
||||
while (j > 0 && str[i] !== str[j]) {
|
||||
j = next[j - 1];
|
||||
}
|
||||
if (str[i] === str[j]) {
|
||||
j++;
|
||||
}
|
||||
next[i] = j;
|
||||
}
|
||||
return next;
|
||||
}
|
||||
|
||||
let next: number[] = getNext(s);
|
||||
let sLength: number = s.length;
|
||||
let nextLength: number = next.length;
|
||||
let suffixLength: number = next[nextLength - 1];
|
||||
if (suffixLength > 0 && sLength % (sLength - suffixLength) === 0) return true;
|
||||
return false;
|
||||
};
|
||||
```
|
||||
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
@ -289,7 +289,7 @@ func findTargetSumWays(nums []int, target int) int {
|
||||
for _, v := range nums {
|
||||
sum += v
|
||||
}
|
||||
if target > sum {
|
||||
if abs(target) > sum {
|
||||
return 0
|
||||
}
|
||||
if (sum+target)%2 == 1 {
|
||||
@ -311,49 +311,12 @@ func findTargetSumWays(nums []int, target int) int {
|
||||
}
|
||||
return dp[bag]
|
||||
}
|
||||
```
|
||||
> 更新版,上一个跑不通了,因为会存在bag 小于0的情况
|
||||
|
||||
```go
|
||||
func findTargetSumWays(nums []int, target int) int {
|
||||
//先转化为数学问题
|
||||
//a-b=target
|
||||
//a+b=sum
|
||||
//a=(target+sum)/2
|
||||
//求出sum
|
||||
var sum int
|
||||
for _,value:=range nums{
|
||||
sum+=value
|
||||
}
|
||||
//如果sum<target或者 sum+target不是偶数(因为a是int) 或者两者之和小于0了
|
||||
if sum<target||(sum+target)%2==1||(sum+target)<0{
|
||||
return 0
|
||||
}
|
||||
//开始dp初始化
|
||||
dp:=make([][]int,len(nums)+1)
|
||||
for i:=0;i<=len(nums);i++{
|
||||
tmp:=make([]int,(target+sum)/2+1)//背包容量
|
||||
dp[i]=tmp
|
||||
}
|
||||
dp[0][0]=1//当背包容量为0,且物品为0时,填满背包就1种方法
|
||||
for i:=0;i<len(nums)+1;i++{
|
||||
if i==0{
|
||||
continue
|
||||
}
|
||||
for j:=0;j<(target+sum)/2+1;j++{
|
||||
if nums[i-1]<=j{//如果背包装的下
|
||||
dp[i][j]=dp[i-1][j]+dp[i-1][j-nums[i-1]]
|
||||
}else{
|
||||
dp[i][j]=dp[i-1][j]
|
||||
}
|
||||
}
|
||||
}
|
||||
return dp[len(nums)][(target+sum)/2]
|
||||
func abs(x int) int {
|
||||
return int(math.Abs(float64(x)))
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
Javascript:
|
||||
```javascript
|
||||
const findTargetSumWays = (nums, target) => {
|
||||
|
@ -245,6 +245,38 @@ var fib = function(n) {
|
||||
};
|
||||
```
|
||||
|
||||
### C
|
||||
动态规划:
|
||||
```c
|
||||
int fib(int n){
|
||||
//当n <= 1时,返回n
|
||||
if(n <= 1)
|
||||
return n;
|
||||
//动态开辟一个int数组,大小为n+1
|
||||
int *dp = (int *)malloc(sizeof(int) * (n + 1));
|
||||
//设置0号位为0,1号为为1
|
||||
dp[0] = 0;
|
||||
dp[1] = 1;
|
||||
|
||||
//从前向后遍历数组(i=2; i <= n; ++i),下标为n时的元素为dp[i-1] + dp[i-2]
|
||||
int i;
|
||||
for(i = 2; i <= n; ++i) {
|
||||
dp[i] = dp[i - 1] + dp[i - 2];
|
||||
}
|
||||
return dp[n];
|
||||
}
|
||||
```
|
||||
|
||||
递归实现:
|
||||
```c
|
||||
int fib(int n){
|
||||
//若n小于等于1,返回n
|
||||
if(n <= 1)
|
||||
return n;
|
||||
//否则返回fib(n-1) + fib(n-2)
|
||||
return fib(n-1) + fib(n-2);
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
-----------------------
|
||||
|
@ -433,6 +433,74 @@ var findBottomLeftValue = function(root) {
|
||||
};
|
||||
```
|
||||
|
||||
## Swift
|
||||
|
||||
递归版本:
|
||||
|
||||
```swift
|
||||
var maxLen = -1
|
||||
var maxLeftValue = 0
|
||||
func findBottomLeftValue_2(_ root: TreeNode?) -> Int {
|
||||
traversal(root, 0)
|
||||
return maxLeftValue
|
||||
}
|
||||
|
||||
func traversal(_ root: TreeNode?, _ deep: Int) {
|
||||
guard let root = root else {
|
||||
return
|
||||
}
|
||||
|
||||
if root.left == nil && root.right == nil {
|
||||
if deep > maxLen {
|
||||
maxLen = deep
|
||||
maxLeftValue = root.val
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if root.left != nil {
|
||||
traversal(root.left, deep + 1)
|
||||
}
|
||||
|
||||
if root.right != nil {
|
||||
traversal(root.right, deep + 1)
|
||||
}
|
||||
return
|
||||
}
|
||||
```
|
||||
层序遍历:
|
||||
|
||||
```swift
|
||||
func findBottomLeftValue(_ root: TreeNode?) -> Int {
|
||||
guard let root = root else {
|
||||
return 0
|
||||
}
|
||||
|
||||
var queue = [root]
|
||||
var result = 0
|
||||
|
||||
while !queue.isEmpty {
|
||||
let size = queue.count
|
||||
for i in 0..<size {
|
||||
let firstNode = queue.removeFirst()
|
||||
|
||||
if i == 0 {
|
||||
result = firstNode.val
|
||||
}
|
||||
|
||||
if let leftNode = firstNode.left {
|
||||
queue.append(leftNode)
|
||||
}
|
||||
|
||||
if let rightNode = firstNode.right {
|
||||
queue.append(rightNode)
|
||||
}
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
-----------------------
|
||||
|
@ -252,6 +252,28 @@ var reverseStr = function(s, k) {
|
||||
|
||||
```
|
||||
|
||||
TypeScript:
|
||||
|
||||
```typescript
|
||||
function reverseStr(s: string, k: number): string {
|
||||
let left: number, right: number;
|
||||
let arr: string[] = s.split('');
|
||||
let temp: string;
|
||||
for (let i = 0, length = arr.length; i < length; i += 2 * k) {
|
||||
left = i;
|
||||
right = (i + k - 1) >= length ? length - 1 : i + k - 1;
|
||||
while (left < right) {
|
||||
temp = arr[left];
|
||||
arr[left] = arr[right];
|
||||
arr[right] = temp;
|
||||
left++;
|
||||
right--;
|
||||
}
|
||||
}
|
||||
return arr.join('');
|
||||
};
|
||||
```
|
||||
|
||||
Swift:
|
||||
|
||||
```swift
|
||||
@ -272,9 +294,21 @@ func reverseStr(_ s: String, _ k: Int) -> String {
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
C#:
|
||||
```csharp
|
||||
public class Solution
|
||||
{
|
||||
public string ReverseStr(string s, int k)
|
||||
{
|
||||
Span<char> span = s.ToCharArray().AsSpan();
|
||||
for (int i = 0; i < span.Length; i += 2 * k)
|
||||
{
|
||||
span[i + k < span.Length ? i..(i + k) : i..].Reverse();
|
||||
}
|
||||
return span.ToString();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
@ -18,6 +18,8 @@
|
||||
|
||||
## 思路
|
||||
|
||||
### 动态规划一
|
||||
|
||||
本题和[动态规划:115.不同的子序列](https://programmercarl.com/0115.不同的子序列.html)相比,其实就是两个字符串都可以删除了,情况虽说复杂一些,但整体思路是不变的。
|
||||
|
||||
这次是两个字符串可以相互删了,这种题目也知道用动态规划的思路来解,动规五部曲,分析如下:
|
||||
@ -98,6 +100,29 @@ public:
|
||||
|
||||
```
|
||||
|
||||
### 动态规划二
|
||||
|
||||
本题和[动态规划:1143.最长公共子序列](https://programmercarl.com/1143.最长公共子序列.html)基本相同,只要求出两个字符串的最长公共子序列长度即可,那么除了最长公共子序列之外的字符都是必须删除的,最后用两个字符串的总长度减去两个最长公共子序列的长度就是删除的最少步数。
|
||||
|
||||
代码如下:
|
||||
|
||||
```CPP
|
||||
class Solution {
|
||||
public:
|
||||
int minDistance(string word1, string word2) {
|
||||
vector<vector<int>> dp(word1.size()+1, vector<int>(word2.size()+1, 0));
|
||||
for (int i=1; i<=word1.size(); i++){
|
||||
for (int j=1; j<=word2.size(); j++){
|
||||
if (word1[i-1] == word2[j-1]) dp[i][j] = dp[i-1][j-1] + 1;
|
||||
else dp[i][j] = max(dp[i-1][j], dp[i][j-1]);
|
||||
}
|
||||
}
|
||||
return word1.size()+word2.size()-dp[word1.size()][word2.size()]*2;
|
||||
}
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
## 其他语言版本
|
||||
|
||||
|
||||
|
@ -401,6 +401,33 @@ struct TreeNode* constructMaximumBinaryTree(int* nums, int numsSize){
|
||||
}
|
||||
```
|
||||
|
||||
## Swift
|
||||
```swift
|
||||
func constructMaximumBinaryTree(_ nums: inout [Int]) -> TreeNode? {
|
||||
return traversal(&nums, 0, nums.count)
|
||||
}
|
||||
|
||||
func traversal(_ nums: inout [Int], _ left: Int, _ right: Int) -> TreeNode? {
|
||||
if left >= right {
|
||||
return nil
|
||||
}
|
||||
|
||||
var maxValueIndex = left
|
||||
for i in (left + 1)..<right {
|
||||
if nums[i] > nums[maxValueIndex] {
|
||||
maxValueIndex = i
|
||||
}
|
||||
}
|
||||
|
||||
let root = TreeNode(nums[maxValueIndex])
|
||||
|
||||
root.left = traversal(&nums, left, maxValueIndex)
|
||||
root.right = traversal(&nums, maxValueIndex + 1, right)
|
||||
return root
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
@ -266,5 +266,21 @@ var minCostClimbingStairs = function(cost) {
|
||||
};
|
||||
```
|
||||
|
||||
### C
|
||||
```c
|
||||
int minCostClimbingStairs(int* cost, int costSize){
|
||||
//开辟dp数组,大小为costSize
|
||||
int *dp = (int *)malloc(sizeof(int) * costSize);
|
||||
//初始化dp[0] = cost[0], dp[1] = cost[1]
|
||||
dp[0] = cost[0], dp[1] = cost[1];
|
||||
|
||||
int i;
|
||||
for(i = 2; i < costSize; ++i) {
|
||||
dp[i] = (dp[i-1] < dp[i-2] ? dp[i-1] : dp[i-2]) + cost[i];
|
||||
}
|
||||
//选出倒数2层楼梯中较小的
|
||||
return dp[i-1] < dp[i-2] ? dp[i-1] : dp[i-2];
|
||||
}
|
||||
```
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
@ -205,6 +205,42 @@ class Solution:
|
||||
return self.get_string(s) == self.get_string(t)
|
||||
pass
|
||||
```
|
||||
双指针
|
||||
```python
|
||||
class Solution:
|
||||
def backspaceCompare(self, s: str, t: str) -> bool:
|
||||
s_index, t_index = len(s) - 1, len(t) - 1
|
||||
s_backspace, t_backspace = 0, 0 # 记录s,t的#数量
|
||||
while s_index >= 0 or t_index >= 0: # 使用or,以防长度不一致
|
||||
while s_index >= 0: # 从后向前,消除s的#
|
||||
if s[s_index] == '#':
|
||||
s_index -= 1
|
||||
s_backspace += 1
|
||||
else:
|
||||
if s_backspace > 0:
|
||||
s_index -= 1
|
||||
s_backspace -= 1
|
||||
else:
|
||||
break
|
||||
while t_index >= 0: # 从后向前,消除t的#
|
||||
if t[t_index] == '#':
|
||||
t_index -= 1
|
||||
t_backspace += 1
|
||||
else:
|
||||
if t_backspace > 0:
|
||||
t_index -= 1
|
||||
t_backspace -= 1
|
||||
else:
|
||||
break
|
||||
if s_index >= 0 and t_index >= 0: # 后半部分#消除完了,接下来比较当前位的值
|
||||
if s[s_index] != t[t_index]:
|
||||
return False
|
||||
elif s_index >= 0 or t_index >= 0: # 一个字符串找到了待比较的字符,另一个没有,返回False
|
||||
return False
|
||||
s_index -= 1
|
||||
t_index -= 1
|
||||
return True
|
||||
```
|
||||
|
||||
### Go
|
||||
|
||||
@ -226,6 +262,51 @@ func backspaceCompare(s string, t string) bool {
|
||||
return getString(s) == getString(t)
|
||||
}
|
||||
|
||||
```
|
||||
双指针
|
||||
```go
|
||||
func backspaceCompare(s string, t string) bool {
|
||||
s_index, t_index := len(s) - 1, len(t) - 1
|
||||
s_backspace, t_backspace := 0, 0 // 记录s,t的#数量
|
||||
for s_index >= 0 || t_index >= 0 { // 使用or,以防长度不一致
|
||||
for s_index >= 0 { // 从后向前,消除s的#
|
||||
if s[s_index] == '#' {
|
||||
s_index--
|
||||
s_backspace++
|
||||
} else {
|
||||
if s_backspace > 0 {
|
||||
s_index--
|
||||
s_backspace--
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
for t_index >= 0 { // 从后向前,消除t的#
|
||||
if t[t_index] == '#' {
|
||||
t_index--
|
||||
t_backspace++
|
||||
} else {
|
||||
if t_backspace > 0 {
|
||||
t_index--
|
||||
t_backspace--
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if s_index >= 0 && t_index >= 0 { // 后半部分#消除完了,接下来比较当前位的值
|
||||
if s[s_index] != t[t_index] {
|
||||
return false
|
||||
}
|
||||
} else if s_index >= 0 || t_index >= 0 { // 一个字符串找到了待比较的字符,另一个没有,返回false
|
||||
return false
|
||||
}
|
||||
s_index--
|
||||
t_index--
|
||||
}
|
||||
return true
|
||||
}
|
||||
```
|
||||
|
||||
### JavaScript
|
||||
|
@ -267,8 +267,32 @@ var removeDuplicates = function(s) {
|
||||
};
|
||||
```
|
||||
|
||||
TypeScript:
|
||||
|
||||
```typescript
|
||||
function removeDuplicates(s: string): string {
|
||||
const helperStack: string[] = [];
|
||||
let i: number = 0;
|
||||
while (i < s.length) {
|
||||
let top: string = helperStack[helperStack.length - 1];
|
||||
if (top === s[i]) {
|
||||
helperStack.pop();
|
||||
} else {
|
||||
helperStack.push(s[i]);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
let res: string = '';
|
||||
while (helperStack.length > 0) {
|
||||
res = helperStack.pop() + res;
|
||||
}
|
||||
return res;
|
||||
};
|
||||
```
|
||||
|
||||
C:
|
||||
方法一:使用栈
|
||||
|
||||
```c
|
||||
char * removeDuplicates(char * s){
|
||||
//求出字符串长度
|
||||
|
@ -116,19 +116,19 @@ Java:
|
||||
```Java
|
||||
// 前序遍历·递归·LC144_二叉树的前序遍历
|
||||
class Solution {
|
||||
ArrayList<Integer> preOrderReverse(TreeNode root) {
|
||||
ArrayList<Integer> result = new ArrayList<Integer>();
|
||||
preOrder(root, result);
|
||||
public List<Integer> preorderTraversal(TreeNode root) {
|
||||
List<Integer> result = new ArrayList<Integer>();
|
||||
preorder(root, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void preOrder(TreeNode root, ArrayList<Integer> result) {
|
||||
public void preorder(TreeNode root, List<Integer> result) {
|
||||
if (root == null) {
|
||||
return;
|
||||
}
|
||||
result.add(root.val); // 注意这一句
|
||||
preOrder(root.left, result);
|
||||
preOrder(root.right, result);
|
||||
result.add(root.val);
|
||||
preorder(root.left, result);
|
||||
preorder(root.right, result);
|
||||
}
|
||||
}
|
||||
// 中序遍历·递归·LC94_二叉树的中序遍历
|
||||
|
@ -298,6 +298,33 @@ javaScript:
|
||||
};
|
||||
```
|
||||
|
||||
TypeScript:
|
||||
|
||||
```typescript
|
||||
function replaceSpace(s: string): string {
|
||||
let arr: string[] = s.split('');
|
||||
let spaceNum: number = 0;
|
||||
let oldLength: number = arr.length;
|
||||
for (let i = 0; i < oldLength; i++) {
|
||||
if (arr[i] === ' ') {
|
||||
spaceNum++;
|
||||
}
|
||||
}
|
||||
arr.length = oldLength + 2 * spaceNum;
|
||||
let cur: number = oldLength - 1;
|
||||
for (let i = arr.length - 1; i >= 0; i--, cur--) {
|
||||
if (arr[cur] !== ' ') {
|
||||
arr[i] = arr[cur]
|
||||
} else {
|
||||
arr[i] = '0';
|
||||
arr[--i] = '2';
|
||||
arr[--i] = '%';
|
||||
}
|
||||
}
|
||||
return arr.join('');
|
||||
};
|
||||
```
|
||||
|
||||
Swift:
|
||||
|
||||
```swift
|
||||
|
@ -209,6 +209,61 @@ var reverseLeftWords = function(s, n) {
|
||||
};
|
||||
```
|
||||
|
||||
版本二(在原字符串上操作):
|
||||
|
||||
```js
|
||||
/**
|
||||
* @param {string} s
|
||||
* @param {number} n
|
||||
* @return {string}
|
||||
*/
|
||||
var reverseLeftWords = function (s, n) {
|
||||
/** Utils */
|
||||
function reverseWords(strArr, start, end) {
|
||||
let temp;
|
||||
while (start < end) {
|
||||
temp = strArr[start];
|
||||
strArr[start] = strArr[end];
|
||||
strArr[end] = temp;
|
||||
start++;
|
||||
end--;
|
||||
}
|
||||
}
|
||||
/** Main code */
|
||||
let strArr = s.split('');
|
||||
let length = strArr.length;
|
||||
reverseWords(strArr, 0, length - 1);
|
||||
reverseWords(strArr, 0, length - n - 1);
|
||||
reverseWords(strArr, length - n, length - 1);
|
||||
return strArr.join('');
|
||||
};
|
||||
```
|
||||
|
||||
TypeScript:
|
||||
|
||||
```typescript
|
||||
function reverseLeftWords(s: string, n: number): string {
|
||||
/** Utils */
|
||||
function reverseWords(strArr: string[], start: number, end: number): void {
|
||||
let temp: string;
|
||||
while (start < end) {
|
||||
temp = strArr[start];
|
||||
strArr[start] = strArr[end];
|
||||
strArr[end] = temp;
|
||||
start++;
|
||||
end--;
|
||||
}
|
||||
}
|
||||
/** Main code */
|
||||
let strArr: string[] = s.split('');
|
||||
let length: number = strArr.length;
|
||||
reverseWords(strArr, 0, length - 1);
|
||||
reverseWords(strArr, 0, length - n - 1);
|
||||
reverseWords(strArr, length - n, length - 1);
|
||||
return strArr.join('');
|
||||
};
|
||||
```
|
||||
|
||||
Swift:
|
||||
|
||||
```swift
|
||||
|
@ -67,7 +67,7 @@ deque是一个双向队列,只要封住一段,只开通另一端就可以实
|
||||
|
||||
我们也可以指定vector为栈的底层实现,初始化语句如下:
|
||||
|
||||
```
|
||||
```cpp
|
||||
std::stack<int, std::vector<int> > third; // 使用vector为底层容器的栈
|
||||
```
|
||||
|
||||
@ -77,7 +77,7 @@ std::stack<int, std::vector<int> > third; // 使用vector为底层容器的栈
|
||||
|
||||
也可以指定list 为起底层实现,初始化queue的语句如下:
|
||||
|
||||
```
|
||||
```cpp
|
||||
std::queue<int, std::list<int>> third; // 定义以list为底层容器的队列
|
||||
```
|
||||
|
||||
|
@ -52,7 +52,7 @@ for(int i = 0; i < weight.size(); i++) { // 遍历物品
|
||||
```CPP
|
||||
// 先遍历物品,再遍历背包
|
||||
for(int i = 0; i < weight.size(); i++) { // 遍历物品
|
||||
for(int j = weight[i]; j < bagWeight ; j++) { // 遍历背包容量
|
||||
for(int j = weight[i]; j <= bagWeight ; j++) { // 遍历背包容量
|
||||
dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);
|
||||
|
||||
}
|
||||
@ -183,11 +183,9 @@ private static void testCompletePack(){
|
||||
int[] value = {15, 20, 30};
|
||||
int bagWeight = 4;
|
||||
int[] dp = new int[bagWeight + 1];
|
||||
for (int i = 0; i < weight.length; i++){
|
||||
for (int j = 1; j <= bagWeight; j++){
|
||||
if (j - weight[i] >= 0){
|
||||
dp[j] = Math.max(dp[j], dp[j - weight[i]] + value[i]);
|
||||
}
|
||||
for (int i = 0; i < weight.length; i++){ // 遍历物品
|
||||
for (int j = weight[i]; j <= bagWeight; j++){ // 遍历背包容量
|
||||
dp[j] = Math.max(dp[j], dp[j - weight[i]] + value[i]);
|
||||
}
|
||||
}
|
||||
for (int maxValue : dp){
|
||||
@ -201,8 +199,8 @@ private static void testCompletePackAnotherWay(){
|
||||
int[] value = {15, 20, 30};
|
||||
int bagWeight = 4;
|
||||
int[] dp = new int[bagWeight + 1];
|
||||
for (int i = 1; i <= bagWeight; i++){
|
||||
for (int j = 0; j < weight.length; j++){
|
||||
for (int i = 1; i <= bagWeight; i++){ // 遍历背包容量
|
||||
for (int j = 0; j < weight.length; j++){ // 遍历物品
|
||||
if (i - weight[j] >= 0){
|
||||
dp[i] = Math.max(dp[i], dp[i - weight[j]] + value[j]);
|
||||
}
|
||||
|
@ -195,10 +195,20 @@ class ListNode {
|
||||
```
|
||||
|
||||
Python:
|
||||
|
||||
```python
|
||||
class ListNode:
|
||||
def __init__(self, val, next=None):
|
||||
self.val = val
|
||||
self.next = next
|
||||
```
|
||||
|
||||
Go:
|
||||
|
||||
```go
|
||||
type ListNode struct {
|
||||
Val int
|
||||
Next *ListNode
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
41
problems/面试题 02.07. 解法更新.md
Normal file
41
problems/面试题 02.07. 解法更新.md
Normal file
@ -0,0 +1,41 @@
|
||||
# 双指针,不计算链表长度
|
||||
设置指向headA和headB的指针pa、pb,分别遍历两个链表,每次循环同时更新pa和pb。
|
||||
* 当链表A遍历完之后,即pa为空时,将pa指向headB;
|
||||
* 当链表B遍历完之后,即pa为空时,将pb指向headA;
|
||||
* 当pa与pb相等时,即指向同一个节点,该节点即为相交起始节点。
|
||||
* 若链表不相交,则pa、pb同时为空时退出循环,即如果链表不相交,pa与pb在遍历过全部节点后同时指向结尾空节点,此时退出循环,返回空。
|
||||
# 证明思路
|
||||
设链表A不相交部分长度为a,链表B不相交部分长度为b,两个链表相交部分长度为c。<br>
|
||||
在pa指向链表A时,即pa为空之前,pa经过链表A不相交部分和相交部分,走过的长度为a+c;<br>
|
||||
pa指向链表B后,在移动相交节点之前经过链表B不相交部分,走过的长度为b,总合为a+c+b。<br>
|
||||
同理,pb走过长度的总合为b+c+a。二者相等,即pa与pb可同时到达相交起始节点。 <br>
|
||||
该方法可避免计算具体链表长度。
|
||||
```cpp
|
||||
class Solution {
|
||||
public:
|
||||
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
|
||||
//链表为空时,返回空指针
|
||||
if(headA == nullptr || headB == nullptr) return nullptr;
|
||||
ListNode* pa = headA;
|
||||
ListNode* pb = headB;
|
||||
//pa与pb在遍历过全部节点后,同时指向结尾空节点时退出循环
|
||||
while(pa != nullptr || pb != nullptr){
|
||||
//pa为空时,将pa指向headB
|
||||
if(pa == nullptr){
|
||||
pa = headB;
|
||||
}
|
||||
//pa为空时,将pb指向headA
|
||||
if(pb == nullptr){
|
||||
pb = headA;
|
||||
}
|
||||
//pa与pb相等时,返回相交起始节点
|
||||
if(pa == pb){
|
||||
return pa;
|
||||
}
|
||||
pa = pa->next;
|
||||
pb = pb->next;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
```
|
@ -239,6 +239,43 @@ var getIntersectionNode = function(headA, headB) {
|
||||
};
|
||||
```
|
||||
|
||||
TypeScript:
|
||||
|
||||
```typescript
|
||||
function getIntersectionNode(headA: ListNode | null, headB: ListNode | null): ListNode | null {
|
||||
let sizeA: number = 0,
|
||||
sizeB: number = 0;
|
||||
let curA: ListNode | null = headA,
|
||||
curB: ListNode | null = headB;
|
||||
while (curA) {
|
||||
sizeA++;
|
||||
curA = curA.next;
|
||||
}
|
||||
while (curB) {
|
||||
sizeB++;
|
||||
curB = curB.next;
|
||||
}
|
||||
curA = headA;
|
||||
curB = headB;
|
||||
if (sizeA < sizeB) {
|
||||
[sizeA, sizeB] = [sizeB, sizeA];
|
||||
[curA, curB] = [curB, curA];
|
||||
}
|
||||
let gap = sizeA - sizeB;
|
||||
while (gap-- && curA) {
|
||||
curA = curA.next;
|
||||
}
|
||||
while (curA && curB) {
|
||||
if (curA === curB) {
|
||||
return curA;
|
||||
}
|
||||
curA = curA.next;
|
||||
curB = curB.next;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
```
|
||||
|
||||
C:
|
||||
|
||||
```c
|
||||
|
Reference in New Issue
Block a user