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: update solutions to lcof problems #2883

Merged
merged 1 commit into from
May 22, 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
6 changes: 5 additions & 1 deletion lcof/面试题41. 数据流中的中位数/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -418,7 +418,11 @@ public class MedianFinder {

<!-- solution:start-->

### 方法二
### 方法二:有序列表

我们也可以使用一个有序列表来维护数据流中的元素,这样我们就可以直接通过索引来获取中位数。

时间复杂度方面,添加元素的时间复杂度为 $O(\log n)$,查找中位数的时间复杂度为 $O(1)$。空间复杂度为 $O(n)$。其中 $n$ 为数据流中元素的个数。

<!-- tabs:start -->

Expand Down
2 changes: 1 addition & 1 deletion lcof/面试题42. 连续子数组的最大和/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ $$

我们可以不用开一个数组来存储所有的计算结果,而是只用两个变量 $f$ 和 $ans$ 来维护对于每一个位置 $i$ 我们的最大值,这样我们可以省去空间复杂度的开销。

时间复杂度 $O(n)$,空间复杂度 $O(1)$。其中 $n$ 为数组长度
时间复杂度 $O(n)$,其中 $n$ 为数组长度。空间复杂度 $O(1)$。

<!-- tabs:start -->

Expand Down
2 changes: 1 addition & 1 deletion lcof/面试题45. 把数组排成最小的数/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ edit_url: https://github.com/doocs/leetcode/edit/main/lcof/%E9%9D%A2%E8%AF%95%E9

### 方法一:自定义排序

将数组中的数字转换为字符串,然后按照字符串拼接的大小进行排序。具体地,比较两个字符串 $a$ 和 $b$,如果 $a + b \lt b + a$,则 $a$ 小于 $b$,否则 $a$ 大于 $b$。
我们将数组中的数字转换为字符串,然后按照字符串拼接的大小进行排序。具体地,比较两个字符串 $a$ 和 $b$,如果 $a + b \lt b + a$,则 $a$ 小于 $b$,否则 $a$ 大于 $b$。

时间复杂度 $O(n \times \log n + n \times m)$,空间复杂度 $O(n \times m)$。其中 $n $ 和 $m$ 分别为数组的长度和字符串的平均长度。

Expand Down
6 changes: 3 additions & 3 deletions lcof/面试题47. 礼物的最大价值/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,6 @@ $$

时间复杂度 $O(m \times n)$,空间复杂度 $O(m \times n)$。其中 $m$ 和 $n$ 分别为棋盘的行数和列数。

我们注意到 $f[i][j]$ 只与 $f[i-1][j]$ 和 $f[i][j-1]$ 有关,因此我们可以仅用两行数组 $f[2][n+1]$ 来存储状态,从而将空间复杂度优化到 $O(n)$。

<!-- tabs:start -->

#### Python3
Expand Down Expand Up @@ -206,7 +204,9 @@ public class Solution {

<!-- solution:start-->

### 方法二
### 方法二:动态规划(空间优化)

我们注意到 $f[i][j]$ 只与 $f[i-1][j]$ 和 $f[i][j-1]$ 有关,因此我们可以仅用两行数组 $f[2][n+1]$ 来存储状态,从而将空间复杂度优化到 $O(n)$。

<!-- tabs:start -->

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ edit_url: https://github.com/doocs/leetcode/edit/main/lcof/%E9%9D%A2%E8%AF%95%E9

我们用双指针 $j$ 和 $i$ 分别表示子串的左右边界,其中 $j$ 是滑动窗口的左边界,$i$ 是滑动窗口的右边界,用哈希表 $vis$ 记录每个字符是否出现过。

遍历字符串 $s$,如果此时 $s[i]$ 在哈希表 $vis$ 中存在,说明 $s[i]$ 重复了,我们需要将左边界 $j$ 右移,直到 $s[i]$ 不在哈希表 $vis$ 中为止,然后将 $s[i]$ 加入哈希表 $vis$ 中。此时,我们更新无重复字符子串的最大长度,即 $ans = max(ans, i - j + 1)$。
遍历字符串 $s$,如果此时 $s[i]$ 在哈希表 $vis$ 中存在,说明 $s[i]$ 重复了,我们需要将左边界 $j$ 右移,直到 $s[i]$ 不在哈希表 $vis$ 中为止,然后将 $s[i]$ 加入哈希表 $vis$ 中。此时,我们更新无重复字符子串的最大长度,即 $ans = \max(ans, i - j + 1)$。

遍历结束后,我们返回 $ans$ 即可。

Expand Down
2 changes: 1 addition & 1 deletion lcof/面试题49. 丑数/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ public class Solution {

### 方法二:动态规划

定义数组 $dp$,其中 $dp[i-1]$ 表示第 $i$ 个丑数,那么第 $n$ 个丑数就是 $dp[n - 1]$。最小的丑数是 $1$,所以 $dp[0]=1$。
我们定义数组 $dp$,其中 $dp[i-1]$ 表示第 $i$ 个丑数,那么第 $n$ 个丑数就是 $dp[n - 1]$。最小的丑数是 $1$,所以 $dp[0]=1$。

定义 $3$ 个指针 $p_2$, $p_3$ 和 $p_5$,表示下一个丑数是当前指针指向的丑数乘以对应的质因数。初始时,三个指针的值都指向 $0$。

Expand Down
23 changes: 11 additions & 12 deletions lcof/面试题50. 第一个只出现一次的字符/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ edit_url: https://github.com/doocs/leetcode/edit/main/lcof/%E9%9D%A2%E8%AF%95%E9

### 方法一:数组或哈希表

我们可以使用哈希表或数组来统计每个字符出现的次数,然后再遍历一遍字符串,找到第一个出现次数为 $1$ 的字符。
我们可以使用哈希表或数组 $cnt$ 来统计每个字符出现的次数,然后再遍历一遍字符串,找到第一个出现次数为 $1$ 的字符。

时间复杂度 $O(n)$,空间复杂度 $O(C)$。其中 $n$ 为字符串长度;而 $C$ 为字符集大小,本题中 $C=26$。

Expand Down Expand Up @@ -121,12 +121,12 @@ func firstUniqChar(s string) byte {

```ts
function firstUniqChar(s: string): string {
const map = new Map();
const cnt: number[] = Array(26).fill(0);
for (const c of s) {
map.set(c, !map.has(c));
cnt[c.charCodeAt(0) - 97]++;
}
for (const c of s) {
if (map.get(c)) {
if (cnt[c.charCodeAt(0) - 97] === 1) {
return c;
}
}
Expand All @@ -137,16 +137,15 @@ function firstUniqChar(s: string): string {
#### Rust

```rust
use std::collections::HashMap;
impl Solution {
pub fn first_uniq_char(s: String) -> char {
let mut map = HashMap::new();
for c in s.as_bytes() {
map.insert(c, !map.contains_key(c));
let mut cnt = [0; 26];
for c in s.chars() {
cnt[(c as usize) - ('a' as usize)] += 1;
}
for c in s.as_bytes() {
if map[c] {
return char::from(*c);
for c in s.chars() {
if cnt[(c as usize) - ('a' as usize)] == 1 {
return c;
}
}
' '
Expand All @@ -162,7 +161,7 @@ impl Solution {
* @return {character}
*/
var firstUniqChar = function (s) {
const cnt = new Array(26).fill(0);
const cnt = Array(26).fill(0);
for (const c of s) {
cnt[c.charCodeAt(0) - 97]++;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* @return {character}
*/
var firstUniqChar = function (s) {
const cnt = new Array(26).fill(0);
const cnt = Array(26).fill(0);
for (const c of s) {
cnt[c.charCodeAt(0) - 97]++;
}
Expand Down
13 changes: 6 additions & 7 deletions lcof/面试题50. 第一个只出现一次的字符/Solution.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
use std::collections::HashMap;
impl Solution {
pub fn first_uniq_char(s: String) -> char {
let mut map = HashMap::new();
for c in s.as_bytes() {
map.insert(c, !map.contains_key(c));
let mut cnt = [0; 26];
for c in s.chars() {
cnt[(c as usize) - ('a' as usize)] += 1;
}
for c in s.as_bytes() {
if map[c] {
return char::from(*c);
for c in s.chars() {
if cnt[(c as usize) - ('a' as usize)] == 1 {
return c;
}
}
' '
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
function firstUniqChar(s: string): string {
const map = new Map();
const cnt: number[] = Array(26).fill(0);
for (const c of s) {
map.set(c, !map.has(c));
cnt[c.charCodeAt(0) - 97]++;
}
for (const c of s) {
if (map.get(c)) {
if (cnt[c.charCodeAt(0) - 97] === 1) {
return c;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ edit_url: https://github.com/doocs/leetcode/edit/main/lcof/%E9%9D%A2%E8%AF%95%E9

我们可以用两个指针 $a$ 和 $b$ 分别指向两个链表的头节点,然后同时分别向后遍历,当 $a$ 到达链表 $A$ 的末尾时,令 $a$ 指向链表 $B$ 的头节点;当 $b$ 到达链表 $B$ 的末尾时,令 $b$ 指向链表 $A$ 的头节点。这样,当它们相遇时,所指向的节点就是第一个公共节点。

时间复杂度 $O(m + n)$,空间复杂度 $O(1)$。其中 $m$ 和 $n$ 分别为两个链表的长度。
时间复杂度 $O(m + n)$,其中 $m$ 和 $n$ 分别为两个链表的长度。空间复杂度 $O(1)$

<!-- tabs:start -->

Expand Down
12 changes: 11 additions & 1 deletion solution/0400-0499/0400.Nth Digit/README_EN.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,17 @@ tags:

<!-- solution:start -->

### Solution 1
### Solution 1: Mathematics

The smallest and largest integers with $k$ digits are $10^{k-1}$ and $10^k-1$ respectively, so the total number of digits for $k$-digit numbers is $k \times 9 \times 10^{k-1}$.

We use $k$ to represent the number of digits of the current number, and $cnt$ to represent the total number of numbers with the current number of digits. Initially, $k=1$, $cnt=9$.

Each time we subtract $cnt \times k$ from $n$, when $n$ is less than or equal to $cnt \times k$, it means that the number corresponding to $n$ is within the range of numbers with the current number of digits. At this time, we can calculate the corresponding number.

The specific method is to first calculate which number of the current number of digits corresponds to $n$, and then calculate which digit of this number it is, so as to get the number on this digit.

The time complexity is $O(\log_{10} n)$.

<!-- tabs:start -->

Expand Down
Loading