File tree Expand file tree Collapse file tree 3 files changed +99
-0
lines changed
Expand file tree Collapse file tree 3 files changed +99
-0
lines changed Original file line number Diff line number Diff line change 8484148. 排序链表
8585151. 颠倒字符串中的单词
8686152. 乘积最大子数组
87+ 153. 寻找旋转排序数组中的最小值
8788155. 最小栈
8889160. 相交链表
8990162. 寻找峰值
Original file line number Diff line number Diff line change 17017088. 合并两个有序数组(排序,双指针)
171171128. 最长连续序列(集合,排序)
172172136. 只出现一次的数字(哈希表,列表,位运算)
173+ 153. 寻找旋转排序数组中的最小值(二分查找)
173174162. 寻找峰值(二分查找)
174175169. 多数元素(排序,哈希表,投票,计数,分治)
175176215. 数组中的第K个最大元素(快速排序,堆排序)
Original file line number Diff line number Diff line change 1+ // 153. 寻找旋转排序数组中的最小值
2+
3+
4+ /*
5+ 二分查找:二分寻找最小值索引
6+
7+ 递增序列:
8+ *
9+ *
10+ *
11+ *
12+ *
13+ ==============
14+ 旋转序列:
15+ 1)旋转后的左段最小值大于右段最大值
16+ 2)中点在断崖左段时 nums[mid] > nums[right],最小值在右半部分
17+ 3)中点在断崖右段时 nums[mid] < nums[right],最小值在左半部分
18+ *
19+ *
20+ *
21+ *
22+ *
23+
24+ 3 4 5 1 2
25+ ↑ ↑ ↑
26+ l mid r
27+ ==============
28+ 3 4 5 1 2
29+ ↑ ↑
30+ l/mid r
31+ ==============
32+ 3 4 5 1 2
33+ ↑
34+ l/r
35+ */
36+ class Solution {
37+ public int findMin (int [] nums ) {
38+ int left = 0 , right = nums .length - 1 ; // 左闭右闭区间,如果用右开区间则不方便判断右值
39+ while (left < right ) { // 循环不变式,如果left == right,则循环结束
40+ int mid = (left + right ) / 2 ; // 向下取整,mid更靠近left,即 left <= mid < right,mid右边的元素必然存在,所以要跟右值比较
41+ if (nums [mid ] < nums [right ]) { // 中值小于右值,则右半部分必然递增,最小值在左半部分,收缩右边界
42+ right = mid ; // 由于中值是小值,所以也可能是最小值,右边界要包括中值
43+ } else {
44+ left = mid + 1 ; // 中值大于右值,最小值在右半部分,由于中值是大值,所以左边界不用包括中值
45+ }
46+ }
47+ return nums [left ]; // 循环结束,left == right,返回最小值
48+ }
49+ }
50+
51+
52+ /*
53+ 二分查找:二分寻找最大值索引,下一位就是最小值,索引加1对数组长度取余 即为最小值索引
54+
55+ 3 4 5 1 2
56+ ↑ ↑ ↑
57+ l mid r
58+ ==============
59+ 3 4 5 1 2
60+ ↑ ↑ ↑
61+ l mid r
62+ ==============
63+ 3 4 5 1 2
64+ ↑
65+ l/r
66+ */
67+ class Solution {
68+ public int findMin (int [] nums ) {
69+ int n = nums .length ;
70+ int left = 0 , right = n - 1 ; // 左闭右闭区间,如果用左开区间则不方便判断左值
71+ while (left < right ) { // 循环不变式,如果left == right,则循环结束
72+ int mid = (left + right + 1 ) / 2 ; // 先加1再向下取整,mid更靠近right,即 left < mid <= right,mid左边的元素必然存在,所以要跟左值比较
73+ if (nums [left ] < nums [mid ]) { // 左值小于中值,则左半部分必然递增,最大值在左半部分,收缩左边界
74+ left = mid ; // 由于中值是大值,所以也可能是最大值,左边界要包括中值
75+ } else {
76+ right = mid - 1 ; // 左值大于中值,最大值在左半部分,由于中值是小值,所以右边界不用包括中值
77+ }
78+ }
79+ return nums [(left + 1 ) % n ]; // 最大值下一位就是最小值
80+ }
81+ }
82+
83+
84+ /*
85+ 一次遍历,当前元素小于前一元素时,该元素时最小值
86+ */
87+ class Solution {
88+ public int findMin (int [] nums ) {
89+ int n = nums .length ;
90+ for (int i = 1 ; i < n ; i ++) {
91+ if (nums [i ] < nums [i - 1 ]) {
92+ return nums [i ];
93+ }
94+ }
95+ return nums [0 ];
96+ }
97+ }
You can’t perform that action at this time.
0 commit comments