Skip to content

feat: add solutions to lcci problems: No.08.03,08.07 #2689

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

Merged
merged 1 commit into from
Apr 29, 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
219 changes: 94 additions & 125 deletions lcci/08.03.Magic Index/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,47 +28,55 @@

## 解法

### 方法一
### 方法一:二分搜索

我们设计一个函数 $dfs(i, j)$,表示在数组 $nums[i, j]$ 中寻找魔术索引。如果找到了,返回魔术索引的值,否则返回 $-1$。那么答案就是 $dfs(0, n-1)$。

函数 $dfs(i, j)$ 的实现如下:

1. 如果 $i > j$,返回 $-1$。
2. 否则,我们取中间位置 $mid = (i + j) / 2$,然后递归调用 $dfs(i, mid-1)$,如果返回值不为 $-1$,说明在左半部分找到了魔术索引,直接返回。否则,如果 $nums[mid] = mid$,说明找到了魔术索引,直接返回。否则,递归调用 $dfs(mid+1, j)$ 并返回。

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

<!-- tabs:start -->

```python
class Solution:
def findMagicIndex(self, nums: List[int]) -> int:
def find(nums, left, right):
if left > right:
def dfs(i: int, j: int) -> int:
if i > j:
return -1
mid = (left + right) >> 1
left_index = find(nums, left, mid - 1)
if left_index != -1:
return left_index
mid = (i + j) >> 1
l = dfs(i, mid - 1)
if l != -1:
return l
if nums[mid] == mid:
return mid
return find(nums, mid + 1, right)
return dfs(mid + 1, j)

return find(nums, 0, len(nums) - 1)
return dfs(0, len(nums) - 1)
```

