Merge branch 'youngyangyang04:master' into master

This commit is contained in:
Amberling
2022-04-21 10:30:14 +08:00
committed by GitHub
20 changed files with 622 additions and 46 deletions

View File

@ -331,6 +331,34 @@ var permute = function(nums) {
```
## TypeScript
```typescript
function permute(nums: number[]): number[][] {
const resArr: number[][] = [];
const helperSet: Set<number> = new Set();
backTracking(nums, []);
return resArr;
function backTracking(nums: number[], route: number[]): void {
if (route.length === nums.length) {
resArr.push(route.slice());
return;
}
let tempVal: number;
for (let i = 0, length = nums.length; i < length; i++) {
tempVal = nums[i];
if (!helperSet.has(tempVal)) {
route.push(tempVal);
helperSet.add(tempVal);
backTracking(nums, route);
route.pop();
helperSet.delete(tempVal);
}
}
}
};
```
### C
```c

View File

@ -292,6 +292,34 @@ var permuteUnique = function (nums) {
```
### TypeScript
```typescript
function permuteUnique(nums: number[]): number[][] {
nums.sort((a, b) => a - b);
const resArr: number[][] = [];
const usedArr: boolean[] = new Array(nums.length).fill(false);
backTracking(nums, []);
return resArr;
function backTracking(nums: number[], route: number[]): void {
if (route.length === nums.length) {
resArr.push(route.slice());
return;
}
for (let i = 0, length = nums.length; i < length; i++) {
if (i > 0 && nums[i] === nums[i - 1] && usedArr[i - 1] === false) continue;
if (usedArr[i] === false) {
route.push(nums[i]);
usedArr[i] = true;
backTracking(nums, route);
usedArr[i] = false;
route.pop();
}
}
}
};
```
### Swift
```swift

View File

@ -272,7 +272,28 @@ var subsets = function(nums) {
};
```
## TypeScript
```typescript
function subsets(nums: number[]): number[][] {
const resArr: number[][] = [];
backTracking(nums, 0, []);
return resArr;
function backTracking(nums: number[], startIndex: number, route: number[]): void {
resArr.push(route.slice());
let length = nums.length;
if (startIndex === length) return;
for (let i = startIndex; i < length; i++) {
route.push(nums[i]);
backTracking(nums, i + 1, route);
route.pop();
}
}
};
```
## C
```c
int* path;
int pathTop;

View File

@ -318,6 +318,28 @@ var subsetsWithDup = function(nums) {
```
### TypeScript
```typescript
function subsetsWithDup(nums: number[]): number[][] {
nums.sort((a, b) => a - b);
const resArr: number[][] = [];
backTraking(nums, 0, []);
return resArr;
function backTraking(nums: number[], startIndex: number, route: number[]): void {
resArr.push(route.slice());
let length: number = nums.length;
if (startIndex === length) return;
for (let i = startIndex; i < length; i++) {
if (i > startIndex && nums[i] === nums[i - 1]) continue;
route.push(nums[i]);
backTraking(nums, i + 1, route);
route.pop();
}
}
};
```
### C
```c
@ -387,7 +409,7 @@ int** subsetsWithDup(int* nums, int numsSize, int* returnSize, int** returnColum
}
```
## Swift
### Swift
```swift
func subsetsWithDup(_ nums: [Int]) -> [[Int]] {

View File

@ -455,6 +455,45 @@ var restoreIpAddresses = function(s) {
};
```
## TypeScript
```typescript
function isValidIpSegment(str: string): boolean {
let resBool: boolean = true;
let tempVal: number = Number(str);
if (
str.length === 0 || isNaN(tempVal) ||
tempVal > 255 || tempVal < 0 ||
(str.length > 1 && str[0] === '0')
) {
resBool = false;
}
return resBool;
}
function restoreIpAddresses(s: string): string[] {
const resArr: string[] = [];
backTracking(s, 0, []);
return resArr;
function backTracking(s: string, startIndex: number, route: string[]): void {
let length: number = s.length;
if (route.length === 4 && startIndex >= length) {
resArr.push(route.join('.'));
return;
}
if (route.length === 4 || startIndex >= length) return;
let tempStr: string = '';
for (let i = startIndex + 1; i <= Math.min(length, startIndex + 3); i++) {
tempStr = s.slice(startIndex, i);
if (isValidIpSegment(tempStr)) {
route.push(s.slice(startIndex, i));
backTracking(s, i, route);
route.pop();
}
}
}
};
```
## Go
回溯(对于前导 0的IP特别注意s[startIndex]=='0'的判断不应该写成s[startIndex]==0因为s截取出来不是数字

View File

@ -408,7 +408,28 @@ class Solution:
return True
```
## Go
```python
# 遵循Carl的写法只添加了节点判断的部分
class Solution:
def isValidBST(self, root: TreeNode) -> bool:
# method 2
que, pre = [], None
while root or que:
while root:
que.append(root)
root = root.left
root = que.pop()
# 对第一个节点只做记录,对后面的节点进行比较
if pre is None:
pre = root.val
else:
if pre >= root.val: return False
pre = root.val
root = root.right
return True
```
## Go
```Go
import "math"

View File

@ -437,41 +437,6 @@ class Solution:
return True
```
层序遍历
```python
class Solution:
def isSymmetric(self, root: TreeNode) -> bool:
if not root: return True
que, cnt = [[root.left, root.right]], 1
while que:
nodes, tmp, sign = que.pop(), [], False
for node in nodes:
if not node:
tmp.append(None)
tmp.append(None)
else:
if node.left:
tmp.append(node.left)
sign = True
else:
tmp.append(None)
if node.right:
tmp.append(node.right)
sign = True
else:
tmp.append(None)
p1, p2 = 0, len(nodes) - 1
while p1 < p2:
if (not nodes[p1] and nodes[p2]) or (nodes[p1] and not nodes[p2]): return False
elif nodes[p1] and nodes[p2] and nodes[p1].val != nodes[p2].val: return False
p1 += 1
p2 -= 1
if sign: que.append(tmp)
cnt += 1
return True
```
## Go
```go

View File

@ -790,7 +790,7 @@ func findRootIndex(target int,inorder []int) int{
```javascript
var buildTree = function(inorder, postorder) {
if (!preorder.length) return null;
if (!inorder.length) return null;
const rootVal = postorder.pop(); // 从后序遍历的数组中获取中间节点的值, 即数组最后一个值
let rootIndex = inorder.indexOf(rootVal); // 获取中间节点在中序遍历中的下标
const root = new TreeNode(rootVal); // 创建中间节点

View File

@ -355,6 +355,7 @@ func sortedArrayToBST(nums []int) *TreeNode {
```
## JavaScript
递归
```javascript
var sortedArrayToBST = function (nums) {
@ -372,7 +373,44 @@ var sortedArrayToBST = function (nums) {
return buildTree(nums, 0, nums.length - 1);
};
```
迭代
```JavaScript
var sortedArrayToBST = function(nums) {
if(nums.length===0){
return null;
}
let root=new TreeNode(0); //初始根节点
let nodeQue=[root]; //放遍历的节点,并初始化
let leftQue=[0]; //放左区间的下标,初始化
let rightQue=[nums.length-1]; // 放右区间的下标
while(nodeQue.length){
let curNode=nodeQue.pop();
let left=leftQue.pop();
let right=rightQue.pop();
let mid=left+Math.floor((right-left)/2);
curNode.val=nums[mid]; //将下标为mid的元素给中间节点
// 处理左区间
if(left<=mid-1){
curNode.left=new TreeNode(0);
nodeQue.push(curNode.left);
leftQue.push(left);
rightQue.push(mid-1);
}
// 处理右区间
if(right>=mid+1){
curNode.right=new TreeNode(0);
nodeQue.push(curNode.right);
leftQue.push(mid+1);
rightQue.push(right);
}
}
return root;
};
```
## TypeScript
```typescript

View File

@ -450,6 +450,38 @@ var partition = function(s) {
};
```
## TypeScript
```typescript
function partition(s: string): string[][] {
function isPalindromeStr(s: string, left: number, right: number): boolean {
while (left < right) {
if (s[left++] !== s[right--]) {
return false;
}
}
return true;
}
function backTracking(s: string, startIndex: number, route: string[]): void {
let length: number = s.length;
if (length === startIndex) {
resArr.push(route.slice());
return;
}
for (let i = startIndex; i < length; i++) {
if (isPalindromeStr(s, startIndex, i)) {
route.push(s.slice(startIndex, i + 1));
backTracking(s, i + 1, route);
route.pop();
}
}
}
const resArr: string[][] = [];
backTracking(s, 0, []);
return resArr;
};
```
## C
```c

View File

@ -315,5 +315,75 @@ class Solution {
}
```
C:
```C
typedef struct HashNodeTag {
int key; /* num */
struct HashNodeTag *next;
}HashNode;
/* Calcualte the hash key */
static inline int hash(int key, int size) {
int index = key % size;
return (index > 0) ? (index) : (-index);
}
/* Calculate the sum of the squares of its digits*/
static inline int calcSquareSum(int num) {
unsigned int sum = 0;
while(num > 0) {
sum += (num % 10) * (num % 10);
num = num/10;
}
return sum;
}
#define HASH_TABLE_SIZE (32)
bool isHappy(int n){
int sum = n;
int index = 0;
bool bHappy = false;
bool bExit = false;
/* allocate the memory for hash table with chaining method*/
HashNode ** hashTable = (HashNode **)calloc(HASH_TABLE_SIZE, sizeof(HashNode));
while(bExit == false) {
/* check if n has been calculated */
index = hash(n, HASH_TABLE_SIZE);
HashNode ** p = hashTable + index;
while((*p) && (bExit == false)) {
/* Check if this num was calculated, if yes, this will be endless loop */
if((*p)->key == n) {
bHappy = false;
bExit = true;
}
/* move to next node of the same index */
p = &((*p)->next);
}
/* put n intot hash table */
HashNode * newNode = (HashNode *)malloc(sizeof(HashNode));
newNode->key = n;
newNode->next = NULL;
*p = newNode;
sum = calcSquareSum(n);
if(sum == 1) {
bHappy = true;
bExit = true;
}
else {
n = sum;
}
}
return bHappy;
}
```
-----------------------
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>

View File

@ -448,6 +448,50 @@ var findItinerary = function(tickets) {
```
### TypeScript
```typescript
function findItinerary(tickets: string[][]): string[] {
/**
TicketsMap 实例:
{ NRT: Map(1) { 'JFK' => 1 }, JFK: Map(2) { 'KUL' => 1, 'NRT' => 1 } }
这里选择Map数据结构的原因是与Object类型的一个主要差异是Map实例会维护键值对的插入顺序。
*/
type TicketsMap = {
[index: string]: Map<string, number>
};
tickets.sort((a, b) => {
return a[1] < b[1] ? -1 : 1;
});
const ticketMap: TicketsMap = {};
for (const [from, to] of tickets) {
if (ticketMap[from] === undefined) {
ticketMap[from] = new Map();
}
ticketMap[from].set(to, (ticketMap[from].get(to) || 0) + 1);
}
const resRoute = ['JFK'];
backTracking(tickets.length, ticketMap, resRoute);
return resRoute;
function backTracking(ticketNum: number, ticketMap: TicketsMap, route: string[]): boolean {
if (route.length === ticketNum + 1) return true;
const targetMap = ticketMap[route[route.length - 1]];
if (targetMap !== undefined) {
for (const [to, count] of targetMap.entries()) {
if (count > 0) {
route.push(to);
targetMap.set(to, count - 1);
if (backTracking(ticketNum, ticketMap, route) === true) return true;
targetMap.set(to, count);
route.pop();
}
}
}
return false;
}
};
```
### Swift
直接迭代tickets数组

View File

@ -281,6 +281,38 @@ impl Solution {
}
}
```
C:
```C
int* intersection1(int* nums1, int nums1Size, int* nums2, int nums2Size, int* returnSize){
int nums1Cnt[1000] = {0};
int lessSize = nums1Size < nums2Size ? nums1Size : nums2Size;
int * result = (int *) calloc(lessSize, sizeof(int));
int resultIndex = 0;
int* tempNums;
int i;
/* Calculate the number's counts for nums1 array */
for(i = 0; i < nums1Size; i ++) {
nums1Cnt[nums1[i]]++;
}
/* Check if the value in nums2 is existing in nums1 count array */
for(i = 0; i < nums2Size; i ++) {
if(nums1Cnt[nums2[i]] > 0) {
result[resultIndex] = nums2[i];
resultIndex ++;
/* Clear this count to avoid duplicated value */
nums1Cnt[nums2[i]] = 0;
}
}
* returnSize = resultIndex;
return result;
}
```
## 相关题目
* 350.两个数组的交集 II

View File

@ -208,6 +208,75 @@ class Solution {
}
```
```java
public class Solution {
public static void main(String[] args) {
int num[] = {1,5,11,5};
canPartition(num);
}
public static boolean canPartition(int[] nums) {
int len = nums.length;
// 题目已经说非空数组,可以不做非空判断
int sum = 0;
for (int num : nums) {
sum += num;
}
// 特判:如果是奇数,就不符合要求
if ((sum %2 ) != 0) {
return false;
}
int target = sum / 2; //目标背包容量
// 创建二维状态数组,行:物品索引,列:容量(包括 0
/*
dp[i][j]表示从数组的 [0, i] 这个子区间内挑选一些正整数
每个数只能用一次,使得这些数的和恰好等于 j。
*/
boolean[][] dp = new boolean[len][target + 1];
// 先填表格第 0 行,第 1 个数只能让容积为它自己的背包恰好装满 这里的dp[][]数组的含义就是“恰好”,所以就算容积比它大的也不要)
if (nums[0] <= target) {
dp[0][nums[0]] = true;
}
// 再填表格后面几行
//外层遍历物品
for (int i = 1; i < len; i++) {
//内层遍历背包
for (int j = 0; j <= target; j++) {
// 直接从上一行先把结果抄下来,然后再修正
dp[i][j] = dp[i - 1][j];
//如果某个物品单独的重量恰好就等于背包的重量那么也是满足dp数组的定义的
if (nums[i] == j) {
dp[i][j] = true;
continue;
}
//如果某个物品的重量小于j那就可以看该物品是否放入背包
//dp[i - 1][j]表示该物品不放入背包,如果在 [0, i - 1] 这个子区间内已经有一部分元素,使得它们的和为 j ,那么 dp[i][j] = true
//dp[i - 1][j - nums[i]]表示该物品放入背包。如果在 [0, i - 1] 这个子区间内就得找到一部分元素,使得它们的和为 j - nums[i]。
if (nums[i] < j) {
dp[i][j] = dp[i - 1][j] || dp[i - 1][j - nums[i]];
}
}
}
for (int i = 0; i < len; i++) {
for (int j = 0; j <= target; j++) {
System.out.print(dp[i][j]+" ");
}
System.out.println();
}
return dp[len - 1][target];
}
}
//dp数组的打印结果
false true false false false false false false false false false false
false true false false false true true false false false false false
false true false false false true true false false false false true
false true false false false true true false false false true true
```
二维数组版本(易于理解):
```Java
class Solution {

View File

@ -396,7 +396,35 @@ var findSubsequences = function(nums) {
```
## TypeScript
```typescript
function findSubsequences(nums: number[]): number[][] {
const resArr: number[][] = [];
backTracking(nums, 0, []);
return resArr;
function backTracking(nums: number[], startIndex: number, route: number[]): void {
let length: number = nums.length;
if (route.length >= 2) {
resArr.push(route.slice());
}
const usedSet: Set<number> = new Set();
for (let i = startIndex; i < length; i++) {
if (
nums[i] < route[route.length - 1] ||
usedSet.has(nums[i])
) continue;
usedSet.add(nums[i]);
route.push(nums[i]);
backTracking(nums, i + 1, route);
route.pop();
}
}
};
```
### C
```c
int* path;
int pathTop;

View File

@ -277,7 +277,30 @@ int fib(int n){
return fib(n-1) + fib(n-2);
}
```
### Rust
动态规划:
```Rust
pub fn fib(n: i32) -> i32 {
let n = n as usize;
let mut dp = vec![0; 31];
dp[1] = 1;
for i in 2..=n {
dp[i] = dp[i - 1] + dp[i - 2];
}
dp[n]
}
```
递归实现:
```Rust
pub fn fib(n: i32) -> i32 {
//若n小于等于1返回n
f n <= 1 {
return n;
}
//否则返回fib(n-1) + fib(n-2)
return fib(n - 1) + fib(n - 2);
}
```
-----------------------
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>

View File

@ -276,7 +276,7 @@ func search(nums []int, target int) int {
```
**JavaScript:**
(版本一)左闭右闭区间
(版本一)左闭右闭区间 [left, right]
```js
/**
@ -285,10 +285,12 @@ func search(nums []int, target int) int {
* @return {number}
*/
var search = function(nums, target) {
// right是数组最后一个数的下标num[right]在查找范围内,是左闭右闭区间
let left = 0, right = nums.length - 1;
// 使用左闭右闭区间
// 当left=right时由于nums[right]在查找范围内,所以要包括此情况
while (left <= right) {
let mid = left + Math.floor((right - left)/2);
// 如果中间数大于目标值要把中间数排除查找范围所以右边界更新为mid-1如果右边界更新为mid那中间数还在下次查找范围内
if (nums[mid] > target) {
right = mid - 1; // 去左面闭区间寻找
} else if (nums[mid] < target) {
@ -300,7 +302,7 @@ var search = function(nums, target) {
return -1;
};
```
(版本二)左闭右开区间
(版本二)左闭右开区间 [left, right)
```js
/**
@ -309,10 +311,13 @@ var search = function(nums, target) {
* @return {number}
*/
var search = function(nums, target) {
let left = 0, right = nums.length;
// 使用左闭右开区间 [left, right)
// right是数组最后一个数的下标+1nums[right]不在查找范围内,是左闭右开区间
let left = 0, right = nums.length;
// 当left=right时由于nums[right]不在查找范围,所以不必包括此情况
while (left < right) {
let mid = left + Math.floor((right - left)/2);
// 如果中间值大于目标值,中间值不应在下次查找的范围内,但中间值的前一个值应在;
// 由于right本来就不在查找范围内所以将右边界更新为中间值如果更新右边界为mid-1则将中间值的前一个值也踢出了下次寻找范围
if (nums[mid] > target) {
right = mid; // 去左区间寻找
} else if (nums[mid] < target) {

View File

@ -185,6 +185,36 @@ class Solution {
}
```
双指针:
```java
class Solution {
public static boolean backspaceCompare(String s, String t) {
char[] sarray = s.toCharArray();
char[] tarray = t.toCharArray();
return generate(sarray).equals(generate(tarray));
}
public static String generate(char[] a){
int slow = -1;
int fast = 0;
if(a.length == 1){
return new String(a);
} else{
for(fast = 0; fast < a.length; fast++){
if(a[fast] != '#')
a[++slow] = a[fast];
else{
if(slow >= 0)
slow--;
}
}
return new String(a,0,slow + 1);
}
}
}
```
### python

View File

@ -76,7 +76,7 @@
* 空间复杂度:$O(n)$递归深度为n所以系统栈所用空间为$O(n)$每一层递归所用的空间都是常数级别注意代码里的result和path都是全局变量就算是放在参数里传的也是引用并不会新申请内存空间最终空间复杂度为$O(n)$。
排列问题分析:
* 时间复杂度:$O(n!)$这个可以从排列的树形图中很明显发现每一层节点为n第二层每一个分支都延伸了n-1个分支再往下又是n-2个分支所以一直到叶子节点一共就是 n * n-1 * n-2 * ..... 1 = n!。
* 时间复杂度:$O(n!)$这个可以从排列的树形图中很明显发现每一层节点为n第二层每一个分支都延伸了n-1个分支再往下又是n-2个分支所以一直到叶子节点一共就是 n * n-1 * n-2 * ..... 1 = n!。每个叶子节点都会有一个构造全排列填进数组的操作(对应的代码:`result.push_back(path)`),该操作的复杂度为$O(n)$。所以最终时间复杂度为n * n!,简化为$O(n!)$。
* 空间复杂度:$O(n)$,和子集问题同理。
组合问题分析:

View File

@ -365,6 +365,87 @@ class Solution:
return res
```
TypeScript
**90.子集II**
```typescript
function subsetsWithDup(nums: number[]): number[][] {
nums.sort((a, b) => a - b);
const resArr: number[][] = [];
backTraking(nums, 0, []);
return resArr;
function backTraking(nums: number[], startIndex: number, route: number[]): void {
resArr.push(route.slice());
const helperSet: Set<number> = new Set();
for (let i = startIndex, length = nums.length; i < length; i++) {
if (helperSet.has(nums[i])) continue;
helperSet.add(nums[i]);
route.push(nums[i]);
backTraking(nums, i + 1, route);
route.pop();
}
}
};
```
**40. 组合总和 II**
```typescript
function combinationSum2(candidates: number[], target: number): number[][] {
candidates.sort((a, b) => a - b);
const resArr: number[][] = [];
backTracking(candidates, target, 0, 0, []);
return resArr;
function backTracking(
candidates: number[], target: number,
curSum: number, startIndex: number, route: number[]
) {
if (curSum > target) return;
if (curSum === target) {
resArr.push(route.slice());
return;
}
const helperSet: Set<number> = new Set();
for (let i = startIndex, length = candidates.length; i < length; i++) {
let tempVal: number = candidates[i];
if (helperSet.has(tempVal)) continue;
helperSet.add(tempVal);
route.push(tempVal);
backTracking(candidates, target, curSum + tempVal, i + 1, route);
route.pop();
}
}
};
```
**47. 全排列 II**
```typescript
function permuteUnique(nums: number[]): number[][] {
const resArr: number[][] = [];
const usedArr: boolean[] = [];
backTracking(nums, []);
return resArr;
function backTracking(nums: number[], route: number[]): void {
if (nums.length === route.length) {
resArr.push(route.slice());
return;
}
const usedSet: Set<number> = new Set();
for (let i = 0, length = nums.length; i < length; i++) {
if (usedArr[i] === true || usedSet.has(nums[i])) continue;
usedSet.add(nums[i]);
route.push(nums[i]);
usedArr[i] = true;
backTracking(nums, route);
usedArr[i] = false;
route.pop();
}
}
};
```
Go