Skip to content

Commit 5cce4a1

Browse files
authored
feat: add solutions to lcci problems: No.08.03,08.07 (doocs#2689)
* No.08.03.Magic Index * No.08.07.Permutation I
1 parent 7a355b5 commit 5cce4a1

20 files changed

+604
-596
lines changed

lcci/08.03.Magic Index/README.md

Lines changed: 94 additions & 125 deletions
Original file line numberDiff line numberDiff line change
@@ -28,47 +28,55 @@
2828

2929
## 解法
3030

31-
### 方法一
31+
### 方法一:二分搜索
32+
33+
我们设计一个函数 $dfs(i, j)$,表示在数组 $nums[i, j]$ 中寻找魔术索引。如果找到了,返回魔术索引的值,否则返回 $-1$。那么答案就是 $dfs(0, n-1)$。
34+
35+
函数 $dfs(i, j)$ 的实现如下:
36+
37+
1. 如果 $i > j$,返回 $-1$。
38+
2. 否则,我们取中间位置 $mid = (i + j) / 2$,然后递归调用 $dfs(i, mid-1)$,如果返回值不为 $-1$,说明在左半部分找到了魔术索引,直接返回。否则,如果 $nums[mid] = mid$,说明找到了魔术索引,直接返回。否则,递归调用 $dfs(mid+1, j)$ 并返回。
39+
40+
时间复杂度 $O(\log n)$,空间复杂度 $O(\log n)$。其中 $n$ 为数组的长度。
3241

3342
<!-- tabs:start -->
3443

3544
```python
3645
class Solution:
3746
def findMagicIndex(self, nums: List[int]) -> int:
38-
def find(nums, left, right):
39-
if left > right:
47+
def dfs(i: int, j: int) -> int:
48+
if i > j:
4049
return -1
41-
mid = (left + right) >> 1
42-
left_index = find(nums, left, mid - 1)
43-
if left_index != -1:
44-
return left_index
50+
mid = (i + j) >> 1
51+
l = dfs(i, mid - 1)
52+
if l != -1:
53+
return l
4554
if nums[mid] == mid:
4655
return mid
47-
return find(nums, mid + 1, right)
56+
return dfs(mid + 1, j)
4857

49-
return find(nums, 0, len(nums) - 1)
58+
return dfs(0, len(nums) - 1)
5059
```
5160

5261
```java
5362
class Solution {
5463
public int findMagicIndex(int[] nums) {
55-
int left = 0, right = nums.length - 1;
56-
return find(nums, left, right);
64+
return dfs(nums, 0, nums.length - 1);
5765
}
5866

59-
private int find(int[] nums, int left, int right) {
60-
if (left > right) {
67+
private int dfs(int[] nums, int i, int j) {
68+
if (i > j) {
6169
return -1;
6270
}
63-
int mid = (left + right) >> 1;
64-
int leftIndex = find(nums, left, mid - 1);
65-
if (leftIndex != -1) {
66-
return leftIndex;
71+
int mid = (i + j) >> 1;
72+
int l = dfs(nums, i, mid - 1);
73+
if (l != -1) {
74+
return l;
6775
}
6876
if (nums[mid] == mid) {
6977
return mid;
7078
}
71-
return find(nums, mid + 1, right);
79+
return dfs(nums, mid + 1, j);
7280
}
7381
}
7482
```
@@ -77,91 +85,86 @@ class Solution {
7785
class Solution {
7886
public:
7987
int findMagicIndex(vector<int>& nums) {
80-
return find(nums, 0, nums.size() - 1);
81-
}
82-
83-
int find(vector<int>& nums, int left, int right) {
84-
if (left > right) {
85-
return -1;
86-
}
87-
int mid = left + right >> 1;
88-
int leftIndex = find(nums, left, mid - 1);
89-
if (leftIndex != -1) {
90-
return leftIndex;
91-
}
92-
if (nums[mid] == mid) {
93-
return mid;
94-
}
95-
return find(nums, mid + 1, right);
88+
function<int(int, int)> dfs = [&](int i, int j) {
89+
if (i > j) {
90+
return -1;
91+
}
92+
int mid = (i + j) >> 1;
93+
int l = dfs(i, mid - 1);
94+
if (l != -1) {
95+
return l;
96+
}
97+
if (nums[mid] == mid) {
98+
return mid;
99+
}
100+
return dfs(mid + 1, j);
101+
};
102+
return dfs(0, nums.size() - 1);
96103
}
97104
};
98105
```
99106
100107
```go
101108
func findMagicIndex(nums []int) int {
102-
return find(nums, 0, len(nums)-1)
103-
}
104-
105-
func find(nums []int, left, right int) int {
106-
if left > right {
107-
return -1
108-
}
109-
mid := (left + right) >> 1
110-
leftIndex := find(nums, left, mid-1)
111-
if leftIndex != -1 {
112-
return leftIndex
109+
var dfs func(i, j int) int
110+
dfs = func(i, j int) int {
111+
if i > j {
112+
return -1
113+
}
114+
mid := (i + j) >> 1
115+
if l := dfs(i, mid-1); l != -1 {
116+
return l
117+
}
118+
if nums[mid] == mid {
119+
return mid
120+
}
121+
return dfs(mid+1, j)
113122
}
114-
if nums[mid] == mid {
115-
return mid
116-
}
117-
return find(nums, mid+1, right)
123+
return dfs(0, len(nums)-1)
118124
}
119125
```
120126

121127
```ts
122128
function findMagicIndex(nums: number[]): number {
123-
const n = nums.length;
124-
const find = (l: number, r: number): number => {
125-
if (l > r || nums[r] < 0) {
129+
const dfs = (i: number, j: number): number => {
130+
if (i > j) {
126131
return -1;
127132
}
128-
const mid = l + Math.floor((r - l) / 2);
129-
if (nums[mid] >= l) {
130-
const res = find(l, mid - 1);
131-
if (res !== -1) {
132-
return res;
133-
}
133+
const mid = (i + j) >> 1;
134+
const l = dfs(i, mid - 1);
135+
if (l !== -1) {
136+
return l;
134137
}
135138
if (nums[mid] === mid) {
136139
return mid;
137140
}
138-
return find(mid + 1, r);
141+
return dfs(mid + 1, j);
139142
};
140-
return find(0, n - 1);
143+
return dfs(0, nums.length - 1);
141144
}
142145
```
143146

144147
```rust
145148
impl Solution {
146-
fn find(nums: &Vec<i32>, l: usize, r: usize) -> i32 {
147-
if l >= r || nums[r - 1] < 0 {
149+
fn dfs(nums: &Vec<i32>, i: usize, j: usize) -> i32 {
150+
if i >= j || nums[j - 1] < 0 {
148151
return -1;
149152
}
150-
let mid = l + (r - l) / 2;
151-
if nums[mid] >= (l as i32) {
152-
let res = Self::find(nums, l, mid);
153-
if res != -1 {
154-
return res;
153+
let mid = (i + j) >> 1;
154+
if nums[mid] >= (i as i32) {
155+
let l = Self::dfs(nums, i, mid);
156+
if l != -1 {
157+
return l;
155158
}
156159
}
157160
if nums[mid] == (mid as i32) {
158161
return mid as i32;
159162
}
160-
Self::find(nums, mid + 1, r)
163+
Self::dfs(nums, mid + 1, j)
161164
}
162165

163166
pub fn find_magic_index(nums: Vec<i32>) -> i32 {
164-
Self::find(&nums, 0, nums.len())
167+
Self::dfs(&nums, 0, nums.len())
165168
}
166169
}
167170
```
@@ -172,77 +175,43 @@ impl Solution {
172175
* @return {number}
173176
*/
174177
var findMagicIndex = function (nums) {
175-
return helper(nums, 0, nums.length - 1);
176-
};
177-
178-
function helper(nums, left, right) {
179-
if (left > right) return -1;
180-
let mid = Math.floor((left + right) / 2);
181-
let leftIndex = helper(nums, left, mid - 1);
182-
if (leftIndex != -1) return leftIndex;
183-
if (nums[mid] == mid) return mid;
184-
return helper(nums, mid + 1, right);
185-
}
186-
```
187-
188-
<!-- tabs:end -->
189-
190-
### 方法二
191-
192-
<!-- tabs:start -->
193-
194-
```ts
195-
function findMagicIndex(nums: number[]): number {
196-
const n = nums.length;
197-
let i = 0;
198-
while (i < n) {
199-
if (nums[i] === i) {
200-
return i;
178+
const dfs = (i, j) => {
179+
if (i > j) {
180+
return -1;
201181
}
202-
i = Math.max(nums[i], i + 1);
203-
}
204-
return -1;
205-
}
206-
```
207-
208-
```rust
209-
impl Solution {
210-
pub fn find_magic_index(nums: Vec<i32>) -> i32 {
211-
let n = nums.len();
212-
let mut i = 0 as i32;
213-
while (i as usize) < n {
214-
let num = nums[i as usize];
215-
if num == i {
216-
return i;
217-
}
218-
i = num.max(i + 1);
182+
const mid = (i + j) >> 1;
183+
const l = dfs(i, mid - 1);
184+
if (l !== -1) {
185+
return l;
219186
}
220-
-1
221-
}
222-
}
187+
if (nums[mid] === mid) {
188+
return mid;
189+
}
190+
return dfs(mid + 1, j);
191+
};
192+
return dfs(0, nums.length - 1);
193+
};
223194
```
224195

225196
```swift
226197
class Solution {
227198
func findMagicIndex(_ nums: [Int]) -> Int {
228-
let left = 0
229-
let right = nums.count - 1
230-
return find(nums, left, right)
199+
return find(nums, 0, nums.count - 1)
231200
}
232201

233-
private func find(_ nums: [Int], _ left: Int, _ right: Int) -> Int {
234-
if left > right {
202+
private func find(_ nums: [Int], _ i: Int, _ j: Int) -> Int {
203+
if i > j {
235204
return -1
236205
}
237-
let mid = (left + right) >> 1
238-
let leftIndex = find(nums, left, mid - 1)
239-
if leftIndex != -1 {
240-
return leftIndex
206+
let mid = (i + j) >> 1
207+
let l = find(nums, i, mid - 1)
208+
if l != -1 {
209+
return l
241210
}
242211
if nums[mid] == mid {
243212
return mid
244213
}
245-
return find(nums, mid + 1, right)
214+
return find(nums, mid + 1, j)
246215
}
247216
}
248217
```

0 commit comments

Comments
 (0)