mirror of
https://github.com/youngyangyang04/leetcode-master.git
synced 2025-07-10 20:40:39 +08:00
Merge branch 'youngyangyang04:master' into master
This commit is contained in:
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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]] {
|
||||
|
@ -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截取出来不是数字))
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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); // 创建中间节点
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
@ -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数组:
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
@ -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>
|
||||
|
@ -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是数组最后一个数的下标+1,nums[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) {
|
||||
|
@ -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
|
||||
|
||||
|
@ -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)$,和子集问题同理。
|
||||
|
||||
组合问题分析:
|
||||
|
@ -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:
|
||||
|
||||
|
Reference in New Issue
Block a user