class Solution {
public int minArray(int[] nums) {
int l = 0, r = nums.length - 1;
while (l < r) {
int mid = l + r >> 1;
if (nums[mid] > nums[r]) l = mid + 1;
else if (nums[mid] < nums[r]) r = mid;
else r--;
}
return nums[l];
}
}
class Solution {
public:
int minArray(vector<int>& numbers) {
int i = 0;
int j = numbers.size()-1;
while(i<j){
int m = i + (j-i)/2;
if(numbers[m] < numbers[j]){
//说明旋转点在m的左边
j = m;
}else if(numbers[m] > numbers[j]) i = m+1;//说明旋转点在m右边
else j--;
}
return numbers[i];
}
};
func minArray(numbers []int) int {
l := 0
r := len(numbers) - 1
var m int
for l < r {
m = l + (r - l) / 2
//判断在左序列还是右序列
if numbers[m] > numbers[r] {
l = m + 1
}else if numbers[m] < numbers[r] {
r = m
}else{
r = r - 1
}
}
return numbers[l]
}
class Solution {
public int minArray(int[] numbers) {
int min = numbers[0];
for (int i = 1; i < numbers.length; i ++) {
if (min > numbers[i]) {
min = numbers[i];
}
}
return min;
}
}
class Solution {
public int minArray(int[] numbers) {
int left = 0, right = numbers.length - 1;
while (left < right) {
if (numbers[left] < numbers[right]) {
return numbers[left];
}
int mid = (left + right) / 2;
if (numbers[left] < numbers[mid]) {
left = mid + 1;
} else if (numbers[left] > numbers[mid]) {
right = mid;
} else if (numbers[left] == numbers[mid]) {
left = left + 1;
}
}
return numbers[left];
}
}
//寻找最小元素即为寻找旋转点
class Solution {
public int minArray(int[] numbers) {
int l = 0, r = numbers.length - 1;
while (l < r) {
int mid = l + (r - l) / 2;
if(numbers[mid] > numbers[r])
l = mid + 1; //旋转点在右侧
else if(numbers[mid] < numbers[r])
r = mid; //旋转点在左侧
else
r = r - 1; //无法确定旋转点的位置,但可以缩小范围
}
return numbers[l];
}
}
class Solution {
public int minArray(int[] numbers) {
//把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。
int left = 0,right = numbers.length-1;
while(left<right){
if(numbers[left]<numbers[right]){
return numbers[left];
}
int mid =(right+left)/2;
if(numbers[mid]>numbers[left]){
left = mid+1;
}else if(numbers[mid]<numbers[left]){
right = mid;
}else{
left++;
}
}
return numbers[left];
}
}
class Solution:
def minArray(self, numbers: List[int]) -> int:
if len(numbers)==1: return numbers[0]
left ,right= 0,len(numbers)-1
while numbers[left]>=numbers[right]and left<right:
r = numbers.pop(0)
numbers.append(r)
right = right-1
return numbers[0]
#一开始是这个想法,但左右和中值关系没有想明白
class Solution:
def minArray(self, numbers: [int]) -> int:
i, j = 0, len(numbers) - 1
while i < j:
m = (i + j) // 2
if numbers[m] > numbers[j]: i = m + 1
elif numbers[m] < numbers[j]: j = m
else: j -= 1
return numbers[i]
public class Solution4 {
//时间复杂度O(logn)
//空间复杂度O(1)
public int minArray(int[] numbers) {
if(numbers == null||numbers.length == 0)return 0;
int l = 0,r = numbers.length - 1;
while (l != r){
if(numbers[l] < numbers[r]) return numbers[l];
int m = (l + r)/2;
if(numbers[m] > numbers[l]){
l = m + 1;
} else if (numbers[m] < numbers[l]) {
r = m;
} else{
l++;
}
}
return numbers[l];
}
}
class Solution {
public int minArray(int[] numbers) {
int l = 0;
int r = numbers.length - 1;
while (l < r) {
if (numbers[l] < numbers[r]) {
return numbers[l];
}
int mid = (l + r) / 2;
if (numbers[mid] > numbers[l]) {
l = mid + 1;
} else if (numbers[mid] < numbers[r]) {
r = mid;
} else {
l++;
}
}
return numbers[l];
}
}
class Solution:
def minArray(self, numbers: List[int]) -> int:
if numbers[0] < numbers[-1]:
return numbers[0]
l, r = 0, len(numbers) - 1
while l < r:
m = (l + r) // 2
if numbers[m] > numbers[r]:
l = m + 1
elif numbers[m] < numbers[r]:
r = m
else:
r -= 1
return numbers[l]
共以下 33 个回答
时间复杂度:O(N)
空间复杂度:O(1)
时间O(log2N) 空间O(1)
时间复杂度O(logn)
时间复杂度:O(n),从右向左遍历,最坏情况遍历n-1次
空间复杂度:O(1)
思路一:顺序遍历整个数组,记录最小的元素。时间复杂度O(N),空间复杂度O(1)。
思路二: 利用整个数组是递增的,采用二分查找的思想。比如[1,2,3,4,5]旋转3次后为4,5,1,2,3,初始时left=0,right=4,mid=2,所以numbers[right]>numbers[mid],说明中间的元素位于第二个递增子数组。跟新right=mid,更新一次时left=0,right=2,mid=1,数组范围[4,5,1],所以numbers[left]<numbers[mid],说明中间的元素位于第一个的递增子数组中,更新left=mid,更新二次时left=1,right=2,mid=2,数组范围[5,1],right-left=1,两个指针相邻,所以让mid=right=2,结束循环,返回numbers[1]。这种思路找到第一个递增子数组和第二个递增子数组的分界点。时间复杂度O(logN),空间复杂度O(1)。
思路三:寻找旋转点。比如数组[3,4,5,6,7,0,1,2],初始时left=0,right=7,mid=3,所以numbers[left]<numbers[mid],跟新left=mid+1,更新一次时left=3,right=7,mid=5,数组范围[6,7,0,1,2],所以numbers[left]>numbers[mid],更新right=mid,更新二次后left=3,right=5,mid=4,数组范围[6,7,0],所以numbers[left]<numbers[mid],更新left=mid+1,更新三次时left=4,right=5,mid=4,数组范围[7,0],所以numbers[left]numbers[mid],所以left=mid+1,此时leftright=5,结束循环,返回numbers[left]。时间复杂度O(logN),空间复杂度O(1)。
时间复杂度:O(lgN)
如下:
思路:二分查找
时间复杂度 O(logN)
**空间复杂度 O(1) **
二分法:
时间 O(logn) 空间 O(1)
偷懒法
时间 空间 不清楚
mid > mid+1时,数组发生了旋转,且最小值一定在mid的右侧,将左指针移动到中间值的后一位,即left = mid+1;
mid < mid+1时,还不能判断数组是否发生了旋转,所以还需要使用 mid 和 right 进行比较
mid > righ时,mid前面的元素就不需要了,最小值在mid右侧,left = mid + 1;
mid <= right时,最小值在mid左侧,也可能是mid,需要保留,即 right = mid
看到旋转矩阵,我想到X战警-逆转未来,用反旋转的方法找到最小numbers[0],但写出来后发现不是log(n).速度太慢啦
//旋转数组& numbers) { nums=numbers;
class Solution {
public:
int minArray(vector
vector
int l=0,r=nums.size()-1;
while(l<=r){
int mid=l+(r-l)/2;
if(nums[mid]>nums[r]) l=mid+1;
else if(nums[mid]>nums[r]) r=mid-1;
else r–;
}
return nums[l];
}
};
二分
下面代码
注意重复数组的处理
二分法,时间复杂度为Olog(n),空间复杂度为O(1)
旋转点就是右侧有序数组的第一个数字
时间复杂度O(log2N)
时间:O(log(n)),空间:O(1)
算法流程**
性质:左排序数组的任一元素>=右派序数组任一元素
循环二分:
设mid = (i + j) / 2(恒有 i <= m < j)
当nums[mid] < nums[j] 时,mid一定在右派序数组中,
即旋转点x一定在[i,m]区间,因此执行j = m
当nums[mid] = nums[j] 时,无法判断mid到底在哪个排序数组中,即无法判断旋转点x 在[i,m]还是[m+1,j]区间中。解决方案:j = j -1 缩小判断范围
返回值:当i j跳出二分循环,并且返回旋转点的值 nums[i]即可
时间 O(log n)
看了下视频讲解,左边肯定比右边大(如果不是,直接返回第一个元素),然后二分,找到中间元素,左边元素小于中间元素,l = mid+1,大于的话,r=mid,相等就l++
时间O(logn)
空间O(1)
时间复杂度为O(lgn)空间复杂度为O(1)