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 lcci problems #1773

Merged
merged 2 commits into from
Oct 9, 2023
Merged
Changes from 1 commit
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
Prev Previous commit
feat: add solutions to lcci problems
* No.10.11.Peaks and Valleys
* No.16.01.Swap Numbers
* No.16.02.Words Frequency
* No.16.05.Factorial Zeros
* No.16.07.Maximum
* No.16.11.Diving Board
* No.16.14.Best Line
* No.16.15.Master Mind
* No.16.16.Sub Sort
* No.16.17.Contiguous Sequence
* No.16.18.Pattern Matching
* No.16.19.Pond Sizes
* No.16.20.T9
* No.16.21.Sum Swap
* No.16.22.Langtons Ant
* No.16.24.Pairs With Sum
yanglbme committed Oct 9, 2023
commit 52e3917d638bd26d723eeaea5291c2482e518d3c
6 changes: 6 additions & 0 deletions lcci/10.11.Peaks and Valleys/README_EN.md
Original file line number Diff line number Diff line change
@@ -20,6 +20,12 @@

## Solutions

**Solution 1: Sorting**

We first sort the array, and then traverse the array and swap the elements at even indices with their next element.

The time complexity is $O(n \times \log n)$, and the space complexity is $O(\log n)$. Here, $n$ is the length of the array.

<!-- tabs:start -->

### **Python3**
20 changes: 19 additions & 1 deletion lcci/16.01.Swap Numbers/README.md
Original file line number Diff line number Diff line change
@@ -19,7 +19,25 @@

<!-- 这里可写通用的实现逻辑 -->

异或运算。
**方法一:位运算**

我们可以使用异或运算 $\oplus$ 来实现两个数的交换。

异或运算有以下三个性质。

- 任何数和 $0$ 做异或运算,结果仍然是原来的数,即 $a \oplus 0=a$。
- 任何数和其自身做异或运算,结果是 $0$,即 $a \oplus a=0$。
- 异或运算满足交换律和结合律,即 $a \oplus b \oplus a=b \oplus a \oplus a=b \oplus (a \oplus a)=b \oplus 0=b$。

因此,我们可以对 $numbers$ 中的两个数 $a$ 和 $b$ 进行如下操作:

- $a=a \oplus b$,此时 $a$ 中存储了两个数的异或结果;
- $b=a \oplus b$,此时 $b$ 中存储了原来 $a$ 的值;
- $a=a \oplus b$,此时 $a$ 中存储了原来 $b$ 的值;

这样,我们就可以实现在不使用临时变量的情况下对两个数进行交换。

时间复杂度 $O(1)$,空间复杂度 $O(1)$。

<!-- tabs:start -->

20 changes: 20 additions & 0 deletions lcci/16.01.Swap Numbers/README_EN.md
Original file line number Diff line number Diff line change
@@ -24,6 +24,26 @@

## Solutions

**Solution 1: Bitwise Operation**

We can use the XOR operation $\oplus$ to implement the swap of two numbers.

The XOR operation has the following three properties:

- Any number XORed with $0$ remains unchanged, i.e., $a \oplus 0=a$.
- Any number XORed with itself results in $0$, i.e., $a \oplus a=0$.
- The XOR operation satisfies the commutative and associative laws, i.e., $a \oplus b \oplus a=b \oplus a \oplus a=b \oplus (a \oplus a)=b \oplus 0=b$.

Therefore, we can perform the following operations on two numbers $a$ and $b$ in the array $numbers$:

- $a=a \oplus b$, now $a$ stores the XOR result of the two numbers;
- $b=a \oplus b$, now $b$ stores the original value of $a$;
- $a=a \oplus b$, now $a$ stores the original value of $b$;

In this way, we can swap two numbers without using a temporary variable.

The time complexity is $O(1)$, and the space complexity is $O(1)$.

<!-- tabs:start -->

### **Python3**
17 changes: 10 additions & 7 deletions lcci/16.02.Words Frequency/README.md
Original file line number Diff line number Diff line change
@@ -5,6 +5,7 @@
## 题目描述

<!-- 这里写题目描述 -->

<p>设计一个方法,找出任意指定单词在一本书中的出现频率。</p>
<p>你的实现应该支持如下操作:</p>
<ul>
@@ -33,9 +34,11 @@ wordsFrequency.get("pen"); //返回1

**方法一:哈希表**

我们用哈希表 `cnt` 统计每个单词出现的次数,`get` 函数直接返回 `cnt[word]` 即可。
我们用哈希表 $cnt$ 统计 $book$ 中每个单词出现的次数。

