【LeetCode】面试题11. 旋转数组的最小数字(二分法)

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/xuan-zhuan-shu-zu-de-zui-xiao-shu-zi-lcof

题目描述:

把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如,数组 [3,4,5,1,2] 为 [1,2,3,4,5] 的一个旋转,该数组的最小值为1。

示例 1:
输入:[3,4,5,1,2]
输出:1

我的代码:(1 ms)(38.8 MB)

时间复杂度为O(n)
思路:找到变小的阶梯,变小了说明变小的那个是第一个元素。
如果遍历完全后,仍未找到变小的那个阶梯,说明此数组是常数组,或者第一个元素就是打头元素。
返回arr[0]就行了。

class Solution {
    public int minArray(int[] numbers) {
        for(int i = 0; i<numbers.length-1; i++){
            if(numbers[i+1]<numbers[i]){
                return numbers[i+1];
            }
        }
        return numbers[0];
    }
}

**

推荐的算法:二分法

时间复杂度:O(log n)
思想,将两个指针分别指向数组的开头和结尾
如果中间的数大于开头的数,说明中间的位置和开头同属于一个子序列,将start移到middle的位置;
如果中间的数小于等于结尾的数,说明中间的位置和结尾同属于一个子序列,将end移动到middle的位置。
直到start = end - 1,那么结尾的位置指的就是最终要求的结果。
有两个特例:
特例1:
1、2、3、4、5、6、7、8、9 直接返回1
特例2:
3、0、3、3、3 或者 3、3、3、0、3
不能判断,只能顺序遍历

class Solution {
    public int minArray(int[] numbers) {
		if (numbers[0] < numbers[numbers.length - 1]) {
			return numbers[0];
		}
		int start = 0;
		int end = numbers.length-1;
		int middle = 0;
		while (start < end - 1) {
			middle = (start + end) / 2;
			if (numbers[start] == numbers[end] && numbers[start] == numbers[middle]) {
				return method(numbers, start, end);
			} else if (numbers[middle] >= numbers[start]) {
				start = middle;
			} else if (numbers[middle] <= numbers[end]) {
				end = middle;
			}
		}
		return numbers[end];
	}

	public int method(int[] numbers, int start, int end) {
		int i = start;
		while (i < end - 1) {
			if (numbers[i] > numbers[i + 1]) {
				return numbers[i + 1];
			}
            i ++;
		}
		return numbers[start];
	}

}

你可能感兴趣的:(算法,二分法,算法,leetcode,java)