28
28
29
29
## 解法
30
30
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$ 为数组的长度。
32
41
33
42
<!-- tabs:start -->
34
43
35
44
``` python
36
45
class Solution :
37
46
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 :
40
49
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
45
54
if nums[mid] == mid:
46
55
return mid
47
- return find(nums, mid + 1 , right )
56
+ return dfs( mid + 1 , j )
48
57
49
- return find(nums, 0 , len (nums) - 1 )
58
+ return dfs( 0 , len (nums) - 1 )
50
59
```
51
60
52
61
``` java
53
62
class Solution {
54
63
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 );
57
65
}
58
66
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 ) {
61
69
return - 1 ;
62
70
}
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 ;
67
75
}
68
76
if (nums[mid] == mid) {
69
77
return mid;
70
78
}
71
- return find (nums, mid + 1 , right );
79
+ return dfs (nums, mid + 1 , j );
72
80
}
73
81
}
74
82
```
@@ -77,91 +85,86 @@ class Solution {
77
85
class Solution {
78
86
public:
79
87
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);
96
103
}
97
104
};
98
105
```
99
106
100
107
```go
101
108
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)
113
122
}
114
- if nums[mid] == mid {
115
- return mid
116
- }
117
- return find (nums, mid+1 , right)
123
+ return dfs(0, len(nums)-1)
118
124
}
119
125
```
120
126
121
127
``` ts
122
128
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 ) {
126
131
return - 1 ;
127
132
}
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 ;
134
137
}
135
138
if (nums [mid ] === mid ) {
136
139
return mid ;
137
140
}
138
- return find (mid + 1 , r );
141
+ return dfs (mid + 1 , j );
139
142
};
140
- return find (0 , n - 1 );
143
+ return dfs (0 , nums . length - 1 );
141
144
}
142
145
```
143
146
144
147
``` rust
145
148
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 {
148
151
return - 1 ;
149
152
}
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 ;
155
158
}
156
159
}
157
160
if nums [mid ] == (mid as i32 ) {
158
161
return mid as i32 ;
159
162
}
160
- Self :: find (nums , mid + 1 , r )
163
+ Self :: dfs (nums , mid + 1 , j )
161
164
}
162
165
163
166
pub fn find_magic_index (nums : Vec <i32 >) -> i32 {
164
- Self :: find (& nums , 0 , nums . len ())
167
+ Self :: dfs (& nums , 0 , nums . len ())
165
168
}
166
169
}
167
170
```
@@ -172,77 +175,43 @@ impl Solution {
172
175
* @return {number}
173
176
*/
174
177
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 ;
201
181
}
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;
219
186
}
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
+ };
223
194
```
224
195
225
196
``` swift
226
197
class Solution {
227
198
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 )
231
200
}
232
201
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 {
235
204
return -1
236
205
}
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
241
210
}
242
211
if nums[mid] == mid {
243
212
return mid
244
213
}
245
- return find (nums, mid + 1 , right )
214
+ return find (nums, mid + 1 , j )
246
215
}
247
216
}
248
217
```
0 commit comments