From 7e122272f17a6525672e669cb9698044fe34afce Mon Sep 17 00:00:00 2001 From: yanglbme Date: Mon, 29 Apr 2024 17:25:44 +0800 Subject: [PATCH] feat: add solutions to lcci problems: No.08.03,08.07 * No.08.03.Magic Index * No.08.07.Permutation I --- lcci/08.03.Magic Index/README.md | 219 +++++++++++-------------- lcci/08.03.Magic Index/README_EN.md | 219 +++++++++++-------------- lcci/08.03.Magic Index/Solution.cpp | 31 ++-- lcci/08.03.Magic Index/Solution.go | 29 ++-- lcci/08.03.Magic Index/Solution.java | 17 +- lcci/08.03.Magic Index/Solution.js | 25 +-- lcci/08.03.Magic Index/Solution.py | 16 +- lcci/08.03.Magic Index/Solution.rs | 18 +- lcci/08.03.Magic Index/Solution.swift | 18 +- lcci/08.03.Magic Index/Solution.ts | 19 +-- lcci/08.03.Magic Index/Solution2.rs | 14 -- lcci/08.03.Magic Index/Solution2.ts | 11 -- lcci/08.07.Permutation I/README.md | 191 ++++++++++++--------- lcci/08.07.Permutation I/README_EN.md | 191 ++++++++++++--------- lcci/08.07.Permutation I/Solution.cpp | 38 +++-- lcci/08.07.Permutation I/Solution.go | 29 ++-- lcci/08.07.Permutation I/Solution.java | 25 +-- lcci/08.07.Permutation I/Solution.js | 45 +++-- lcci/08.07.Permutation I/Solution.py | 21 +-- lcci/08.07.Permutation I/Solution.ts | 24 +++ 20 files changed, 604 insertions(+), 596 deletions(-) delete mode 100644 lcci/08.03.Magic Index/Solution2.rs delete mode 100644 lcci/08.03.Magic Index/Solution2.ts create mode 100644 lcci/08.07.Permutation I/Solution.ts diff --git a/lcci/08.03.Magic Index/README.md b/lcci/08.03.Magic Index/README.md index 177d645e37939..2729821d66556 100644 --- a/lcci/08.03.Magic Index/README.md +++ b/lcci/08.03.Magic Index/README.md @@ -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$ 为数组的长度。 ```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); } } ``` @@ -77,91 +85,86 @@ class Solution { class Solution { public: int findMagicIndex(vector& nums) { - return find(nums, 0, nums.size() - 1); - } - - int find(vector& 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 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, l: usize, r: usize) -> i32 { - if l >= r || nums[r - 1] < 0 { + fn dfs(nums: &Vec, 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 { - Self::find(&nums, 0, nums.len()) + Self::dfs(&nums, 0, nums.len()) } } ``` @@ -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); -} -``` - - - -### 方法二 - - - -```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 { - 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) } } ``` diff --git a/lcci/08.03.Magic Index/README_EN.md b/lcci/08.03.Magic Index/README_EN.md index 2e75075d7a5bf..993359f546f41 100644 --- a/lcci/08.03.Magic Index/README_EN.md +++ b/lcci/08.03.Magic Index/README_EN.md @@ -34,47 +34,55 @@ ## Solutions -### Solution 1 +### Solution 1: Binary Search + +We design a function $dfs(i, j)$ to find the magic index in the array $nums[i, j]$. If found, return the value of the magic index, otherwise return $-1$. So the answer is $dfs(0, n-1)$. + +The implementation of the function $dfs(i, j)$ is as follows: + +1. If $i > j$, return $-1$. +2. Otherwise, we take the middle position $mid = (i + j) / 2$, then recursively call $dfs(i, mid-1)$. If the return value is not $-1$, it means that the magic index is found in the left half, return it directly. Otherwise, if $nums[mid] = mid$, it means that the magic index is found, return it directly. Otherwise, recursively call $dfs(mid+1, j)$ and return. + +The time complexity is $O(\log n)$, and the space complexity is $O(\log n)$. Where $n$ is the length of the array. ```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); } } ``` @@ -83,91 +91,86 @@ class Solution { class Solution { public: int findMagicIndex(vector& nums) { - return find(nums, 0, nums.size() - 1); - } - - int find(vector& 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 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, l: usize, r: usize) -> i32 { - if l >= r || nums[r - 1] < 0 { + fn dfs(nums: &Vec, 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 { - Self::find(&nums, 0, nums.len()) + Self::dfs(&nums, 0, nums.len()) } } ``` @@ -178,77 +181,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); -} -``` - - - -### Solution 2 - - - -```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 { - 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) } } ``` diff --git a/lcci/08.03.Magic Index/Solution.cpp b/lcci/08.03.Magic Index/Solution.cpp index b86f2690b7ad1..baf2c6cbecb9c 100644 --- a/lcci/08.03.Magic Index/Solution.cpp +++ b/lcci/08.03.Magic Index/Solution.cpp @@ -1,21 +1,20 @@ class Solution { public: int findMagicIndex(vector& nums) { - return find(nums, 0, nums.size() - 1); - } - - int find(vector& 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 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); } }; \ No newline at end of file diff --git a/lcci/08.03.Magic Index/Solution.go b/lcci/08.03.Magic Index/Solution.go index 2a352c7c3ee7d..dc9ff71759392 100644 --- a/lcci/08.03.Magic Index/Solution.go +++ b/lcci/08.03.Magic Index/Solution.go @@ -1,18 +1,17 @@ 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 + 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) } - mid := (left + right) >> 1 - leftIndex := find(nums, left, mid-1) - if leftIndex != -1 { - return leftIndex - } - if nums[mid] == mid { - return mid - } - return find(nums, mid+1, right) + return dfs(0, len(nums)-1) } \ No newline at end of file diff --git a/lcci/08.03.Magic Index/Solution.java b/lcci/08.03.Magic Index/Solution.java index 3cf55a1a0c701..376fd241e45aa 100644 --- a/lcci/08.03.Magic Index/Solution.java +++ b/lcci/08.03.Magic Index/Solution.java @@ -1,21 +1,20 @@ 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); } } \ No newline at end of file diff --git a/lcci/08.03.Magic Index/Solution.js b/lcci/08.03.Magic Index/Solution.js index ec59ca1f61687..04557466a6371 100644 --- a/lcci/08.03.Magic Index/Solution.js +++ b/lcci/08.03.Magic Index/Solution.js @@ -3,14 +3,19 @@ * @return {number} */ var findMagicIndex = function (nums) { - return helper(nums, 0, nums.length - 1); + const dfs = (i, j) => { + if (i > j) { + return -1; + } + const mid = (i + j) >> 1; + const 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.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); -} diff --git a/lcci/08.03.Magic Index/Solution.py b/lcci/08.03.Magic Index/Solution.py index d82ad883e773c..30a230a53f8a6 100644 --- a/lcci/08.03.Magic Index/Solution.py +++ b/lcci/08.03.Magic Index/Solution.py @@ -1,14 +1,14 @@ 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) diff --git a/lcci/08.03.Magic Index/Solution.rs b/lcci/08.03.Magic Index/Solution.rs index f5674a654709a..a4b12573d063c 100644 --- a/lcci/08.03.Magic Index/Solution.rs +++ b/lcci/08.03.Magic Index/Solution.rs @@ -1,22 +1,22 @@ impl Solution { - fn find(nums: &Vec, l: usize, r: usize) -> i32 { - if l >= r || nums[r - 1] < 0 { + fn dfs(nums: &Vec, 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 { - Self::find(&nums, 0, nums.len()) + Self::dfs(&nums, 0, nums.len()) } } diff --git a/lcci/08.03.Magic Index/Solution.swift b/lcci/08.03.Magic Index/Solution.swift index f56e7f9537b52..8f04ee244eb8c 100644 --- a/lcci/08.03.Magic Index/Solution.swift +++ b/lcci/08.03.Magic Index/Solution.swift @@ -1,22 +1,20 @@ 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) } } diff --git a/lcci/08.03.Magic Index/Solution.ts b/lcci/08.03.Magic Index/Solution.ts index 74db52ca16bf0..dfc79eee60109 100644 --- a/lcci/08.03.Magic Index/Solution.ts +++ b/lcci/08.03.Magic Index/Solution.ts @@ -1,20 +1,17 @@ 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); } diff --git a/lcci/08.03.Magic Index/Solution2.rs b/lcci/08.03.Magic Index/Solution2.rs deleted file mode 100644 index cd13572072eff..0000000000000 --- a/lcci/08.03.Magic Index/Solution2.rs +++ /dev/null @@ -1,14 +0,0 @@ -impl Solution { - pub fn find_magic_index(nums: Vec) -> 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); - } - -1 - } -} diff --git a/lcci/08.03.Magic Index/Solution2.ts b/lcci/08.03.Magic Index/Solution2.ts deleted file mode 100644 index 09a988aa75c36..0000000000000 --- a/lcci/08.03.Magic Index/Solution2.ts +++ /dev/null @@ -1,11 +0,0 @@ -function findMagicIndex(nums: number[]): number { - const n = nums.length; - let i = 0; - while (i < n) { - if (nums[i] === i) { - return i; - } - i = Math.max(nums[i], i + 1); - } - return -1; -} diff --git a/lcci/08.07.Permutation I/README.md b/lcci/08.07.Permutation I/README.md index 803eefe364579..c401b8e43c670 100644 --- a/lcci/08.07.Permutation I/README.md +++ b/lcci/08.07.Permutation I/README.md @@ -30,57 +30,65 @@ ## 解法 -### 方法一:回溯 +### 方法一:DFS(回溯) + +我们设计一个函数 $dfs(i)$ 表示已经填完了前 $i$ 个位置,现在需要填第 $i+1$ 个位置。枚举所有可能的字符,如果这个字符没有被填过,就填入这个字符,然后继续填下一个位置,直到填完所有的位置。 + +时间复杂度 $O(n \times n!)$,其中 $n$ 是字符串的长度。一共有 $n!$ 个排列,每个排列需要 $O(n)$ 的时间来构造。 ```python class Solution: def permutation(self, S: str) -> List[str]: - def dfs(u, t): - if u == n: - ans.append(''.join(t)) + def dfs(i: int): + if i == n: + ans.append("".join(t)) return - for i in range(n): - if vis[i]: + for j, c in enumerate(S): + if vis[j]: continue - vis[i] = True - t.append(S[i]) - dfs(u + 1, t) + vis[j] = True + t.append(c) + dfs(i + 1) t.pop() - vis[i] = False + vis[j] = False n = len(S) vis = [False] * n ans = [] - dfs(0, []) + t = [] + dfs(0) return ans ``` ```java class Solution { + private char[] s; + private boolean[] vis = new boolean['z' + 1]; + private List ans = new ArrayList<>(); + private StringBuilder t = new StringBuilder(); + public String[] permutation(String S) { - Set vis = new HashSet<>(); - List ans = new ArrayList<>(); - StringBuilder t = new StringBuilder(); - dfs(0, S, t, ans, vis); + s = S.toCharArray(); + dfs(0); return ans.toArray(new String[0]); } - private void dfs(int u, String S, StringBuilder t, List ans, Set vis) { - if (u == S.length()) { + private void dfs(int i) { + if (i == s.length) { ans.add(t.toString()); return; } - for (char c : S.toCharArray()) { - if (vis.contains(c)) { + for (char c : s) { + if (vis[c]) { continue; } - vis.add(c); + vis[c] = true; t.append(c); - dfs(u + 1, S, t, ans, vis); + dfs(i + 1); t.deleteCharAt(t.length() - 1); - vis.remove(c); + vis[c] = false; } } } @@ -90,54 +98,82 @@ class Solution { class Solution { public: vector permutation(string S) { - unordered_set vis; + int n = S.size(); + vector vis(n); vector ans; - string t = ""; - dfs(0, S, t, ans, vis); + string t; + function dfs = [&](int i) { + if (i >= n) { + ans.push_back(t); + return; + } + for (int j = 0; j < n; ++j) { + if (vis[j]) { + continue; + } + vis[j] = true; + t.push_back(S[j]); + dfs(i + 1); + t.pop_back(); + vis[j] = false; + } + }; + dfs(0); return ans; } - - void dfs(int u, string& S, string& t, vector& ans, unordered_set& vis) { - if (u == S.size()) { - ans.push_back(t); - return; - } - for (char& c : S) { - if (vis.count(c)) continue; - vis.insert(c); - t.push_back(c); - dfs(u + 1, S, t, ans, vis); - vis.erase(c); - t.pop_back(); - } - } }; ``` ```go -func permutation(S string) []string { - vis := make(map[byte]bool) - var ans []string - var t []byte - var dfs func(u int, t []byte) - dfs = func(u int, t []byte) { - if u == len(S) { +func permutation(S string) (ans []string) { + t := []byte{} + vis := make([]bool, len(S)) + var dfs func(int) + dfs = func(i int) { + if i >= len(S) { ans = append(ans, string(t)) return } - for i := range S { - if vis[S[i]] { + for j := range S { + if vis[j] { continue } - vis[S[i]] = true - t = append(t, S[i]) - dfs(u+1, t) - vis[S[i]] = false + vis[j] = true + t = append(t, S[j]) + dfs(i + 1) t = t[:len(t)-1] + vis[j] = false } } - dfs(0, t) - return ans + dfs(0) + return +} +``` + +```ts +function permutation(S: string): string[] { + const n = S.length; + const vis: boolean[] = Array(n).fill(false); + const ans: string[] = []; + const t: string[] = []; + const dfs = (i: number) => { + if (i >= n) { + ans.push(t.join('')); + return; + } + for (let j = 0; j < n; ++j) { + if (vis[j]) { + continue; + } + vis[j] = true; + t.push(S[j]); + dfs(i + 1); + t.pop(); + vis[j] = false; + } + }; + dfs(0); + return ans; } ``` @@ -147,30 +183,29 @@ func permutation(S string) []string { * @return {string[]} */ var permutation = function (S) { - let res = []; - let arr = [...S]; - let prev = []; - let record = new Array(S.length).fill(false); - dfs(arr, 0, prev, record, res); - return res; -}; - -function dfs(arr, depth, prev, record, res) { - if (depth == arr.length) { - res.push(prev.join('')); - return; - } - for (let i = 0; i < arr.length; i++) { - if (record[i]) { - continue; + const n = S.length; + const vis = Array(n).fill(false); + const ans = []; + const t = []; + const dfs = i => { + if (i >= n) { + ans.push(t.join('')); + return; } - prev.push(arr[i]); - record[i] = true; - dfs(arr, depth + 1, prev, record, res); - prev.pop(); - record[i] = false; - } -} + for (let j = 0; j < n; ++j) { + if (vis[j]) { + continue; + } + vis[j] = true; + t.push(S[j]); + dfs(i + 1); + t.pop(); + vis[j] = false; + } + }; + dfs(0); + return ans; +}; ``` diff --git a/lcci/08.07.Permutation I/README_EN.md b/lcci/08.07.Permutation I/README_EN.md index ac04b96e870c3..0df6211f3a1f0 100644 --- a/lcci/08.07.Permutation I/README_EN.md +++ b/lcci/08.07.Permutation I/README_EN.md @@ -35,57 +35,65 @@ ## Solutions -### Solution 1 +### Solution 1: DFS (Backtracking) + +We design a function $dfs(i)$ to represent that the first $i$ positions have been filled, and now the $i+1$ position needs to be filled. We enumerate all possible characters, if this character has not been filled, we fill in this character, and then continue to fill the next position until all positions are filled. + +The time complexity is $O(n \times n!)$, where $n$ is the length of the string. There are $n!$ permutations in total, and each permutation takes $O(n)$ time to construct. ```python class Solution: def permutation(self, S: str) -> List[str]: - def dfs(u, t): - if u == n: - ans.append(''.join(t)) + def dfs(i: int): + if i == n: + ans.append("".join(t)) return - for i in range(n): - if vis[i]: + for j, c in enumerate(S): + if vis[j]: continue - vis[i] = True - t.append(S[i]) - dfs(u + 1, t) + vis[j] = True + t.append(c) + dfs(i + 1) t.pop() - vis[i] = False + vis[j] = False n = len(S) vis = [False] * n ans = [] - dfs(0, []) + t = [] + dfs(0) return ans ``` ```java class Solution { + private char[] s; + private boolean[] vis = new boolean['z' + 1]; + private List ans = new ArrayList<>(); + private StringBuilder t = new StringBuilder(); + public String[] permutation(String S) { - Set vis = new HashSet<>(); - List ans = new ArrayList<>(); - StringBuilder t = new StringBuilder(); - dfs(0, S, t, ans, vis); + s = S.toCharArray(); + dfs(0); return ans.toArray(new String[0]); } - private void dfs(int u, String S, StringBuilder t, List ans, Set vis) { - if (u == S.length()) { + private void dfs(int i) { + if (i == s.length) { ans.add(t.toString()); return; } - for (char c : S.toCharArray()) { - if (vis.contains(c)) { + for (char c : s) { + if (vis[c]) { continue; } - vis.add(c); + vis[c] = true; t.append(c); - dfs(u + 1, S, t, ans, vis); + dfs(i + 1); t.deleteCharAt(t.length() - 1); - vis.remove(c); + vis[c] = false; } } } @@ -95,54 +103,82 @@ class Solution { class Solution { public: vector permutation(string S) { - unordered_set vis; + int n = S.size(); + vector vis(n); vector ans; - string t = ""; - dfs(0, S, t, ans, vis); + string t; + function dfs = [&](int i) { + if (i >= n) { + ans.push_back(t); + return; + } + for (int j = 0; j < n; ++j) { + if (vis[j]) { + continue; + } + vis[j] = true; + t.push_back(S[j]); + dfs(i + 1); + t.pop_back(); + vis[j] = false; + } + }; + dfs(0); return ans; } - - void dfs(int u, string& S, string& t, vector& ans, unordered_set& vis) { - if (u == S.size()) { - ans.push_back(t); - return; - } - for (char& c : S) { - if (vis.count(c)) continue; - vis.insert(c); - t.push_back(c); - dfs(u + 1, S, t, ans, vis); - vis.erase(c); - t.pop_back(); - } - } }; ``` ```go -func permutation(S string) []string { - vis := make(map[byte]bool) - var ans []string - var t []byte - var dfs func(u int, t []byte) - dfs = func(u int, t []byte) { - if u == len(S) { +func permutation(S string) (ans []string) { + t := []byte{} + vis := make([]bool, len(S)) + var dfs func(int) + dfs = func(i int) { + if i >= len(S) { ans = append(ans, string(t)) return } - for i := range S { - if vis[S[i]] { + for j := range S { + if vis[j] { continue } - vis[S[i]] = true - t = append(t, S[i]) - dfs(u+1, t) - vis[S[i]] = false + vis[j] = true + t = append(t, S[j]) + dfs(i + 1) t = t[:len(t)-1] + vis[j] = false } } - dfs(0, t) - return ans + dfs(0) + return +} +``` + +```ts +function permutation(S: string): string[] { + const n = S.length; + const vis: boolean[] = Array(n).fill(false); + const ans: string[] = []; + const t: string[] = []; + const dfs = (i: number) => { + if (i >= n) { + ans.push(t.join('')); + return; + } + for (let j = 0; j < n; ++j) { + if (vis[j]) { + continue; + } + vis[j] = true; + t.push(S[j]); + dfs(i + 1); + t.pop(); + vis[j] = false; + } + }; + dfs(0); + return ans; } ``` @@ -152,30 +188,29 @@ func permutation(S string) []string { * @return {string[]} */ var permutation = function (S) { - let res = []; - let arr = [...S]; - let prev = []; - let record = new Array(S.length).fill(false); - dfs(arr, 0, prev, record, res); - return res; -}; - -function dfs(arr, depth, prev, record, res) { - if (depth == arr.length) { - res.push(prev.join('')); - return; - } - for (let i = 0; i < arr.length; i++) { - if (record[i]) { - continue; + const n = S.length; + const vis = Array(n).fill(false); + const ans = []; + const t = []; + const dfs = i => { + if (i >= n) { + ans.push(t.join('')); + return; } - prev.push(arr[i]); - record[i] = true; - dfs(arr, depth + 1, prev, record, res); - prev.pop(); - record[i] = false; - } -} + for (let j = 0; j < n; ++j) { + if (vis[j]) { + continue; + } + vis[j] = true; + t.push(S[j]); + dfs(i + 1); + t.pop(); + vis[j] = false; + } + }; + dfs(0); + return ans; +}; ``` diff --git a/lcci/08.07.Permutation I/Solution.cpp b/lcci/08.07.Permutation I/Solution.cpp index efec2b97d3bd0..21a09c6485db8 100644 --- a/lcci/08.07.Permutation I/Solution.cpp +++ b/lcci/08.07.Permutation I/Solution.cpp @@ -1,25 +1,27 @@ class Solution { public: vector permutation(string S) { - unordered_set vis; + int n = S.size(); + vector vis(n); vector ans; - string t = ""; - dfs(0, S, t, ans, vis); + string t; + function dfs = [&](int i) { + if (i >= n) { + ans.push_back(t); + return; + } + for (int j = 0; j < n; ++j) { + if (vis[j]) { + continue; + } + vis[j] = true; + t.push_back(S[j]); + dfs(i + 1); + t.pop_back(); + vis[j] = false; + } + }; + dfs(0); return ans; } - - void dfs(int u, string& S, string& t, vector& ans, unordered_set& vis) { - if (u == S.size()) { - ans.push_back(t); - return; - } - for (char& c : S) { - if (vis.count(c)) continue; - vis.insert(c); - t.push_back(c); - dfs(u + 1, S, t, ans, vis); - vis.erase(c); - t.pop_back(); - } - } }; \ No newline at end of file diff --git a/lcci/08.07.Permutation I/Solution.go b/lcci/08.07.Permutation I/Solution.go index dc2376b6d2f4a..20d5c55fded5f 100644 --- a/lcci/08.07.Permutation I/Solution.go +++ b/lcci/08.07.Permutation I/Solution.go @@ -1,24 +1,23 @@ -func permutation(S string) []string { - vis := make(map[byte]bool) - var ans []string - var t []byte - var dfs func(u int, t []byte) - dfs = func(u int, t []byte) { - if u == len(S) { +func permutation(S string) (ans []string) { + t := []byte{} + vis := make([]bool, len(S)) + var dfs func(int) + dfs = func(i int) { + if i >= len(S) { ans = append(ans, string(t)) return } - for i := range S { - if vis[S[i]] { + for j := range S { + if vis[j] { continue } - vis[S[i]] = true - t = append(t, S[i]) - dfs(u+1, t) - vis[S[i]] = false + vis[j] = true + t = append(t, S[j]) + dfs(i + 1) t = t[:len(t)-1] + vis[j] = false } } - dfs(0, t) - return ans + dfs(0) + return } \ No newline at end of file diff --git a/lcci/08.07.Permutation I/Solution.java b/lcci/08.07.Permutation I/Solution.java index 0dc4c679e8202..896ed99f9d1ea 100644 --- a/lcci/08.07.Permutation I/Solution.java +++ b/lcci/08.07.Permutation I/Solution.java @@ -1,26 +1,29 @@ class Solution { + private char[] s; + private boolean[] vis = new boolean['z' + 1]; + private List ans = new ArrayList<>(); + private StringBuilder t = new StringBuilder(); + public String[] permutation(String S) { - Set vis = new HashSet<>(); - List ans = new ArrayList<>(); - StringBuilder t = new StringBuilder(); - dfs(0, S, t, ans, vis); + s = S.toCharArray(); + dfs(0); return ans.toArray(new String[0]); } - private void dfs(int u, String S, StringBuilder t, List ans, Set vis) { - if (u == S.length()) { + private void dfs(int i) { + if (i == s.length) { ans.add(t.toString()); return; } - for (char c : S.toCharArray()) { - if (vis.contains(c)) { + for (char c : s) { + if (vis[c]) { continue; } - vis.add(c); + vis[c] = true; t.append(c); - dfs(u + 1, S, t, ans, vis); + dfs(i + 1); t.deleteCharAt(t.length() - 1); - vis.remove(c); + vis[c] = false; } } } \ No newline at end of file diff --git a/lcci/08.07.Permutation I/Solution.js b/lcci/08.07.Permutation I/Solution.js index bbe3003cbbcf8..f1dcb5d98f69f 100644 --- a/lcci/08.07.Permutation I/Solution.js +++ b/lcci/08.07.Permutation I/Solution.js @@ -3,27 +3,26 @@ * @return {string[]} */ var permutation = function (S) { - let res = []; - let arr = [...S]; - let prev = []; - let record = new Array(S.length).fill(false); - dfs(arr, 0, prev, record, res); - return res; -}; - -function dfs(arr, depth, prev, record, res) { - if (depth == arr.length) { - res.push(prev.join('')); - return; - } - for (let i = 0; i < arr.length; i++) { - if (record[i]) { - continue; + const n = S.length; + const vis = Array(n).fill(false); + const ans = []; + const t = []; + const dfs = i => { + if (i >= n) { + ans.push(t.join('')); + return; + } + for (let j = 0; j < n; ++j) { + if (vis[j]) { + continue; + } + vis[j] = true; + t.push(S[j]); + dfs(i + 1); + t.pop(); + vis[j] = false; } - prev.push(arr[i]); - record[i] = true; - dfs(arr, depth + 1, prev, record, res); - prev.pop(); - record[i] = false; - } -} + }; + dfs(0); + return ans; +}; diff --git a/lcci/08.07.Permutation I/Solution.py b/lcci/08.07.Permutation I/Solution.py index 86e9be8496d31..537c2f0484bb7 100644 --- a/lcci/08.07.Permutation I/Solution.py +++ b/lcci/08.07.Permutation I/Solution.py @@ -1,20 +1,21 @@ class Solution: def permutation(self, S: str) -> List[str]: - def dfs(u, t): - if u == n: - ans.append(''.join(t)) + def dfs(i: int): + if i == n: + ans.append("".join(t)) return - for i in range(n): - if vis[i]: + for j, c in enumerate(S): + if vis[j]: continue - vis[i] = True - t.append(S[i]) - dfs(u + 1, t) + vis[j] = True + t.append(c) + dfs(i + 1) t.pop() - vis[i] = False + vis[j] = False n = len(S) vis = [False] * n ans = [] - dfs(0, []) + t = [] + dfs(0) return ans diff --git a/lcci/08.07.Permutation I/Solution.ts b/lcci/08.07.Permutation I/Solution.ts new file mode 100644 index 0000000000000..251a7ad6d6b76 --- /dev/null +++ b/lcci/08.07.Permutation I/Solution.ts @@ -0,0 +1,24 @@ +function permutation(S: string): string[] { + const n = S.length; + const vis: boolean[] = Array(n).fill(false); + const ans: string[] = []; + const t: string[] = []; + const dfs = (i: number) => { + if (i >= n) { + ans.push(t.join('')); + return; + } + for (let j = 0; j < n; ++j) { + if (vis[j]) { + continue; + } + vis[j] = true; + t.push(S[j]); + dfs(i + 1); + t.pop(); + vis[j] = false; + } + }; + dfs(0); + return ans; +}