[LeetCode] Find Minimum in Rotated Sorted Array

Suppose a sorted array is rotated at some pivot unknown to you beforehand.

(i.e., 0 1 2 4 5 6 7 might become 4 5 6 7 0 1 2).

Find the minimum element.

You may assume no duplicate exists in the array.

这题其实就是找翻转后右侧部分的最左端点,典型的二分搜索变体,大致思路分成两种情况讨论:

1)如果搜索范围在翻转部分,稍微复杂一点:

1.1)如果中间点在翻转后的左侧,则应该往右寻找,因为如果没有冗余元素,最小值不可能出现在左侧;

1.2)如果中间点在翻转后的右侧,则应该往左寻找。不过这时应该缓存下当前中间点对应的元素,因为再往左的话,可能就到了翻转后的左侧部分,就可能错过全局最小值了。

2)如果搜索范围在排序的部分,则当前的最小值肯定是在最左端。不过这个时候最左端的值不一定是全局最小,需要跟缓存的最小值在进行一次比较。

	public int findMin(int[] num) {
		int low = 0, high = num.length - 1;
		int ret = Integer.MAX_VALUE;

		while (low <= high) {
			int mid = low + (high - low) / 2;
			// On the sorted part.
			if (num[low] <= num[high]) {
				return Math.min(num[low], ret);
			} else { // On the rotated part.
				// num[mid] is on the left rotated part.
				if (num[mid] >= num[low]) {
					low = mid + 1;
				} else { // num[mid] is on the right rotated part.
					ret = num[mid];
					high = mid - 1;
				}
			}
		}
 	return ret;
	}

注意最后的return语句其实是不可能到达的,因为一旦low和high相等,那么num[low]和num[high]也必然相等了,直接就返回了。

Follow up for "Find Minimum in Rotated Sorted Array":
What if duplicates are allowed?

Would this affect the run-time complexity? How and why?

Suppose a sorted array is rotated at some pivot unknown to you beforehand.

(i.e., 0 1 2 4 5 6 7 might become 4 5 6 7 0 1 2).

Find the minimum element.

The array may contain duplicates.

如果存在冗余元素,那么则必须把num[low]和num[high]相等的情况单独讨论了。这种情况下,只能老老实实的线性搜索了。如果使用二分查找,这个时候可能会出问题:如果输入数组的最左和最右元素相等,而且都存在一片连续相等的区域,那么中间点可能也会在最左或者最右的连续相等区域中。这个时候应该是无法判断再往哪个方向搜索的。例如[3, 3, 3, 3, 3, 3, 4, 2, 3, 3]和[3, 3, 4, 2, 3, 3, 3, 3, 3, 3],取中间点后根本无法判断继续往哪个方向搜索。

	public int findMin(int[] num) {
		int low = 0, high = num.length - 1;
		int ret = Integer.MAX_VALUE;

		while (low <= high) {
			// Linear scan to find a non-flat part.
			if (num[low] == num[high]) {
				ret = Math.min(num[low], ret);
				low++;
				continue;
			}
			int mid = low + (high - low) / 2;
			// On the sorted part.
			if (num[low] < num[high]) {
				return Math.min(num[low], ret);
			} else { // On the rotated part.
				// num[mid] is on the left rotated part.
				if (num[mid] >= num[low]) {
					low = mid + 1;
				} else { // num[mid] is on the right rotated part.
					ret = num[mid];
					high = mid - 1;
				}
			}
		}
		return ret;
	}

相比于之前不考虑冗余元素的解法,就是多了一个if语句,单独处理num[low]和num[high]相等的情况。

你可能感兴趣的:(LeetCode,array,search,binary,rotate)