旋转数组的最小数字(剑指offer第六题)

旋转数组最小值算法

一、题目描述:

         把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。
        例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。 NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。

 二、思路分析:

    我自己的思路是这样的,先把这个旋转数组的各种情况都考虑全面,if-else 分开,然后再对每种情况展开讨论,得出除了特殊情况外可以用算法复杂度较低的二分法来求。但是某有两个特殊情况必须用暴力顺序查找了。

   情况分类:

      (1):输入的旋转数组的大小为0时

      (2): 该旋转数组是前0个元素放到了末尾的情况

      (3):容易忽略的条件
非递减数组的旋转的意识是 可以是数字连续的比如:12222 旋转为:22212 或者旋转为:212222

        这种情况就是容易忽略的情况,这种情况无法用二分法来计算,因为不知道mid值是左边半个数组还是右边半个数组的,只能用暴力法求解。

     (4):正常情况,用二分法

三、可运行java代码

public class Solution_6 {
	public int minNumberInRotateArray(int[] array) {
		if (array.length == 0) { // 输入的旋转数组的大小为0时
			return 0;
		}
		int i = 0, j = array.length - 1, mid = (i + j) / 2;
		if (array[1] < array[array.length - 1]) { // 该旋转数组是前0个元素放到了末尾的情况
			return array[1];
		}

		// 容易忽略的条件
		// 非递减数组的旋转的意识是 可以是数字连续的比如:12222 旋转为:22212 或者旋转为:212222
		// 这种情况就是容易忽略的情况,这种情况无法用二分法来计算,因为不知道mid值是左边半个数组还是右边半个数组的,只能用暴力法求解
		if (array[mid] == array[i] && array[mid] == array[j]) {
			return findMin(array); // 调用暴力求解发,求出最小值
		}

		// 剩下的情况都可以用二分法来求解
		while (i < j - 1) { // 由于下面mid采用的是向下取整,所以这里是i<j-1即可,否则i<j会先入死循环
			if (array[i] <= array[mid]) {
				System.out.println("i=" + i + ";j=" + j);
				i = mid;
				mid = (i + j) / 2;
			} else {
				j = mid;
				mid = (i + j) / 2;
			}
		}
		System.out.println("mid=" + mid);
		return array[mid + 1];
	}

	// 暴力法:顺序查找
	public int findMin(int[] array) {
		int min = array[1]; // 假设数组第一个值为最小值
		for (int i = 0; i < array.length; i++) {
			if (array[i] < min) {
				min = array[i];
			}
		}
		return min;
	}
    
	
	//测试例子
	public static void main(String[] args) {
		int[] a = { 6501, 6828, 6963, 7036, 7422, 7674, 8146, 8468, 8704, 8717,
				9170, 9359, 9719, 9895, 9896, 9913, 9962, 154, 293, 334, 492,
				1323, 1479, 1539, 1727, 1870, 1943, 2383, 2392, 2996, 3282,
				3812, 3903, 4465, 4605, 4665, 4772, 4828, 5142, 5437, 5448,
				5668, 5706, 5725, 6300, 6335 };
		Solution_6 s = new Solution_6();
		System.out.println(s.minNumberInRotateArray(a));
	}
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值