Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add solutions to lc problems: No.2156,3109 #2568

Merged
merged 3 commits into from
Apr 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -364,8 +364,8 @@ function findAnagrams(s: string, p: string): number[] {
if (m < n) {
return ans;
}
const cnt1: number[] = new Array(26).fill(0);
const cnt2: number[] = new Array(26).fill(0);
const cnt1: number[] = Array(26).fill(0);
const cnt2: number[] = Array(26).fill(0);
const idx = (c: string) => c.charCodeAt(0) - 'a'.charCodeAt(0);
for (const c of p) {
++cnt1[idx(c)];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -348,8 +348,8 @@ function findAnagrams(s: string, p: string): number[] {
if (m < n) {
return ans;
}
const cnt1: number[] = new Array(26).fill(0);
const cnt2: number[] = new Array(26).fill(0);
const cnt1: number[] = Array(26).fill(0);
const cnt2: number[] = Array(26).fill(0);
const idx = (c: string) => c.charCodeAt(0) - 'a'.charCodeAt(0);
for (const c of p) {
++cnt1[idx(c)];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ function findAnagrams(s: string, p: string): number[] {
if (m < n) {
return ans;
}
const cnt1: number[] = new Array(26).fill(0);
const cnt2: number[] = new Array(26).fill(0);
const cnt1: number[] = Array(26).fill(0);
const cnt2: number[] = Array(26).fill(0);
const idx = (c: string) => c.charCodeAt(0) - 'a'.charCodeAt(0);
for (const c of p) {
++cnt1[idx(c)];
Expand Down
2 changes: 1 addition & 1 deletion solution/1700-1799/1766.Tree of Coprimes/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@

接下来我们可以使用回溯的方法,从根节点开始遍历整棵树,对于每个节点 $i$,我们可以通过 $f$ 数组得到 $nums[i]$ 的所有互质数。然后我们枚举 $nums[i]$ 的所有互质数,找到已经出现过的且深度最大的祖先节点 $t$,即为 $i$ 的最近的互质祖先节点。这里我们可以用一个长度为 $51$ 的栈数组 $stks$ 来获取每个出现过的值 $v$ 的节点以及其深度。每个栈 $stks[v]$ 的栈顶元素就是最近的深度最大的祖先节点。

时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为节点个数。
时间复杂度 $O(n \times M)$,空间复杂度 $O(M^2 + n)$。其中 $n$ 为节点个数,而 $M$ 为 $nums[i]$ 的最大值,本题中 $M = 50$

<!-- tabs:start -->

Expand Down
8 changes: 7 additions & 1 deletion solution/1700-1799/1766.Tree of Coprimes/README_EN.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,13 @@

## Solutions

### Solution 1
### Solution 1: Preprocessing + Enumeration + Stack + Backtracking

Since the range of $nums[i]$ in the problem is $[1, 50]$, we can preprocess all the coprime numbers for each number and record them in the array $f$, where $f[i]$ represents all the coprime numbers of $i$.

Next, we can use a backtracking method to traverse the entire tree from the root node. For each node $i$, we can get all the coprime numbers of $nums[i]$ through the array $f$. Then we enumerate all the coprime numbers of $nums[i]$, find the ancestor node $t$ that has appeared and has the maximum depth, which is the nearest coprime ancestor node of $i$. Here we can use a stack array $stks$ of length $51$ to get each appeared value $v$ and its depth. The top element of each stack $stks[v]$ is the nearest ancestor node with the maximum depth.

The time complexity is $O(n \times M)$, and the space complexity is $O(M^2 + n)$. Where $n$ is the number of nodes, and $M$ is the maximum value of $nums[i]$, in this problem $M = 50$.

<!-- tabs:start -->

Expand Down
181 changes: 157 additions & 24 deletions solution/2100-2199/2156.Find Substring With Given Hash Value/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,149 @@

## 解法

### 方法一
### 方法一:滑动窗口 + 倒序遍历

我们可以维护一个长度为 $k$ 的滑动窗口,用来计算子串的哈希值。考虑到如果正序遍历字符串,在哈希值的计算中,涉及到除法取模的操作,处理起来比较麻烦。因此我们可以倒序遍历字符串,这样在计算哈希值的时候,只需要乘法和取模操作。

我们首先计算字符串末尾的 $k$ 个字符的哈希值,然后从字符串末尾开始倒序遍历,每次计算当前窗口的哈希值,如果等于给定的哈希值,我们就找到了一个满足条件的子串,更新答案字符串的起始位置。

最后返回答案字符串即可。

时间复杂度 $O(n)$,其中 $n$ 是字符串的长度。空间复杂度 $O(1)$。

<!-- tabs:start -->

```python
class Solution:
def subStrHash(
self, s: str, power: int, modulo: int, k: int, hashValue: int
) -> str:
h, n = 0, len(s)
p = 1
for i in range(n - 1, n - 1 - k, -1):
val = ord(s[i]) - ord("a") + 1
h = ((h * power) + val) % modulo
if i != n - k:
p = p * power % modulo
j = n - k
for i in range(n - 1 - k, -1, -1):
pre = ord(s[i + k]) - ord("a") + 1
cur = ord(s[i]) - ord("a") + 1
h = ((h - pre * p) * power + cur) % modulo
if h == hashValue:
j = i
return s[j : j + k]
```

```java
class Solution {
public String subStrHash(String s, int power, int modulo, int k, int hashValue) {
long h = 0, p = 1;
int n = s.length();
for (int i = n - 1; i >= n - k; --i) {
int val = s.charAt(i) - 'a' + 1;
h = ((h * power % modulo) + val) % modulo;
if (i != n - k) {
p = p * power % modulo;
}
}
int j = n - k;
for (int i = n - k - 1; i >= 0; --i) {
int pre = s.charAt(i + k) - 'a' + 1;
int cur = s.charAt(i) - 'a' + 1;
h = ((h - pre * p % modulo + modulo) * power % modulo + cur) % modulo;
if (h == hashValue) {
j = i;
}
}
return s.substring(j, j + k);
}
}
```

```cpp
class Solution {
public:
string subStrHash(string s, int power, int modulo, int k, int hashValue) {
long long h = 0, p = 1;
int n = s.size();
for (int i = n - 1; i >= n - k; --i) {
int val = s[i] - 'a' + 1;
h = ((h * power % modulo) + val) % modulo;
if (i != n - k) {
p = p * power % modulo;
}
}
int j = n - k;
for (int i = n - k - 1; i >= 0; --i) {
int pre = s[i + k] - 'a' + 1;
int cur = s[i] - 'a' + 1;
h = ((h - pre * p % modulo + modulo) * power % modulo + cur) % modulo;
if (h == hashValue) {
j = i;
}
}
return s.substr(j, k);
}
};
```

```go
func subStrHash(s string, power int, modulo int, k int, hashValue int) string {
h, p := 0, 1
n := len(s)
for i := n - 1; i >= n-k; i-- {
val := int(s[i] - 'a' + 1)
h = (h*power%modulo + val) % modulo
if i != n-k {
p = p * power % modulo
}
}
j := n - k
for i := n - k - 1; i >= 0; i-- {
pre := int(s[i+k] - 'a' + 1)
cur := int(s[i] - 'a' + 1)
h = ((h-pre*p%modulo+modulo)*power%modulo + cur) % modulo
if h == hashValue {
j = i
}
}
return s[j : j+k]
}
```

```ts
function subStrHash(
s: string,
power: number,
modulo: number,
k: number,
hashValue: number,
): string {
let h: bigint = BigInt(0),
p: bigint = BigInt(1);
const n: number = s.length;
const mod = BigInt(modulo);
for (let i: number = n - 1; i >= n - k; --i) {
const val: bigint = BigInt(s.charCodeAt(i) - 'a'.charCodeAt(0) + 1);
h = (((h * BigInt(power)) % mod) + val) % mod;
if (i !== n - k) {
p = (p * BigInt(power)) % mod;
}
}
let j: number = n - k;
for (let i: number = n - k - 1; i >= 0; --i) {
const pre: bigint = BigInt(s.charCodeAt(i + k) - 'a'.charCodeAt(0) + 1);
const cur: bigint = BigInt(s.charCodeAt(i) - 'a'.charCodeAt(0) + 1);
h = ((((h - ((pre * p) % mod) + mod) * BigInt(power)) % mod) + cur) % mod;
if (Number(h) === hashValue) {
j = i;
}
}
return s.substring(j, j + k);
}
```

```js
/**
* @param {string} s
Expand All @@ -70,34 +209,28 @@
* @return {string}
*/
var subStrHash = function (s, power, modulo, k, hashValue) {
power = BigInt(power);
modulo = BigInt(modulo);
hashValue = BigInt(hashValue);
let h = BigInt(0),
p = BigInt(1);
const n = s.length;
let pk = 1n;
let ac = 0n;
// 倒序滑动窗口
for (let i = n - 1; i > n - 1 - k; i--) {
ac = (ac * power + getCode(s, i)) % modulo;
pk = (pk * power) % modulo;
}
let ans = -1;
if (ac == hashValue) {
ans = n - k;
const mod = BigInt(modulo);
for (let i = n - 1; i >= n - k; --i) {
const val = BigInt(s.charCodeAt(i) - 'a'.charCodeAt(0) + 1);
h = (((h * BigInt(power)) % mod) + val) % mod;
if (i !== n - k) {
p = (p * BigInt(power)) % mod;
}
}
for (let i = n - 1 - k; i >= 0; i--) {
let pre = (getCode(s, i + k) * pk) % modulo;
ac = (ac * power + getCode(s, i) - pre + modulo) % modulo;
if (ac == hashValue) {
ans = i;
let j = n - k;
for (let i = n - k - 1; i >= 0; --i) {
const pre = BigInt(s.charCodeAt(i + k) - 'a'.charCodeAt(0) + 1);
const cur = BigInt(s.charCodeAt(i) - 'a'.charCodeAt(0) + 1);
h = ((((h - ((pre * p) % mod) + mod) * BigInt(power)) % mod) + cur) % mod;
if (Number(h) === hashValue) {
j = i;
}
}
return ans == -1 ? '' : s.substring(ans, ans + k);
return s.substring(j, j + k);
};

function getCode(str, index) {
return BigInt(str.charCodeAt(index) - 'a'.charCodeAt(0) + 1);
}
```

<!-- tabs:end -->
Expand Down
Loading
Loading