Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 5ad2c28

Browse files
authored
feat: add solutions to lc problem: No.1901 (doocs#2101)
No.1901.Find a Peak Element II
1 parent be97b13 commit 5ad2c28

File tree

8 files changed

+418
-2
lines changed

8 files changed

+418
-2
lines changed

solution/1900-1999/1901.Find a Peak Element II/README.md

Lines changed: 153 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,22 +54,174 @@
5454

5555
<!-- 这里可写通用的实现逻辑 -->
5656

57+
**方法一:二分查找**
58+
59+
记 $m$ 和 $n$ 分别为矩阵的行数和列数。
60+
61+
题目要求我们寻找峰值,并且时间复杂度为 $O(m \times \log n)$ 或 $O(n \times \log m)$,那么我们可以考虑使用二分查找。
62+
63+
我们考虑第 $i$ 行的最大值,不妨将其下标记为 $j$。
64+
65+
如果 $mat[i][j] \gt mat[i + 1][j]$,那么第 $[0,..i]$ 行中必然存在一个峰值,我们只需要在第 $[0,..i]$ 行中找到最大值即可。同理,如果 $mat[i][j] \lt mat[i + 1][j]$,那么第 $[i + 1,..m - 1]$ 行中必然存在一个峰值,我们只需要在第 $[i + 1,..m - 1]$ 行中找到最大值即可。
66+
67+
为什么上述做法是对的?我们不妨用反证法来证明。
68+
69+
如果 $mat[i][j] \gt mat[i + 1][j]$,假设第 $[0,..i]$ 行中不存在峰值,那么 $mat[i][j]$ 不是峰值,而由于 $mat[i][j]$ 是第 $i$ 行的最大值,并且 $mat[i][j] \gt mat[i + 1][j]$,那么 $mat[i][j] \lt mat[i - 1][j]$。我们继续从第 $i - 1$ 行往上考虑,每一行的最大值都小于上一行的最大值。那么当遍历到 $i = 0$ 时,由于矩阵中的元素都是正整数,并且矩阵周边一圈的格子的值都为 $-1$。因此,在第 $0$ 行时,其最大值大于其所有相邻元素,那么第 $0$ 行的最大值就是峰值,与假设矛盾。因此,第 $[0,..i]$ 行中必然存在一个峰值。
70+
71+
对于 $mat[i][j] \lt mat[i + 1][j]$ 的情况,我们可以用类似的方法证明第 $[i + 1,..m - 1]$ 行中必然存在一个峰值。
72+
73+
因此,我们可以使用二分查找来寻找峰值。
74+
75+
我们二分查找矩阵的行,初始时查找的边界为 $l = 0$, $r = m - 1$。每一次,我们找到当前的中间行 $mid$,并找到该行的最大值下标 $j$。如果 $mat[mid][j] \gt mat[mid + 1][j]$,那么我们就在第 $[0,..mid]$ 行中寻找峰值,即更新 $r = mid$。否则,我们就在第 $[mid + 1,..m - 1]$ 行中寻找峰值,即更新 $l = mid + 1$。当 $l = r$ 时,我们就找到了峰值所在的位置 $[l, j_l]$。其中 $j_l$ 是第 $l$ 行的最大值下标。
76+
77+
时间复杂度 $O(n \times \log m)$,其中 $m$ 和 $n$ 分别为矩阵的行数和列数。二分查找的时间复杂度为 $O(\log m)$,每次二分查找时,我们需要遍历第 $mid$ 行的所有元素,时间复杂度为 $O(n)$。空间复杂度 $O(1)$。
78+
5779
<!-- tabs:start -->
5880

5981
### **Python3**
6082

6183
<!-- 这里可写当前语言的特殊实现逻辑 -->
6284

6385
```python
64-
86+
class Solution:
87+
def findPeakGrid(self, mat: List[List[int]]) -> List[int]:
88+
l, r = 0, len(mat) - 1
89+
while l < r:
90+
mid = (l + r) >> 1
91+
j = mat[mid].index(max(mat[mid]))
92+
if mat[mid][j] > mat[mid + 1][j]:
93+
r = mid
94+
else:
95+
l = mid + 1
96+
return [l, mat[l].index(max(mat[l]))]
6597
```
6698

6799
### **Java**
68100

69101
<!-- 这里可写当前语言的特殊实现逻辑 -->
70102

71103
```java
104+
class Solution {
105+
public int[] findPeakGrid(int[][] mat) {
106+
int l = 0, r = mat.length - 1;
107+
int n = mat[0].length;
108+
while (l < r) {
109+
int mid = (l + r) >> 1;
110+
int j = maxPos(mat[mid]);
111+
if (mat[mid][j] > mat[mid + 1][j]) {
112+
r = mid;
113+
} else {
114+
l = mid + 1;
115+
}
116+
}
117+
return new int[] {l, maxPos(mat[l])};
118+
}
119+
120+
private int maxPos(int[] arr) {
121+
int j = 0;
122+
for (int i = 1; i < arr.length; ++i) {
123+
if (arr[j] < arr[i]) {
124+
j = i;
125+
}
126+
}
127+
return j;
128+
}
129+
}
130+
```
131+
132+
### **C++**
133+
134+
```cpp
135+
class Solution {
136+
public:
137+
vector<int> findPeakGrid(vector<vector<int>>& mat) {
138+
int l = 0, r = mat.size() - 1;
139+
while (l < r) {
140+
int mid = (l + r) >> 1;
141+
int j = distance(mat[mid].begin(), max_element(mat[mid].begin(), mat[mid].end()));
142+
if (mat[mid][j] > mat[mid + 1][j]) {
143+
r = mid;
144+
} else {
145+
l = mid + 1;
146+
}
147+
}
148+
int j = distance(mat[l].begin(), max_element(mat[l].begin(), mat[l].end()));
149+
return {l, j};
150+
}
151+
};
152+
```
153+
154+
### **Go**
155+
156+
```go
157+
func findPeakGrid(mat [][]int) []int {
158+
maxPos := func(arr []int) int {
159+
j := 0
160+
for i := 1; i < len(arr); i++ {
161+
if arr[i] > arr[j] {
162+
j = i
163+
}
164+
}
165+
return j
166+
}
167+
l, r := 0, len(mat)-1
168+
for l < r {
169+
mid := (l + r) >> 1
170+
j := maxPos(mat[mid])
171+
if mat[mid][j] > mat[mid+1][j] {
172+
r = mid
173+
} else {
174+
l = mid + 1
175+
}
176+
}
177+
return []int{l, maxPos(mat[l])}
178+
}
179+
```
180+
181+
### **TypeScript**
182+
183+
```ts
184+
function findPeakGrid(mat: number[][]): number[] {
185+
let [l, r] = [0, mat.length - 1];
186+
while (l < r) {
187+
const mid = (l + r) >> 1;
188+
const j = mat[mid].indexOf(Math.max(...mat[mid]));
189+
if (mat[mid][j] > mat[mid + 1][j]) {
190+
r = mid;
191+
} else {
192+
l = mid + 1;
193+
}
194+
}
195+
return [l, mat[l].indexOf(Math.max(...mat[l]))];
196+
}
197+
```
72198

199+
### **Rust**
200+
201+
```rust
202+
impl Solution {
203+
pub fn find_peak_grid(mat: Vec<Vec<i32>>) -> Vec<i32> {
204+
let mut l: usize = 0;
205+
let mut r: usize = mat.len() - 1;
206+
while l < r {
207+
let mid: usize = (l + r) >> 1;
208+
let j: usize = mat[mid]
209+
.iter()
210+
.position(|&x| x == *mat[mid].iter().max().unwrap())
211+
.unwrap();
212+
if mat[mid][j] > mat[mid + 1][j] {
213+
r = mid;
214+
} else {
215+
l = mid + 1;
216+
}
217+
}
218+
let j: usize = mat[l]
219+
.iter()
220+
.position(|&x| x == *mat[l].iter().max().unwrap())
221+
.unwrap();
222+
vec![l as i32, j as i32]
223+
}
224+
}
73225
```
74226

75227
### **...**

solution/1900-1999/1901.Find a Peak Element II/README_EN.md

Lines changed: 153 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,18 +46,170 @@
4646

4747
## Solutions
4848

49+
**Solution 1: Binary Search**
50+
51+
Let $m$ and $n$ be the number of rows and columns of the matrix, respectively.
52+
53+
The problem asks us to find a peak, and the time complexity should be $O(m \times \log n)$ or $O(n \times \log m)$. Therefore, we can consider using binary search.
54+
55+
We consider the maximum value of the $i$-th row, and denote its index as $j$.
56+
57+
If $mat[i][j] > mat[i + 1][j]$, then there must be a peak in the rows $[0,..i]$. We only need to find the maximum value in these rows. Similarly, if $mat[i][j] < mat[i + 1][j]$, then there must be a peak in the rows $[i + 1,..m - 1]$. We only need to find the maximum value in these rows.
58+
59+
Why is the above method correct? We can prove it by contradiction.
60+
61+
If $mat[i][j] > mat[i + 1][j]$, suppose there is no peak in the rows $[0,..i]$. Then $mat[i][j]$ is not a peak. Since $mat[i][j]$ is the maximum value of the $i$-th row, and $mat[i][j] > mat[i + 1][j]$, then $mat[i][j] < mat[i - 1][j]$. We continue to consider from the $(i - 1)$-th row upwards, and the maximum value of each row is less than the maximum value of the previous row. When we traverse to $i = 0$, since all elements in the matrix are positive integers, and the values of the cells around the matrix are $-1$. Therefore, at the 0-th row, its maximum value is greater than all its adjacent elements, so the maximum value of the 0-th row is a peak, which contradicts the assumption. Therefore, there must be a peak in the rows $[0,..i]$.
62+
63+
For the case where $mat[i][j] < mat[i + 1][j]$, we can prove in a similar way that there must be a peak in the rows $[i + 1,..m - 1]$.
64+
65+
Therefore, we can use binary search to find the peak.
66+
67+
We perform binary search on the rows of the matrix, initially with the search boundaries $l = 0$, $r = m - 1$. Each time, we find the middle row $mid$ and find the index $j$ of the maximum value of this row. If $mat[mid][j] > mat[mid + 1][j]$, then we search for the peak in the rows $[0,..mid]$, i.e., update $r = mid$. Otherwise, we search for the peak in the rows $[mid + 1,..m - 1]$, i.e., update $l = mid + 1$. When $l = r$, we find the position $[l, j_l]$ of the peak, where $j_l$ is the index of the maximum value of the $l$-th row.
68+
69+
The time complexity is $O(n \times \log m)$, where $m$ and $n$ are the number of rows and columns of the matrix, respectively. The time complexity of binary search is $O(\log m)$, and each time we perform binary search, we need to traverse all elements of the $mid$-th row, with a time complexity of $O(n)$. The space complexity is $O(1)$.
70+
4971
<!-- tabs:start -->
5072

5173
### **Python3**
5274

5375
```python
54-
76+
class Solution:
77+
def findPeakGrid(self, mat: List[List[int]]) -> List[int]:
78+
l, r = 0, len(mat) - 1
79+
while l < r:
80+
mid = (l + r) >> 1
81+
j = mat[mid].index(max(mat[mid]))
82+
if mat[mid][j] > mat[mid + 1][j]:
83+
r = mid
84+
else:
85+
l = mid + 1
86+
return [l, mat[l].index(max(mat[l]))]
5587
```
5688

5789
### **Java**
5890

5991
```java
92+
class Solution {
93+
public int[] findPeakGrid(int[][] mat) {
94+
int l = 0, r = mat.length - 1;
95+
int n = mat[0].length;
96+
while (l < r) {
97+
int mid = (l + r) >> 1;
98+
int j = maxPos(mat[mid]);
99+
if (mat[mid][j] > mat[mid + 1][j]) {
100+
r = mid;
101+
} else {
102+
l = mid + 1;
103+
}
104+
}
105+
return new int[] {l, maxPos(mat[l])};
106+
}
107+
108+
private int maxPos(int[] arr) {
109+
int j = 0;
110+
for (int i = 1; i < arr.length; ++i) {
111+
if (arr[j] < arr[i]) {
112+
j = i;
113+
}
114+
}
115+
return j;
116+
}
117+
}
118+
```
119+
120+
### **C++**
121+
122+
```cpp
123+
class Solution {
124+
public:
125+
vector<int> findPeakGrid(vector<vector<int>>& mat) {
126+
int l = 0, r = mat.size() - 1;
127+
while (l < r) {
128+
int mid = (l + r) >> 1;
129+
int j = distance(mat[mid].begin(), max_element(mat[mid].begin(), mat[mid].end()));
130+
if (mat[mid][j] > mat[mid + 1][j]) {
131+
r = mid;
132+
} else {
133+
l = mid + 1;
134+
}
135+
}
136+
int j = distance(mat[l].begin(), max_element(mat[l].begin(), mat[l].end()));
137+
return {l, j};
138+
}
139+
};
140+
```
141+
142+
### **Go**
143+
144+
```go
145+
func findPeakGrid(mat [][]int) []int {
146+
maxPos := func(arr []int) int {
147+
j := 0
148+
for i := 1; i < len(arr); i++ {
149+
if arr[i] > arr[j] {
150+
j = i
151+
}
152+
}
153+
return j
154+
}
155+
l, r := 0, len(mat)-1
156+
for l < r {
157+
mid := (l + r) >> 1
158+
j := maxPos(mat[mid])
159+
if mat[mid][j] > mat[mid+1][j] {
160+
r = mid
161+
} else {
162+
l = mid + 1
163+
}
164+
}
165+
return []int{l, maxPos(mat[l])}
166+
}
167+
```
168+
169+
### **TypeScript**
170+
171+
```ts
172+
function findPeakGrid(mat: number[][]): number[] {
173+
let [l, r] = [0, mat.length - 1];
174+
while (l < r) {
175+
const mid = (l + r) >> 1;
176+
const j = mat[mid].indexOf(Math.max(...mat[mid]));
177+
if (mat[mid][j] > mat[mid + 1][j]) {
178+
r = mid;
179+
} else {
180+
l = mid + 1;
181+
}
182+
}
183+
return [l, mat[l].indexOf(Math.max(...mat[l]))];
184+
}
185+
```
60186

187+
### **Rust**
188+
189+
```rust
190+
impl Solution {
191+
pub fn find_peak_grid(mat: Vec<Vec<i32>>) -> Vec<i32> {
192+
let mut l: usize = 0;
193+
let mut r: usize = mat.len() - 1;
194+
while l < r {
195+
let mid: usize = (l + r) >> 1;
196+
let j: usize = mat[mid]
197+
.iter()
198+
.position(|&x| x == *mat[mid].iter().max().unwrap())
199+
.unwrap();
200+
if mat[mid][j] > mat[mid + 1][j] {
201+
r = mid;
202+
} else {
203+
l = mid + 1;
204+
}
205+
}
206+
let j: usize = mat[l]
207+
.iter()
208+
.position(|&x| x == *mat[l].iter().max().unwrap())
209+
.unwrap();
210+
vec![l as i32, j as i32]
211+
}
212+
}
61213
```
62214

63215
### **...**
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
class Solution {
2+
public:
3+
vector<int> findPeakGrid(vector<vector<int>>& mat) {
4+
int l = 0, r = mat.size() - 1;
5+
while (l < r) {
6+
int mid = (l + r) >> 1;
7+
int j = distance(mat[mid].begin(), max_element(mat[mid].begin(), mat[mid].end()));
8+
if (mat[mid][j] > mat[mid + 1][j]) {
9+
r = mid;
10+
} else {
11+
l = mid + 1;
12+
}
13+
}
14+
int j = distance(mat[l].begin(), max_element(mat[l].begin(), mat[l].end()));
15+
return {l, j};
16+
}
17+
};
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
func findPeakGrid(mat [][]int) []int {
2+
maxPos := func(arr []int) int {
3+
j := 0
4+
for i := 1; i < len(arr); i++ {
5+
if arr[i] > arr[j] {
6+
j = i
7+
}
8+
}
9+
return j
10+
}
11+
l, r := 0, len(mat)-1
12+
for l < r {
13+
mid := (l + r) >> 1
14+
j := maxPos(mat[mid])
15+
if mat[mid][j] > mat[mid+1][j] {
16+
r = mid
17+
} else {
18+
l = mid + 1
19+
}
20+
}
21+
return []int{l, maxPos(mat[l])}
22+
}

0 commit comments

Comments
 (0)