```java
class Solution {
public int findMagicIndex(int[] nums) {
int left = 0, right = nums.length - 1;
return find(nums, left, right);
return dfs(nums, 0, nums.length - 1);
}

private int find(int[] nums, int left, int right) {
if (left > right) {
private int dfs(int[] nums, int i, int j) {
if (i > j) {
return -1;
}
int mid = (left + right) >> 1;
int leftIndex = find(nums, left, mid - 1);
if (leftIndex != -1) {
return leftIndex;
int mid = (i + j) >> 1;
int l = dfs(nums, i, mid - 1);
if (l != -1) {
return l;
}
if (nums[mid] == mid) {
return mid;
}
return find(nums, mid + 1, right);
return dfs(nums, mid + 1, j);
}
}
```
Expand All @@ -77,91 +85,86 @@ class Solution {
class Solution {
public:
int findMagicIndex(vector<int>& nums) {
return find(nums, 0, nums.size() - 1);
}

int find(vector<int>& nums, int left, int right) {
if (left > right) {
return -1;
}
int mid = left + right >> 1;
int leftIndex = find(nums, left, mid - 1);
if (leftIndex != -1) {
return leftIndex;
}
if (nums[mid] == mid) {
return mid;
}
return find(nums, mid + 1, right);
function<int(int, int)> dfs = [&](int i, int j) {
if (i > j) {
return -1;
}
int mid = (i + j) >> 1;
int l = dfs(i, mid - 1);
if (l != -1) {
return l;
}
if (nums[mid] == mid) {
return mid;
}
return dfs(mid + 1, j);
};
return dfs(0, nums.size() - 1);
}
};
```

```go
func findMagicIndex(nums []int) int {
return find(nums, 0, len(nums)-1)
}

func find(nums []int, left, right int) int {
if left > right {
return -1
}
mid := (left + right) >> 1
leftIndex := find(nums, left, mid-1)
if leftIndex != -1 {
return leftIndex
var dfs func(i, j int) int
dfs = func(i, j int) int {
if i > j {
return -1
}
mid := (i + j) >> 1
if l := dfs(i, mid-1); l != -1 {
return l
}
if nums[mid] == mid {
return mid
}
return dfs(mid+1, j)
}
if nums[mid] == mid {
return mid
}
return find(nums, mid+1, right)
return dfs(0, len(nums)-1)
}
```

```ts
function findMagicIndex(nums: number[]): number {
const n = nums.length;
const find = (l: number, r: number): number => {
if (l > r || nums[r] < 0) {
const dfs = (i: number, j: number): number => {
if (i > j) {
return -1;
}
const mid = l + Math.floor((r - l) / 2);
if (nums[mid] >= l) {
const res = find(l, mid - 1);
if (res !== -1) {
return res;
}
const mid = (i + j) >> 1;
const l = dfs(i, mid - 1);
if (l !== -1) {
return l;
}
if (nums[mid] === mid) {
return mid;
}
return find(mid + 1, r);
return dfs(mid + 1, j);
};
return find(0, n - 1);
return dfs(0, nums.length - 1);
}
```

```rust
impl Solution {
fn find(nums: &Vec<i32>, l: usize, r: usize) -> i32 {
if l >= r || nums[r - 1] < 0 {
fn dfs(nums: &Vec<i32>, i: usize, j: usize) -> i32 {
if i >= j || nums[j - 1] < 0 {
return -1;
}
let mid = l + (r - l) / 2;
if nums[mid] >= (l as i32) {
let res = Self::find(nums, l, mid);
if res != -1 {
return res;
let mid = (i + j) >> 1;
if nums[mid] >= (i as i32) {
let l = Self::dfs(nums, i, mid);
if l != -1 {
return l;
}
}
if nums[mid] == (mid as i32) {
return mid as i32;
}
Self::find(nums, mid + 1, r)
Self::dfs(nums, mid + 1, j)
}

pub fn find_magic_index(nums: Vec<i32>) -> i32 {
Self::find(&nums, 0, nums.len())
Self::dfs(&nums, 0, nums.len())
}
}
```
Expand All @@ -172,77 +175,43 @@ impl Solution {
* @return {number}
*/
var findMagicIndex = function (nums) {
return helper(nums, 0, nums.length - 1);
};

function helper(nums, left, right) {
if (left > right) return -1;
let mid = Math.floor((left + right) / 2);
let leftIndex = helper(nums, left, mid - 1);
if (leftIndex != -1) return leftIndex;
if (nums[mid] == mid) return mid;
return helper(nums, mid + 1, right);
}
```

<!-- tabs:end -->

### 方法二

<!-- tabs:start -->

```ts
function findMagicIndex(nums: number[]): number {
const n = nums.length;
let i = 0;
while (i < n) {
if (nums[i] === i) {
return i;
const dfs = (i, j) => {
if (i > j) {
return -1;
}
i = Math.max(nums[i], i + 1);
}
return -1;
}
```

```rust
impl Solution {
pub fn find_magic_index(nums: Vec<i32>) -> i32 {
let n = nums.len();
let mut i = 0 as i32;
while (i as usize) < n {
let num = nums[i as usize];
if num == i {
return i;
}
i = num.max(i + 1);
const mid = (i + j) >> 1;
const l = dfs(i, mid - 1);
if (l !== -1) {
return l;
}
-1
}
}
if (nums[mid] === mid) {
return mid;
}
return dfs(mid + 1, j);
};
return dfs(0, nums.length - 1);
};
```

```swift
class Solution {
func findMagicIndex(_ nums: [Int]) -> Int {
let left = 0
let right = nums.count - 1
return find(nums, left, right)
return find(nums, 0, nums.count - 1)
}

private func find(_ nums: [Int], _ left: Int, _ right: Int) -> Int {
if left > right {
private func find(_ nums: [Int], _ i: Int, _ j: Int) -> Int {
if i > j {
return -1
}
let mid = (left + right) >> 1
let leftIndex = find(nums, left, mid - 1)
if leftIndex != -1 {
return leftIndex
let mid = (i + j) >> 1
let l = find(nums, i, mid - 1)
if l != -1 {
return l
}
if nums[mid] == mid {
return mid
}
return find(nums, mid + 1, right)
return find(nums, mid + 1, j)
}
}
```
Expand Down
Loading