今天面试遇到一个有意思的题,记录一下如下。
题目一:
一个循环数组,数组中原始值按升序排列(假设所有值不相等),但是现在从某个位置截断,该位置后面的元素移动到数组的最前面,找出这样的数组的最小值。如 arr = { 1,2,3,4,5,6},移动后arr = {4,5,6,1,2,3},其中最小值为1.
思路比较简单:基于二分查找
要注意的是数组为升序和降序的特殊情形。
代码如下:
public class Main {
public static void main(String args[]) {
int[] arr = new int[]{4, 5, 6, 1, 2, 3};
int[] arr1 = new int[]{1, 2, 3, 4, 5, 6};
int[] arr2 = new int[]{6, 5, 4, 3, 2, 1};
System.out.println(findMin(arr));
System.out.println(findMin(arr1));
System.out.println(findMin(arr2));
}
public static int findMin(int[] arr) {
int mid = 0, start = 0, end = arr.length - 1;
while (start < end) {
mid = (start + end) >> 1;
if (arr[mid] > arr[end])//arr[mid]在在arr的前半部
//这里不能使用if(arr[mid] > arr[start]),因为可能存在1,2,3,4,5,6这种情况
start = mid + 1;
else {//arr[mid]在在arr的后半部
end = mid;
}
}
return arr[end];
}
}
输出如下:
1
1
1
题目二:
如果题一中数组arr中可能存在相等的元素,同样求数组中的最小值。比如 int[] arr = new int[]{5, 3, 5, 7, 5, 5},其中最小值为3.
思路:显示题目一的做法在这里不适用,因为没有考虑元素相等的情况。那么在题一思路上进行改进:
首先,也是基于二分查找;
if arr[mid] > arr[end],arr[mid]位于arr的前半部分,
else if arr[mid] < arr[end],arr[mid]位于arr的后半部分,
else if arr[mid] == arr[end],情况稍微复杂一些。
在arr[mid] == arr[end]的基础上,
if arr[mid] > arr[start], 那么arr[mid]一定位于前半部分,
else if arr[mid] < arr[start], 那么arr[mid]一定位于后半部分,
else if arr[mid] == arr[start], 那么最小值有可能在start~mid之间,也可能在mid~end之间,此时 start++, end–
代码如下:
public class Main {
public static void main(String args[]) {
int[] arr = new int[]{4, 5, 6, 1, 2, 3};//1
int[] arr1 = new int[]{1, 2, 3, 4, 5, 6};//1
int[] arr2 = new int[]{6, 5, 4, 3, 2, 1};//1
int[] arr3 = new int[]{5, 5, 5, 6, 7, 5};//5
int[] arr4 = new int[]{5, 3, 5, 7, 5, 5};//3
int[] arr5 = new int[]{5, 6, 7, 5, 3, 5};//3
System.out.println(findMinBest(arr));
System.out.println(findMinBest(arr1));
System.out.println(findMinBest(arr2));
System.out.println(findMinBest(arr3));
System.out.println(findMinBest(arr4));
System.out.println(findMinBest(arr5));
}
public static int findMinBest(int[] arr) {
int mid = 0, start = 0, end = arr.length - 1;
while (start < end) {
mid = (start + end) >> 1;
if (arr[mid] > arr[end])//arr[mid]一定位于前半部
start = mid + 1;
else if (arr[mid] == arr[end]) {
if (arr[mid] == arr[start]) {
start++;
end--;
} else if (arr[mid] > arr[start])
end = mid - 1;
else {//arr[mid] < arr[start]
end = mid;
start++;
}
} else {//arr[mid] < arr[end]
end = mid;
}
}
return arr[end];
}
}
输出如下:
1
1
1
5
3
3
本文记录了一道面试题,涉及一个循环数组,数组中的元素按升序排列,但经过某种操作后,需要找出最小值。通过二分查找的方法,分别解决了不考虑相等元素和考虑相等元素两种情况,给出了相应的代码实现。
1449

被折叠的 条评论
为什么被折叠?