调用 `get` 函数时,我们只需要返回 $cnt$ 中对应的单词的出现次数即可。

初始化哈希表 `cnt` 的时间复杂度为 $O(n)$,其中 $n$ 为 `book` 的长度。`get` 函数的时间复杂度为 $O(1)$。空间复杂度为 $O(n)$。
时间复杂度方面,初始化哈希表 $cnt$ 的时间复杂度为 $O(n)$,其中 $n$ 为 $book$ 的长度。`get` 函数的时间复杂度为 $O(1)$。空间复杂度为 $O(n)$。

<!-- tabs:start -->

@@ -194,7 +197,7 @@ class WordsFrequency {
```rust
use std::collections::HashMap;
struct WordsFrequency {
counter: HashMap<String, i32>
cnt: HashMap<String, i32>
}


@@ -205,15 +208,15 @@ struct WordsFrequency {
impl WordsFrequency {

fn new(book: Vec<String>) -> Self {
let mut counter = HashMap::new();
let mut cnt = HashMap::new();
for word in book.into_iter() {
*counter.entry(word).or_insert(0) += 1;
*cnt.entry(word).or_insert(0) += 1;
}
Self { counter }
Self { cnt }
}

fn get(&self, word: String) -> i32 {
*self.counter.get(&word).unwrap_or(&0)
*self.cnt.get(&word).unwrap_or(&0)
}
}

18 changes: 13 additions & 5 deletions lcci/16.02.Words Frequency/README_EN.md
Original file line number Diff line number Diff line change
@@ -42,6 +42,14 @@ wordsFrequency.get(&quot;pen&quot;); //returns 1

## Solutions

**Solution 1: Hash Table**

We use a hash table $cnt$ to count the number of occurrences of each word in $book$.

When calling the `get` function, we only need to return the number of occurrences of the corresponding word in $cnt$.

In terms of time complexity, the time complexity of initializing the hash table $cnt$ is $O(n)$, where $n$ is the length of $book$. The time complexity of the `get` function is $O(1)$. The space complexity is $O(n)$.

<!-- tabs:start -->

### **Python3**
@@ -195,7 +203,7 @@ class WordsFrequency {
```rust
use std::collections::HashMap;
struct WordsFrequency {
counter: HashMap<String, i32>
cnt: HashMap<String, i32>
}


@@ -206,15 +214,15 @@ struct WordsFrequency {
impl WordsFrequency {

fn new(book: Vec<String>) -> Self {
let mut counter = HashMap::new();
let mut cnt = HashMap::new();
for word in book.into_iter() {
*counter.entry(word).or_insert(0) += 1;
*cnt.entry(word).or_insert(0) += 1;
}
Self { counter }
Self { cnt }
}

fn get(&self, word: String) -> i32 {
*self.counter.get(&word).unwrap_or(&0)
*self.cnt.get(&word).unwrap_or(&0)
}
}

22 changes: 11 additions & 11 deletions lcci/16.02.Words Frequency/Solution.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
class WordsFrequency:
def __init__(self, book: List[str]):
self.cnt = Counter(book)

def get(self, word: str) -> int:
return self.cnt[word]


# Your WordsFrequency object will be instantiated and called as such:
# obj = WordsFrequency(book)
# param_1 = obj.get(word)
class WordsFrequency:
def __init__(self, book: List[str]):
self.cnt = Counter(book)
def get(self, word: str) -> int:
return self.cnt[word]
# Your WordsFrequency object will be instantiated and called as such:
# obj = WordsFrequency(book)
# param_1 = obj.get(word)
58 changes: 29 additions & 29 deletions lcci/16.02.Words Frequency/Solution.rs
Original file line number Diff line number Diff line change
@@ -1,30 +1,30 @@
use std::collections::HashMap;
struct WordsFrequency {
counter: HashMap<String, i32>
}


/**
* `&self` means the method takes an immutable reference.
* If you need a mutable reference, change it to `&mut self` instead.
*/
impl WordsFrequency {

fn new(book: Vec<String>) -> Self {
let mut counter = HashMap::new();
for word in book.into_iter() {
*counter.entry(word).or_insert(0) += 1;
}
Self { counter }
}

fn get(&self, word: String) -> i32 {
*self.counter.get(&word).unwrap_or(&0)
}
}

/**
* Your WordsFrequency object will be instantiated and called as such:
* let obj = WordsFrequency::new(book);
* let ret_1: i32 = obj.get(word);
use std::collections::HashMap;
struct WordsFrequency {
cnt: HashMap<String, i32>
}
/**
* `&self` means the method takes an immutable reference.
* If you need a mutable reference, change it to `&mut self` instead.
*/
impl WordsFrequency {
fn new(book: Vec<String>) -> Self {
let mut cnt = HashMap::new();
for word in book.into_iter() {
*cnt.entry(word).or_insert(0) += 1;
}
Self { cnt }
}
fn get(&self, word: String) -> i32 {
*self.cnt.get(&word).unwrap_or(&0)
}
}
/**
* Your WordsFrequency object will be instantiated and called as such:
* let obj = WordsFrequency::new(book);
* let ret_1: i32 = obj.get(word);
*/
13 changes: 13 additions & 0 deletions lcci/16.05.Factorial Zeros/README_EN.md
Original file line number Diff line number Diff line change
@@ -27,6 +27,19 @@

## Solutions

**Solution 1: Mathematics**

The problem is actually asking for the number of factors of $5$ in $[1,n]$.

Let's take $130$ as an example:

1. Divide $130$ by $5$ for the first time, and get $26$, which means there are $26$ numbers containing a factor of $5$.
2. Divide $26$ by $5$ for the second time, and get $5$, which means there are $5$ numbers containing a factor of $5^2$.
3. Divide $5$ by $5$ for the third time, and get $1$, which means there is $1$ number containing a factor of $5^3$.
4. Add up all the counts to get the total number of factors of $5$ in $[1,n]$.

The time complexity is $O(\log n)$, and the space complexity is $O(1)$.

<!-- tabs:start -->

### **Python3**
8 changes: 8 additions & 0 deletions lcci/16.07.Maximum/README_EN.md
Original file line number Diff line number Diff line change
@@ -16,6 +16,14 @@

## Solutions

**Solution 1: Bitwise Operation**

We can extract the sign bit $k$ of $a-b$. If the sign bit is $1$, it means $a \lt b$; if the sign bit is $0$, it means $a \ge b$.

Then the final result is $a \times (k \oplus 1) + b \times k$.

The time complexity is $O(1)$, and the space complexity is $O(1)$.

<!-- tabs:start -->

### **Python3**
11 changes: 11 additions & 0 deletions lcci/16.11.Diving Board/README.md
Original file line number Diff line number Diff line change
@@ -5,6 +5,7 @@
## 题目描述

<!-- 这里写题目描述 -->

<p>你正在使用一堆木板建造跳水板。有两种类型的木板,其中长度较短的木板长度为<code>shorter</code>,长度较长的木板长度为<code>longer</code>。你必须正好使用<code>k</code>块木板。编写一个方法,生成跳水板所有可能的长度。</p>
<p>返回的长度需要从小到大排列。</p>
<p><strong>示例:</strong></p>
@@ -24,6 +25,16 @@ k = 3

<!-- 这里可写通用的实现逻辑 -->

**方法一:分类讨论**

如果 $k=0$,则不存在任何一种方案,我们可以直接返回空列表。

如果 $shorter=longer$,则我们只能使用长度为 $longer \times k$ 的木板,因此我们直接返回长度为 $longer \times k$ 的列表。

否则,我们可以使用长度为 $shorter \times (k-i) + longer \times i$ 的木板,其中 $0 \leq i \leq k$。我们在 $[0, k]$ 的范围内枚举 $i$,并计算对应的长度即可。对于不同的 $i$,我们不会得到相同的长度,这是因为,假如有 $0 \leq i \lt j \leq k$,那么两者长度差为 $shorter \times (k-i) + longer \times i - shorter \times (k-j) - longer \times j$,整理得到长度差 $(i - j) \times (longer - shorter) \lt 0$。因此,对于不同的 $i$,我们会得到不同的长度。

时间复杂度 $O(k)$,其中 $k$ 为木板数量。忽略答案的空间消耗,空间复杂度 $O(1)$。

<!-- tabs:start -->

### **Python3**
10 changes: 10 additions & 0 deletions lcci/16.11.Diving Board/README_EN.md
Original file line number Diff line number Diff line change
@@ -33,6 +33,16 @@ k = 3

## Solutions

**Solution 1: Case Analysis**

If $k=0$, there is no solution, and we can directly return an empty list.

If $shorter=longer$, we can only use a board with length $longer \times k$, so we directly return a list with length $longer \times k$.

Otherwise, we can use a board with length $shorter \times (k-i) + longer \times i$, where $0 \leq i \leq k$. We enumerate $i$ in the range $[0, k]$, and calculate the corresponding length. For different values of $i$, we will not get the same length, because if $0 \leq i \lt j \leq k$, then the difference in length is $(i - j) \times (longer - shorter) \lt 0$. Therefore, for different values of $i$, we will get different lengths.

The time complexity is $O(k)$, where $k$ is the number of boards. Ignoring the space consumption of the answer, the space complexity is $O(1)$.

<!-- tabs:start -->

### **Python3**
12 changes: 12 additions & 0 deletions lcci/16.14.Best Line/README_EN.md
Original file line number Diff line number Diff line change
@@ -24,6 +24,18 @@

## Solutions

**Solution 1: Brute Force**

We can enumerate any two points $(x_1, y_1), (x_2, y_2)$, connect these two points into a line, and the number of points on this line is 2. Then we enumerate other points $(x_3, y_3)$, and determine whether they are on the same line. If they are, the number of points on the line increases by 1; otherwise, the number of points on the line remains the same. Find the maximum number of points on a line, and the corresponding smallest two point indices are the answer.

The time complexity is $O(n^3)$, and the space complexity is $O(1)$. Here, $n$ is the length of the array `points`.

**Solution 2: Enumeration + Hash Table**

We can enumerate a point $(x_1, y_1)$, store the slope of the line connecting $(x_1, y_1)$ and all other points $(x_2, y_2)$ in a hash table. Points with the same slope are on the same line, and the key of the hash table is the slope, and the value is the number of points on the line. Find the maximum value in the hash table, which is the answer. To avoid precision issues, we can reduce the slope $\frac{y_2 - y_1}{x_2 - x_1}$, and the reduction method is to find the greatest common divisor, and then divide the numerator and denominator by the greatest common divisor. The resulting numerator and denominator are used as the key of the hash table.

The time complexity is $O(n^2 \times \log m)$, and the space complexity is $O(n)$. Here, $n$ and $m$ are the length of the array `points` and the maximum difference between all horizontal and vertical coordinates in the array `points`, respectively.

<!-- tabs:start -->

### **Python3**
2 changes: 1 addition & 1 deletion lcci/16.15.Master Mind/README.md
Original file line number Diff line number Diff line change
@@ -25,7 +25,7 @@

**方法一:哈希表**

同时遍历两个字符串,算出对应位置字符相同的个数,累加到 $x$ 中,然后将两个字符串出现的字符以及出现的次数分别记录在哈希表 `cnt1``cnt2` 中。
同时遍历两个字符串,算出对应位置字符相同的个数,累加到 $x$ 中,然后将两个字符串出现的字符以及出现的次数分别记录在哈希表 $cnt1$$cnt2$ 中。

接着遍历两个哈希表,算出有多少共同出现的字符,累加到 $y$ 中。那么答案就是 $[x, y - x]$。

8 changes: 8 additions & 0 deletions lcci/16.15.Master Mind/README_EN.md
Original file line number Diff line number Diff line change
@@ -28,6 +28,14 @@

## Solutions

**Solution 1: Hash Table**

We simultaneously traverse both strings, count the number of corresponding characters that are the same, and accumulate them in $x$. Then we record the characters and their frequencies in both strings in hash tables $cnt1$ and $cnt2$, respectively.

Next, we traverse both hash tables, count the number of common characters, and accumulate them in $y$. The answer is then $[x, y - x]$.

The time complexity is $O(C)$, and the space complexity is $O(C)$. Here, $C=4$ for this problem.

<!-- tabs:start -->

### **Python3**
10 changes: 10 additions & 0 deletions lcci/16.16.Sub Sort/README_EN.md
Original file line number Diff line number Diff line change
@@ -21,6 +21,16 @@

## Solutions

**Solution 1: Two Passes**

We first traverse the array $array$ from left to right, and use $mx$ to record the maximum value encountered so far. If the current value $x$ is less than $mx$, it means that $x$ needs to be sorted, and we record the index $i$ of $x$ as $right$; otherwise, update $mx$.

Similarly, we traverse the array $array$ from right to left, and use $mi$ to record the minimum value encountered so far. If the current value $x$ is greater than $mi$, it means that $x$ needs to be sorted, and we record the index $i$ of $x$ as $left$; otherwise, update $mi$.

Finally, return $[left, right]$.

The time complexity is $O(n)$, where $n$ is the length of the array $array$. The space complexity is $O(1)$.

<!-- tabs:start -->

### **Python3**
Loading