Skip to content

Commit 4507b47

Browse files
authored
feat: add solutions to lc problem: No.0744 (doocs#2734)
1 parent 3a32817 commit 4507b47

File tree

13 files changed

+118
-275
lines changed

13 files changed

+118
-275
lines changed

solution/0700-0799/0744.Find Smallest Letter Greater Than Target/README.md

+39-107
Original file line numberDiff line numberDiff line change
@@ -49,42 +49,31 @@
4949

5050
## 解法
5151

52-
### 方法一:遍历
52+
### 方法一:二分查找
5353

54-
遍历 `letters`,返回第一个满足 `letters[i] > target` 条件的元素。若是遍历结束还未找到,则返回 `letters[0]`
54+
由于 $\text{letters}$ 是按照非递减顺序排序的,所以我们可以使用二分查找来找到大于 `target` 的最小字符
5555

56-
> 至少存在两个不同的字母,所以不会返回 `target`
56+
我们定义二分查找的左边界 $l = 0$,右边界 $r = n$。对于每一次二分查找,我们计算中间位置 $mid = (l + r) / 2$,如果 $letters[mid] > \text{target}$,则说明我们需要在左半部分继续查找,即 $r = mid$;否则我们需要在右半部分继续查找,即 $l = mid + 1$
5757

58-
时间复杂度:$O(N)$。
58+
最后我们返回 $letters[l \mod n]$ 即可。
59+
60+
时间复杂度 $O(\log n)$,其中 $n$ 是 $\text{letters}$ 的长度。空间复杂度 $O(1)$。
5961

6062
<!-- tabs:start -->
6163

6264
```python
6365
class Solution:
6466
def nextGreatestLetter(self, letters: List[str], target: str) -> str:
65-
left, right = 0, len(letters)
66-
while left < right:
67-
mid = (left + right) >> 1
68-
if ord(letters[mid]) > ord(target):
69-
right = mid
70-
else:
71-
left = mid + 1
72-
return letters[left % len(letters)]
67+
i = bisect_right(letters, ord(target), key=lambda c: ord(c))
68+
return letters[i % len(letters)]
7369
```
7470

7571
```java
7672
class Solution {
7773
public char nextGreatestLetter(char[] letters, char target) {
78-
int left = 0, right = letters.length;
79-
while (left < right) {
80-
int mid = (left + right) >> 1;
81-
if (letters[mid] > target) {
82-
right = mid;
83-
} else {
84-
left = mid + 1;
85-
}
86-
}
87-
return letters[left % letters.length];
74+
int i = Arrays.binarySearch(letters, (char) (target + 1));
75+
i = i < 0 ? -i - 1 : i;
76+
return letters[i % letters.length];
8877
}
8978
}
9079
```
@@ -93,59 +82,48 @@ class Solution {
9382
class Solution {
9483
public:
9584
char nextGreatestLetter(vector<char>& letters, char target) {
96-
int left = 0, right = letters.size();
97-
while (left < right) {
98-
int mid = left + right >> 1;
99-
if (letters[mid] > target) {
100-
right = mid;
101-
} else {
102-
left = mid + 1;
103-
}
104-
}
105-
return letters[left % letters.size()];
85+
int i = upper_bound(letters.begin(), letters.end(), target) - letters.begin();
86+
return letters[i % letters.size()];
10687
}
10788
};
10889
```
10990
11091
```go
11192
func nextGreatestLetter(letters []byte, target byte) byte {
112-
left, right := 0, len(letters)
113-
for left < right {
114-
mid := (left + right) >> 1
115-
if letters[mid] > target {
116-
right = mid
117-
} else {
118-
left = mid + 1
119-
}
120-
}
121-
return letters[left%len(letters)]
93+
i := sort.Search(len(letters), func(i int) bool { return letters[i] > target })
94+
return letters[i%len(letters)]
12295
}
12396
```
12497

12598
```ts
12699
function nextGreatestLetter(letters: string[], target: string): string {
127-
const n = letters.length;
128-
let left = 0;
129-
let right = letters.length;
130-
while (left < right) {
131-
let mid = (left + right) >>> 1;
100+
let [l, r] = [0, letters.length];
101+
while (l < r) {
102+
const mid = (l + r) >> 1;
132103
if (letters[mid] > target) {
133-
right = mid;
104+
r = mid;
134105
} else {
135-
left = mid + 1;
106+
l = mid + 1;
136107
}
137108
}
138-
return letters[left % n];
109+
return letters[l % letters.length];
139110
}
140111
```
141112

142113
```rust
143114
impl Solution {
144115
pub fn next_greatest_letter(letters: Vec<char>, target: char) -> char {
145-
*letters
146-
.iter()
147-
.find(|&&c| c > target)
148-
.unwrap_or(&letters[0])
116+
let mut l = 0;
117+
let mut r = letters.len();
118+
while l < r {
119+
let mid = l + (r - l) / 2;
120+
if letters[mid] > target {
121+
r = mid;
122+
} else {
123+
l = mid + 1;
124+
}
125+
}
126+
letters[l % letters.len()]
149127
}
150128
}
151129
```
@@ -158,63 +136,17 @@ class Solution {
158136
* @return String
159137
*/
160138
function nextGreatestLetter($letters, $target) {
161-
$left = 0;
162-
$right = count($letters);
163-
while ($left <= $right) {
164-
$mid = floor($left + ($right - $left) / 2);
139+
$l = 0;
140+
$r = count($letters);
141+
while ($l < $r) {
142+
$mid = $l + $r >> 1;
165143
if ($letters[$mid] > $target) {
166-
$right = $mid - 1;
167-
} else {
168-
$left = $mid + 1;
169-
}
170-
}
171-
if ($left >= count($letters)) {
172-
return $letters[0];
173-
} else {
174-
return $letters[$left];
175-
}
176-
}
177-
}
178-
```
179-
180-
<!-- tabs:end -->
181-
182-
### 方法二:二分
183-
184-
利用 `letters` 有序的特点,可以使用二分来快速查找。
185-
186-
在返回值方面相比传统二分不一样,需要对结果进行取余操作:`letters[l % n]`
187-
188-
为什么?如题描述,字母是重复出现的,当索引过界时,不是没有结果,而是需要返回前面的元素。
189-
190-
一个容易理解的版本,使用减法:
191-
192-
```c
193-
if (l < n) {
194-
return letters[l];
195-
}
196-
return letters[l - n];
197-
```
198-
199-
时间复杂度:$O(logN)$。
200-
201-
<!-- tabs:start -->
202-
203-
```rust
204-
impl Solution {
205-
pub fn next_greatest_letter(letters: Vec<char>, target: char) -> char {
206-
let n = letters.len();
207-
let mut left = 0;
208-
let mut right = n;
209-
while left < right {
210-
let mid = left + (right - left) / 2;
211-
if letters[mid] > target {
212-
right = mid;
144+
$r = $mid;
213145
} else {
214-
left = mid + 1;
146+
$l = $mid + 1;
215147
}
216148
}
217-
letters[left % n]
149+
return $letters[$l % count($letters)];
218150
}
219151
}
220152
```

solution/0700-0799/0744.Find Smallest Letter Greater Than Target/README_EN.md

+42-87
Original file line numberDiff line numberDiff line change
@@ -48,36 +48,31 @@
4848

4949
## Solutions
5050

51-
### Solution 1
51+
### Solution 1: Binary Search
52+
53+
Since `letters` is sorted in non-decreasing order, we can use binary search to find the smallest character that is larger than `target`.
54+
55+
We define the left boundary of the binary search as $l = 0$, and the right boundary as $r = n$. For each binary search, we calculate the middle position $mid = (l + r) / 2$. If $letters[mid] > \text{target}$, it means we need to continue searching in the left half, so we set $r = mid$. Otherwise, we need to continue searching in the right half, so we set $l = mid + 1$.
56+
57+
Finally, we return $letters[l \mod n]$.
58+
59+
The time complexity is $O(\log n)$, where $n$ is the length of `letters`. The space complexity is $O(1)$.
5260

5361
<!-- tabs:start -->
5462

5563
```python
5664
class Solution:
5765
def nextGreatestLetter(self, letters: List[str], target: str) -> str:
58-
left, right = 0, len(letters)
59-
while left < right:
60-
mid = (left + right) >> 1
61-
if ord(letters[mid]) > ord(target):
62-
right = mid
63-
else:
64-
left = mid + 1
65-
return letters[left % len(letters)]
66+
i = bisect_right(letters, ord(target), key=lambda c: ord(c))
67+
return letters[i % len(letters)]
6668
```
6769

6870
```java
6971
class Solution {
7072
public char nextGreatestLetter(char[] letters, char target) {
71-
int left = 0, right = letters.length;
72-
while (left < right) {
73-
int mid = (left + right) >> 1;
74-
if (letters[mid] > target) {
75-
right = mid;
76-
} else {
77-
left = mid + 1;
78-
}
79-
}
80-
return letters[left % letters.length];
73+
int i = Arrays.binarySearch(letters, (char) (target + 1));
74+
i = i < 0 ? -i - 1 : i;
75+
return letters[i % letters.length];
8176
}
8277
}
8378
```
@@ -86,59 +81,48 @@ class Solution {
8681
class Solution {
8782
public:
8883
char nextGreatestLetter(vector<char>& letters, char target) {
89-
int left = 0, right = letters.size();
90-
while (left < right) {
91-
int mid = left + right >> 1;
92-
if (letters[mid] > target) {
93-
right = mid;
94-
} else {
95-
left = mid + 1;
96-
}
97-
}
98-
return letters[left % letters.size()];
84+
int i = upper_bound(letters.begin(), letters.end(), target) - letters.begin();
85+
return letters[i % letters.size()];
9986
}
10087
};
10188
```
10289
10390
```go
10491
func nextGreatestLetter(letters []byte, target byte) byte {
105-
left, right := 0, len(letters)
106-
for left < right {
107-
mid := (left + right) >> 1
108-
if letters[mid] > target {
109-
right = mid
110-
} else {
111-
left = mid + 1
112-
}
113-
}
114-
return letters[left%len(letters)]
92+
i := sort.Search(len(letters), func(i int) bool { return letters[i] > target })
93+
return letters[i%len(letters)]
11594
}
11695
```
11796

11897
```ts
11998
function nextGreatestLetter(letters: string[], target: string): string {
120-
const n = letters.length;
121-
let left = 0;
122-
let right = letters.length;
123-
while (left < right) {
124-
let mid = (left + right) >>> 1;
99+
let [l, r] = [0, letters.length];
100+
while (l < r) {
101+
const mid = (l + r) >> 1;
125102
if (letters[mid] > target) {
126-
right = mid;
103+
r = mid;
127104
} else {
128-
left = mid + 1;
105+
l = mid + 1;
129106
}
130107
}
131-
return letters[left % n];
108+
return letters[l % letters.length];
132109
}
133110
```
134111

135112
```rust
136113
impl Solution {
137114
pub fn next_greatest_letter(letters: Vec<char>, target: char) -> char {
138-
*letters
139-
.iter()
140-
.find(|&&c| c > target)
141-
.unwrap_or(&letters[0])
115+
let mut l = 0;
116+
let mut r = letters.len();
117+
while l < r {
118+
let mid = l + (r - l) / 2;
119+
if letters[mid] > target {
120+
r = mid;
121+
} else {
122+
l = mid + 1;
123+
}
124+
}
125+
letters[l % letters.len()]
142126
}
143127
}
144128
```
@@ -151,46 +135,17 @@ class Solution {
151135
* @return String
152136
*/
153137
function nextGreatestLetter($letters, $target) {
154-
$left = 0;
155-
$right = count($letters);
156-
while ($left <= $right) {
157-
$mid = floor($left + ($right - $left) / 2);
138+
$l = 0;
139+
$r = count($letters);
140+
while ($l < $r) {
141+
$mid = $l + $r >> 1;
158142
if ($letters[$mid] > $target) {
159-
$right = $mid - 1;
160-
} else {
161-
$left = $mid + 1;
162-
}
163-
}
164-
if ($left >= count($letters)) {
165-
return $letters[0];
166-
} else {
167-
return $letters[$left];
168-
}
169-
}
170-
}
171-
```
172-
173-
<!-- tabs:end -->
174-
175-
### Solution 2
176-
177-
<!-- tabs:start -->
178-
179-
```rust
180-
impl Solution {
181-
pub fn next_greatest_letter(letters: Vec<char>, target: char) -> char {
182-
let n = letters.len();
183-
let mut left = 0;
184-
let mut right = n;
185-
while left < right {
186-
let mid = left + (right - left) / 2;
187-
if letters[mid] > target {
188-
right = mid;
143+
$r = $mid;
189144
} else {
190-
left = mid + 1;
145+
$l = $mid + 1;
191146
}
192147
}
193-
letters[left % n]
148+
return $letters[$l % count($letters)];
194149
}
195150
}
196151
```

0 commit comments

Comments
 (0)