diff --git a/problems/0001.两数之和.md b/problems/0001.两数之和.md index 8551274c..22b2e7eb 100644 --- a/problems/0001.两数之和.md +++ b/problems/0001.两数之和.md @@ -186,6 +186,24 @@ var twoSum = function (nums, target) { }; ``` +TypeScript: + +```typescript +function twoSum(nums: number[], target: number): number[] { + let helperMap: Map = 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 diff --git a/problems/0005.最长回文子串.md b/problems/0005.最长回文子串.md index f204a607..99458825 100644 --- a/problems/0005.最长回文子串.md +++ b/problems/0005.最长回文子串.md @@ -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; +} +``` -----------------------
diff --git a/problems/0015.三数之和.md b/problems/0015.三数之和.md index c78ab06d..e191eabc 100644 --- a/problems/0015.三数之和.md +++ b/problems/0015.三数之和.md @@ -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> ThreeSum(int[] nums) + { + var result = new List>(); + + 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 { n1, n2, n3 }); + + while (left < right && nums[left] == n2) + { + left++; + } + + while (left < right && nums[right] == n3) + { + right--; + } + } + } + } + + return result; + } +} +``` + -----------------------
diff --git a/problems/0018.四数之和.md b/problems/0018.四数之和.md index b94ebeef..bad258c1 100644 --- a/problems/0018.四数之和.md +++ b/problems/0018.四数之和.md @@ -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> FourSum(int[] nums, int target) + { + var result = new List>(); + + 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 { n1, n2, n3, n4 }); + + while (left < right && nums[left] == n3) + { + left++; + } + + while (left < right && nums[right] == n4) + { + right--; + } + } + } + } + } + + return result; + } +} +``` + -----------------------
diff --git a/problems/0019.删除链表的倒数第N个节点.md b/problems/0019.删除链表的倒数第N个节点.md index e041937f..813e9b02 100644 --- a/problems/0019.删除链表的倒数第N个节点.md +++ b/problems/0019.删除链表的倒数第N个节点.md @@ -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 { diff --git a/problems/0020.有效的括号.md b/problems/0020.有效的括号.md index 9e4046d4..95d62e42 100644 --- a/problems/0020.有效的括号.md +++ b/problems/0020.有效的括号.md @@ -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]() diff --git a/problems/0024.两两交换链表中的节点.md b/problems/0024.两两交换链表中的节点.md index 01abc7b4..bf1fd5e1 100644 --- a/problems/0024.两两交换链表中的节点.md +++ b/problems/0024.两两交换链表中的节点.md @@ -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 diff --git a/problems/0027.移除元素.md b/problems/0027.移除元素.md index 99990302..d69f2bcf 100644 --- a/problems/0027.移除元素.md +++ b/problems/0027.移除元素.md @@ -42,7 +42,7 @@ ![27.移除元素-暴力解法](https://tva1.sinaimg.cn/large/008eGmZEly1gntrc7x9tjg30du09m1ky.gif) -很明显暴力解法的时间复杂度是O(n^2),这道题目暴力解法在leetcode上是可以过的。 +很明显暴力解法的时间复杂度是$O(n^2)$,这道题目暴力解法在leetcode上是可以过的。 代码如下: diff --git a/problems/0028.实现strStr.md b/problems/0028.实现strStr.md index f0b56719..bbe5b80f 100644 --- a/problems/0028.实现strStr.md +++ b/problems/0028.实现strStr.md @@ -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 版本 > 前缀表统一减一 diff --git a/problems/0031.下一个排列.md b/problems/0031.下一个排列.md index 84bf3e60..2219e24d 100644 --- a/problems/0031.下一个排列.md +++ b/problems/0031.下一个排列.md @@ -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; } } diff --git a/problems/0034.在排序数组中查找元素的第一个和最后一个位置.md b/problems/0034.在排序数组中查找元素的第一个和最后一个位置.md index 2b96e41b..dfd90b82 100644 --- a/problems/0034.在排序数组中查找元素的第一个和最后一个位置.md +++ b/problems/0034.在排序数组中查找元素的第一个和最后一个位置.md @@ -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 diff --git a/problems/0051.N皇后.md b/problems/0051.N皇后.md index 51415e88..7eb0d7a0 100644 --- a/problems/0051.N皇后.md +++ b/problems/0051.N皇后.md @@ -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= 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 diff --git a/problems/0052.N皇后II.md b/problems/0052.N皇后II.md index 78531798..67e439ca 100644 --- a/problems/0052.N皇后II.md +++ b/problems/0052.N皇后II.md @@ -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; +} +``` + -----------------------
diff --git a/problems/0054.螺旋矩阵.md b/problems/0054.螺旋矩阵.md index 3f85c607..ccf6f471 100644 --- a/problems/0054.螺旋矩阵.md +++ b/problems/0054.螺旋矩阵.md @@ -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 +``` -----------------------
diff --git a/problems/0059.螺旋矩阵II.md b/problems/0059.螺旋矩阵II.md index c7e91b4d..3f7a59ca 100644 --- a/problems/0059.螺旋矩阵II.md +++ b/problems/0059.螺旋矩阵II.md @@ -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 diff --git a/problems/0062.不同路径.md b/problems/0062.不同路径.md index e209abb1..efa85a03 100644 --- a/problems/0062.不同路径.md +++ b/problems/0062.不同路径.md @@ -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; +} +``` -----------------------
diff --git a/problems/0063.不同路径II.md b/problems/0063.不同路径II.md index 1bcc11cd..8e82007e 100644 --- a/problems/0063.不同路径II.md +++ b/problems/0063.不同路径II.md @@ -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 diff --git a/problems/0070.爬楼梯.md b/problems/0070.爬楼梯.md index 97db670a..7f47a991 100644 --- a/problems/0070.爬楼梯.md +++ b/problems/0070.爬楼梯.md @@ -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]; +} +``` + -----------------------
diff --git a/problems/0096.不同的二叉搜索树.md b/problems/0096.不同的二叉搜索树.md index 48826697..41fcb8fe 100644 --- a/problems/0096.不同的二叉搜索树.md +++ b/problems/0096.不同的二叉搜索树.md @@ -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]; +} +``` -----------------------
diff --git a/problems/0110.平衡二叉树.md b/problems/0110.平衡二叉树.md index c0914f05..9d43407a 100644 --- a/problems/0110.平衡二叉树.md +++ b/problems/0110.平衡二叉树.md @@ -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) + } +} +``` + -----------------------
diff --git a/problems/0112.路径总和.md b/problems/0112.路径总和.md index 910e57c8..5ec8ffd0 100644 --- a/problems/0112.路径总和.md +++ b/problems/0112.路径总和.md @@ -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 +} +``` diff --git a/problems/0129.求根到叶子节点数字之和.md b/problems/0129.求根到叶子节点数字之和.md index d07d5244..980779c2 100644 --- a/problems/0129.求根到叶子节点数字之和.md +++ b/problems/0129.求根到叶子节点数字之和.md @@ -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; +} +``` -----------------------
diff --git a/problems/0142.环形链表II.md b/problems/0142.环形链表II.md index dfe042b8..e8ca950d 100644 --- a/problems/0142.环形链表II.md +++ b/problems/0142.环形链表II.md @@ -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? { diff --git a/problems/0143.重排链表.md b/problems/0143.重排链表.md index 4ea9cb97..00622623 100644 --- a/problems/0143.重排链表.md +++ b/problems/0143.重排链表.md @@ -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; +} +``` ----------------------- diff --git a/problems/0150.逆波兰表达式求值.md b/problems/0150.逆波兰表达式求值.md index f44703f1..f4dad823 100644 --- a/problems/0150.逆波兰表达式求值.md +++ b/problems/0150.逆波兰表达式求值.md @@ -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 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 diff --git a/problems/0151.翻转字符串里的单词.md b/problems/0151.翻转字符串里的单词.md index d58ace89..ead5fa12 100644 --- a/problems/0151.翻转字符串里的单词.md +++ b/problems/0151.翻转字符串里的单词.md @@ -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 diff --git a/problems/0202.快乐数.md b/problems/0202.快乐数.md index 2d678151..f0a46a40 100644 --- a/problems/0202.快乐数.md +++ b/problems/0202.快乐数.md @@ -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 = 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 { diff --git a/problems/0209.长度最小的子数组.md b/problems/0209.长度最小的子数组.md index 17422ca0..dc1d9f18 100644 --- a/problems/0209.长度最小的子数组.md +++ b/problems/0209.长度最小的子数组.md @@ -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; +} +``` + -----------------------
diff --git a/problems/0225.用队列实现栈.md b/problems/0225.用队列实现栈.md index fdb544a6..c45917db 100644 --- a/problems/0225.用队列实现栈.md +++ b/problems/0225.用队列实现栈.md @@ -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 { diff --git a/problems/0232.用栈实现队列.md b/problems/0232.用栈实现队列.md index 4edba2f2..b00ffd80 100644 --- a/problems/0232.用栈实现队列.md +++ b/problems/0232.用栈实现队列.md @@ -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 { diff --git a/problems/0239.滑动窗口最大值.md b/problems/0239.滑动窗口最大值.md index d9788f63..adf3548c 100644 --- a/problems/0239.滑动窗口最大值.md +++ b/problems/0239.滑动窗口最大值.md @@ -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 { diff --git a/problems/0242.有效的字母异位词.md b/problems/0242.有效的字母异位词.md index cdcf39ce..52f8e667 100644 --- a/problems/0242.有效的字母异位词.md +++ b/problems/0242.有效的字母异位词.md @@ -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 { diff --git a/problems/0257.二叉树的所有路径.md b/problems/0257.二叉树的所有路径.md index cb837d87..4078320f 100644 --- a/problems/0257.二叉树的所有路径.md +++ b/problems/0257.二叉树的所有路径.md @@ -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 +} +``` -----------------------
diff --git a/problems/0283.移动零.md b/problems/0283.移动零.md index 13b9c26c..bb75a696 100644 --- a/problems/0283.移动零.md +++ b/problems/0283.移动零.md @@ -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) { diff --git a/problems/0343.整数拆分.md b/problems/0343.整数拆分.md index 471a7ab7..282670a3 100644 --- a/problems/0343.整数拆分.md +++ b/problems/0343.整数拆分.md @@ -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]; +} +``` + -----------------------
diff --git a/problems/0344.反转字符串.md b/problems/0344.反转字符串.md index 9176c915..58bada05 100644 --- a/problems/0344.反转字符串.md +++ b/problems/0344.反转字符串.md @@ -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]); + } + } +} +``` -----------------------
diff --git a/problems/0347.前K个高频元素.md b/problems/0347.前K个高频元素.md index 0b8fd2d7..8bd774e9 100644 --- a/problems/0347.前K个高频元素.md +++ b/problems/0347.前K个高频元素.md @@ -142,7 +142,7 @@ class Solution { Set> entries = map.entrySet(); // 根据map的value值正序排,相当于一个小顶堆 - PriorityQueue> queue = new PriorityQueue<>((o1, o2) -> o2.getValue() - o1.getValue()); + PriorityQueue> queue = new PriorityQueue<>((o1, o2) -> o1.getValue() - o2.getValue()); for (Map.Entry entry : entries) { queue.offer(entry); if (queue.size() > k) { diff --git a/problems/0349.两个数组的交集.md b/problems/0349.两个数组的交集.md index 812c4489..92342f17 100644 --- a/problems/0349.两个数组的交集.md +++ b/problems/0349.两个数组的交集.md @@ -190,7 +190,33 @@ var intersection = function(nums1, nums2) { }; ``` +TypeScript: + +版本一(正常解法): + +```typescript +function intersection(nums1: number[], nums2: number[]): number[] { + let resSet: Set = new Set(), + nums1Set: Set = 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() diff --git a/problems/0383.赎金信.md b/problems/0383.赎金信.md index 650f2a99..31e19b10 100644 --- a/problems/0383.赎金信.md +++ b/problems/0383.赎金信.md @@ -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 diff --git a/problems/0404.左叶子之和.md b/problems/0404.左叶子之和.md index ddbd100e..09272052 100644 --- a/problems/0404.左叶子之和.md +++ b/problems/0404.左叶子之和.md @@ -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() + 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 +} +``` diff --git a/problems/0435.无重叠区间.md b/problems/0435.无重叠区间.md index 118360bc..389443d1 100644 --- a/problems/0435.无重叠区间.md +++ b/problems/0435.无重叠区间.md @@ -183,28 +183,22 @@ public: ```java class Solution { public int eraseOverlapIntervals(int[][] intervals) { - if (intervals.length < 2) return 0; - - Arrays.sort(intervals, new Comparator() { - @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; } } ``` diff --git a/problems/0452.用最少数量的箭引爆气球.md b/problems/0452.用最少数量的箭引爆气球.md index ebfe648f..33bbad55 100644 --- a/problems/0452.用最少数量的箭引爆气球.md +++ b/problems/0452.用最少数量的箭引爆气球.md @@ -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>) -> 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; + } +} +``` -----------------------
diff --git a/problems/0454.四数相加II.md b/problems/0454.四数相加II.md index 6e916608..a7c903eb 100644 --- a/problems/0454.四数相加II.md +++ b/problems/0454.四数相加II.md @@ -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 = 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 { /** diff --git a/problems/0459.重复的子字符串.md b/problems/0459.重复的子字符串.md index 9c74f4a7..ccfb485c 100644 --- a/problems/0459.重复的子字符串.md +++ b/problems/0459.重复的子字符串.md @@ -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; +}; +``` -----------------------
diff --git a/problems/0494.目标和.md b/problems/0494.目标和.md index 1835f498..0faef4a5 100644 --- a/problems/0494.目标和.md +++ b/problems/0494.目标和.md @@ -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 { diff --git a/problems/0509.斐波那契数.md b/problems/0509.斐波那契数.md index d8020d83..c6ce76c0 100644 --- a/problems/0509.斐波那契数.md +++ b/problems/0509.斐波那契数.md @@ -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); +} +``` ----------------------- diff --git a/problems/0513.找树左下角的值.md b/problems/0513.找树左下角的值.md index 99f42d34..84ed3932 100644 --- a/problems/0513.找树左下角的值.md +++ b/problems/0513.找树左下角的值.md @@ -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..= 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 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(); + } +} +``` -----------------------
diff --git a/problems/0583.两个字符串的删除操作.md b/problems/0583.两个字符串的删除操作.md index d2f7d84b..53c1a125 100644 --- a/problems/0583.两个字符串的删除操作.md +++ b/problems/0583.两个字符串的删除操作.md @@ -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> dp(word1.size()+1, vector(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; + } +}; + +``` + ## 其他语言版本 diff --git a/problems/0654.最大二叉树.md b/problems/0654.最大二叉树.md index b4679c7d..44c74f89 100644 --- a/problems/0654.最大二叉树.md +++ b/problems/0654.最大二叉树.md @@ -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).. nums[maxValueIndex] { + maxValueIndex = i + } + } + + let root = TreeNode(nums[maxValueIndex]) + + root.left = traversal(&nums, left, maxValueIndex) + root.right = traversal(&nums, maxValueIndex + 1, right) + return root +} +``` + + -----------------------
diff --git a/problems/0746.使用最小花费爬楼梯.md b/problems/0746.使用最小花费爬楼梯.md index 0009f06c..e94e4d24 100644 --- a/problems/0746.使用最小花费爬楼梯.md +++ b/problems/0746.使用最小花费爬楼梯.md @@ -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]; +} +``` -----------------------
diff --git a/problems/0844.比较含退格的字符串.md b/problems/0844.比较含退格的字符串.md index 5d629a8c..00d52e42 100644 --- a/problems/0844.比较含退格的字符串.md +++ b/problems/0844.比较含退格的字符串.md @@ -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 diff --git a/problems/1047.删除字符串中的所有相邻重复项.md b/problems/1047.删除字符串中的所有相邻重复项.md index d6eefd07..9a0bb1c1 100644 --- a/problems/1047.删除字符串中的所有相邻重复项.md +++ b/problems/1047.删除字符串中的所有相邻重复项.md @@ -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){ //求出字符串长度 diff --git a/problems/二叉树的递归遍历.md b/problems/二叉树的递归遍历.md index 45b576e7..4beed650 100644 --- a/problems/二叉树的递归遍历.md +++ b/problems/二叉树的递归遍历.md @@ -116,19 +116,19 @@ Java: ```Java // 前序遍历·递归·LC144_二叉树的前序遍历 class Solution { - ArrayList preOrderReverse(TreeNode root) { - ArrayList result = new ArrayList(); - preOrder(root, result); + public List preorderTraversal(TreeNode root) { + List result = new ArrayList(); + preorder(root, result); return result; } - void preOrder(TreeNode root, ArrayList result) { + public void preorder(TreeNode root, List 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_二叉树的中序遍历 diff --git a/problems/剑指Offer05.替换空格.md b/problems/剑指Offer05.替换空格.md index d0f382c8..530545fb 100644 --- a/problems/剑指Offer05.替换空格.md +++ b/problems/剑指Offer05.替换空格.md @@ -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 diff --git a/problems/剑指Offer58-II.左旋转字符串.md b/problems/剑指Offer58-II.左旋转字符串.md index c391d661..61391274 100644 --- a/problems/剑指Offer58-II.左旋转字符串.md +++ b/problems/剑指Offer58-II.左旋转字符串.md @@ -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 diff --git a/problems/栈与队列理论基础.md b/problems/栈与队列理论基础.md index b9811b29..44fcbdd5 100644 --- a/problems/栈与队列理论基础.md +++ b/problems/栈与队列理论基础.md @@ -67,7 +67,7 @@ deque是一个双向队列,只要封住一段,只开通另一端就可以实 我们也可以指定vector为栈的底层实现,初始化语句如下: -``` +```cpp std::stack > third; // 使用vector为底层容器的栈 ``` @@ -77,7 +77,7 @@ std::stack > third; // 使用vector为底层容器的栈 也可以指定list 为起底层实现,初始化queue的语句如下: -``` +```cpp std::queue> third; // 定义以list为底层容器的队列 ``` diff --git a/problems/背包问题理论基础完全背包.md b/problems/背包问题理论基础完全背包.md index 3cc8557c..cea69c72 100644 --- a/problems/背包问题理论基础完全背包.md +++ b/problems/背包问题理论基础完全背包.md @@ -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]); } diff --git a/problems/链表理论基础.md b/problems/链表理论基础.md index 109aa1ed..a4fefa2b 100644 --- a/problems/链表理论基础.md +++ b/problems/链表理论基础.md @@ -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 +} +``` diff --git a/problems/面试题 02.07. 解法更新.md b/problems/面试题 02.07. 解法更新.md new file mode 100644 index 00000000..6115d02e --- /dev/null +++ b/problems/面试题 02.07. 解法更新.md @@ -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。
+在pa指向链表A时,即pa为空之前,pa经过链表A不相交部分和相交部分,走过的长度为a+c;
+pa指向链表B后,在移动相交节点之前经过链表B不相交部分,走过的长度为b,总合为a+c+b。
+同理,pb走过长度的总合为b+c+a。二者相等,即pa与pb可同时到达相交起始节点。
+该方法可避免计算具体链表长度。 +```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; + } +}; +``` diff --git a/problems/面试题02.07.链表相交.md b/problems/面试题02.07.链表相交.md index e8198aa0..dd91f069 100644 --- a/problems/面试题02.07.链表相交.md +++ b/problems/面试题02.07.链表相交.md @@ -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