Skip to content

Commit

Permalink
[javascript]
Browse files Browse the repository at this point in the history
  • Loading branch information
brucecat committed Mar 20, 2021
1 parent ebe8d71 commit 7f7094d
Show file tree
Hide file tree
Showing 56 changed files with 6,532 additions and 223 deletions.
147 changes: 117 additions & 30 deletions 动态规划系列/动态规划之KMP字符匹配算法.md
Original file line number Diff line number Diff line change
Expand Up @@ -430,41 +430,128 @@ KMP 算法也就是动态规划那点事,我们的公众号文章目录有一
<p align='center'>
<img src="../pictures/qrcode.jpg" width=200 >
</p>

======其他语言代码======

[28.实现 strStr()](https://leetcode-cn.com/problems/implement-strstr)

### python

[MoguCloud](https://github.com/MoguCloud) 提供 实现 strStr() 的 Python 完整代码:
```py

```python
class Solution:
def strStr(self, haystack: str, needle: str) -> int:
# 边界条件判断
if not needle:
return 0
pat = needle
txt = haystack

M = len(pat)
# dp[状态][字符] = 下个状态
dp = [[0 for _ in range(256)] for _ in pat]
# base case
dp[0][ord(pat[0])] = 1
# 影子状态 X 初始化为 0
X = 0
for j in range(1, M):
for c in range(256):
dp[j][c] = dp[X][c]
dp[j][ord(pat[j])] = j + 1
# 更新影子状态
X = dp[X][ord(pat[j])]
def strStr(self, haystack: str, needle: str) -> int:
# 边界条件判断
if not needle:
return 0
pat = needle
txt = haystack

M = len(pat)
# dp[状态][字符] = 下个状态
dp = [[0 for _ in range(256)] for _ in pat]
# base case
dp[0][ord(pat[0])] = 1
# 影子状态 X 初始化为 0
X = 0
for j in range(1, M):
for c in range(256):
dp[j][c] = dp[X][c]
dp[j][ord(pat[j])] = j + 1
# 更新影子状态
X = dp[X][ord(pat[j])]

N = len(txt)
# pat 初始状态为 0
j = 0
for i in range(N):
# 计算 pat 的下一个状态
j = dp[j][ord(txt[i])]
# 到达终止态,返回结果
if j == M:
return i - M + 1
# 没到达终止态,匹配失败
return -1
# 计算 pat 的下一个状态
j = dp[j][ord(txt[i])]
# 到达终止态,返回结果
if j == M:
return i - M + 1
# 没到达终止态,匹配失败
return -1
```



### javascript

```js
class KMP {
constructor(pat) {
this.pat = pat;
let m = pat.length;

// dp[状态][字符] = 下个状态 初始化一个m*256的整数矩阵
this.dp = new Array(m);
for (let i = 0; i < m; i++) {
this.dp[i] = new Array(256);
this.dp[i].fill(0, 0, 256);
}

// base case
this.dp[0][this.pat[0].charCodeAt()] = 1;

// 影子状态X 初始为0
let x = 0;

// 构建状态转移图
for (let j = 1; j < m; j++) {
for (let c = 0; c < 256; c++) {
this.dp[j][c] = this.dp[x][c];
}

// dp[][对应的ASCII码]
this.dp[j][this.pat[j].charCodeAt()] = j + 1;

// 更新影子状态
x = this.dp[x][this.pat[j].charCodeAt()]
}
}

search(txt) {

let m = this.pat.length;
let n = txt.length;

// pat的初始态为0
let j = 0;
for (let i = 0; i < n; i++) {
// 计算pat的下一个状态
j = this.dp[j][txt[i].charCodeAt()];

// 到达终止态 返回结果
if (j === m) return i - m + 1;
}

// 没到终止态 匹配失败
return -1;
}

}

/**
* @param {string} haystack
* @param {string} needle
* @return {number}
*/
var strStr = function(haystack, needle) {
if(haystack === ""){
if(needle !== ""){
return -1;
}
return 0;
}

if(needle === ""){
return 0;
}
let kmp = new KMP(needle);
return kmp.search(haystack)
};
```



120 changes: 113 additions & 7 deletions 动态规划系列/动态规划之博弈问题.md
Original file line number Diff line number Diff line change
Expand Up @@ -214,14 +214,9 @@ int stoneGame(int[] piles) {
<p align='center'>
<img src="../pictures/qrcode.jpg" width=200 >
</p>

======其他语言代码======





* python3版本
### python

由[SCUHZS](https://github.com/brucecat)提供

Expand Down Expand Up @@ -287,7 +282,9 @@ class Solution:

```

* C++ 版本


### C++ 版本

由 [TCeason](https://github.com/TCeason) 提供

Expand Down Expand Up @@ -328,3 +325,112 @@ public:

```



### javascript

由[SCUHZS](https://github.com/brucecat)提供

**1、暴力递归解**

```js
/**
* 返回[i,j]上先手所能取得的最优决策的值
* @param piles
* @param i
* @param j
* @return {number|*}
*/
var f=function(piles,i,j) {
if(i===j){ //如果i===j,只有一个元素,那么先手只能选它
return piles[i]
}
//否则 有2种情况:
//1 先选i,之后在[i+1,j]上后手进行最优选择
//2 先选j,之后在[i,j-1]上后手进行最优选择
return Math.max(piles[i]+s(i+1,j),piles[j]+s(i,j-1))
}
/**
*返回[i,j]上后手所能取得的最优决策的值
* @param piles
* @param i
* @param j
* @return {number}
*/
var s=function(piles,i,j) {
if(i===j){ //如果i===j,只有一个元素,那么后手没有选,只能为0
return 0
}
//对于这种双方都是绝顶聪明的人,数据一开始对于双方都是可见的,那么数据一确定,先后手一确定,那么结果就已经确定了
//先手选的人会把最优解选了,那么剩给后手的只有最差的情况
//所以后手的人虽然能从剩下的之中进行最优决策,但结果确是命中注定的了,只能是最差的
//所以返回[i+1,j] [i,j-1]上进行最优选择的最小值
//这也说明了先手的人在大概率下会赢得游戏(在某些情况下先手必赢,比如本题的情况:具体分析看官方解析)
return Math.min(f(i+1,j),f(i,j-1))
}
/**
*
* @param piles
* @return {boolean}
*/
var stoneGame = function(piles) {
return f(0,piles.length-1)>s(0,piles.length-1) //亚历克斯先选和李后选得到的最大值做比较
};
```

**2、动态规划dp做法**

这里采取的是三维的做法

```js
var stoneGame = function (piles) {
let n = piles.length;

// 初始化一个n*n的矩阵 dp数组
let dp = []
for (let i = 0; i < n; i++) {
dp[i] = []
}

// 在三角区域填充
for (let i = 0; i < n; i++) {
for (let j = i; j < n; j++) {
dp[i][j] = [0, 0]
}
}


// 填入base case
for (let i = 0; i < n; i++) {
dp[i][i][0] = piles[i];
dp[i][i][1] = 0;
}

// 斜着遍历数组
for (let l = 2; l <= n; l++) {
for (let i = 0; i <= n - 1; i++) {
let j = l + i - 1;

// 先手选择最左边或最右边的分数
let left = piles[i] + dp[i + 1][j][1];
let right = piles[j] + dp[i][j - 1][1];

// 套用状态转移方程
if (left > right) {
dp[i][j][0] = left;
dp[i][j][1] = dp[i + 1][j][0];
} else {
dp[i][j][0] = right;
dp[i][j][1] = dp[i][j - 1][0];
}
}
}

let res = dp[0][n - 1];
return res[0] - res[1]
};
```



###
60 changes: 58 additions & 2 deletions 动态规划系列/动态规划之四键键盘.md
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ dp[i] = dp[i - 1] + 1;
但是,如果要按 `C-V`,还要考虑之前是在哪里 `C-A C-C` 的。

**刚才说了,最优的操作序列一定是 `C-A C-C` 接着若干 `C-V`,所以我们用一个变量 `j` 作为若干 `C-V` 的起点**。那么 `j` 之前的 2 个操作就应该是 `C-A C-C` 了:

```java
public int maxA(int N) {
int[] dp = new int[N + 1];
Expand Down Expand Up @@ -200,4 +200,60 @@ def dp(n, a_num, copy):
<img src="../pictures/qrcode.jpg" width=200 >
</p>

======其他语言代码======
======其他语言代码======

### javascript

[651.四键键盘](https://leetcode-cn.com/problems/4-keys-keyboard)

**1、第一种思路**

```js
let maxA = function (N) {
// 备忘录
let memo = {}

let dp = function (n, a_num, copy) {
if (n <= 0) {
return a_num;
}

let key = n + ',' + a_num + ',' + copy
// 避免计算重叠子问题
if (memo[key] !== undefined) {
return memo[key]
}

memo[key] = Math.max(
dp(n - 1, a_num + 1, copy), // A
dp(n - 1, a_num + copy, copy), // C-V
dp(n - 2, a_num, a_num) // C-A C-C
)

return memo[key]
}

return dp(N, 0, 0)
}
```

**2、第二种思路**

```js
var maxA = function (N) {
let dp = new Array(N + 1);
dp[0] = 0;
for (let i = 1; i <= N; i++) {
// 按A键盘
dp[i] = dp[i - 1] + 1;
for (let j = 2; j < i; j++) {
// 全选 & 复制 dp[j-2],连续粘贴 i - j 次
// 屏幕上共 dp[j - 2] * (i - j + 1) 个 A
dp[i] = Math.max(dp[i], dp[j - 2] * (i - (j - 2) - 1));
}
}
// N 次按键之后最多有几个 A?
return dp[N];
}
```

Loading

0 comments on commit 7f7094d

Please sign in to comment.