我在一次采访中遇到了这个问题。请帮我解决问题。
问题是:
你已经对可旋转阵列进行了分类,i。即数组包含已排序的元素,它可以循环旋转,就像数组中的元素是[5,6,10,19,20,29]然后旋转第一次数组成为[29,5,6,10,19] ,20],第二次变为[20,29,5,6,10,19]等等。
所以你需要在任何一点找到数组中最小的元素。您将不会被提供数字时间数组旋转。只是给出旋转的数组元素并找出其中最小的元素。在这种情况下,输出应为5。
答案 0 :(得分:35)
方法1:
您可以在O(logN)
时间内完成此操作。
使用修改后的二进制搜索来查找作为索引i
的旋转点,使其成为arr[i] > arr[i+1]
。
示例:
[6,7,8,9,1,2,3,4,5]
^
i
对两个子阵列(arr[1], arr[2], .., arr[i])
和
(arr[i+1], arr[i+2], ..., arr[n])
进行了排序。
答案是min(arr[1], arr[i+1])
方法2:
当您将已排序的旋转数组拆分为两半(arr[1],..,arr[mid])
和(arr[mid+1],..,arr[n])
时,其中一个始终排序,另一个始终具有最小值。我们可以直接使用修改后的二进制搜索来继续搜索未分类的一半
// index of first element
l = 0
// index of last element.
h = arr.length - 1
// always restrict the search to the unsorted
// sub-array. The min is always there.
while (arr[l] > arr[h]) {
// find mid.
mid = (l + h)/2
// decide which sub-array to continue with.
if (arr[mid] > arr[h]) {
l = mid + 1
} else {
h = mid
}
}
// answer
return arr[l]
答案 1 :(得分:2)
如果重复数据元素,如{8,8,8,8,8}或{1,8,8,8,8}或{8,1,8,8,8}或{,则上述算法失败8,8,1,8,8}或{8,8,8,8,1}
// solution pasted below will work all test cases :)
//break the array in two subarray and search for pattern like a[mid]>a[mid+1]
// and return the min position
public static int smallestSearch(int[] array,int start,int end)
{
if(start==end)
return array.length;
int mid=(start+end)/2;
if(array[mid]>array[mid+1])
return min(mid+1,smallestSearch(array,start,mid),smallestSearch(array,mid+1,end));
else
return min(smallestSearch(array,start,mid),smallestSearch(array,mid+1,end));
}
public static int min(int a,int b)
{
if(a==b)
return a;
else if(a<b)
return a;
else
return b;
}
public static int min(int a,int b,int c)
{
if(a<c)
{
if(a<b)
{
return a;
}
else
{
return b;
}
}
else
{
if(b<c)
return b;
else
return c;
}
}
答案 2 :(得分:1)
要查找已排序的旋转数组中的最小数字: 使用二进制搜索概念
public class RotatedSortedArrayWithoutDuplicates1 {
public static void main(String[] args) {
int[] a = { 4, 6, 8, 10, 34, 56, 78, 1, 3 };
System.out.println(findMin(a));
}
private static int findMin(int[] a) {
if (a.length == 0 || a == null) {
return -1;
}
int start = 0;
int last = a.length - 1;
while (start + 1 < last) {
int mid = start + (last - start) / 2;
int m = a[mid];
int s = a[start];
int l = a[last];
if (m > l) {
start = mid + 1;
}
if (m < l) {
last = mid;
} else {
last--;
}
} // while
if (a[start] > a[last]) {
return a[last];
} else {
return a[start];
}
}
}
但如果你不想使用二进制搜索,那么:
public class Abc {
public static void main(String[] args) {
int[] a = { 4, 5, 6, 7, 7, 8, 9, 1, 1, 2, 3, 3 };
System.out.println(findMin(a));
}
public static int findMin(int[] a) {
int min = a[a.length - 1];
for (int i = 0; i < a.length; i++) {
if (min > a[i]) {
min = a[i];
break;
}
}
return min;
}// findmin
}// end
以下是Python中的代码:
def fix(a):
min = a[0]
for i in range(len(a)):
if(min > a[i]):
min = a[i]
break
return min
a = [2, 2,3,4,1,2]
print(fix(a))
答案 3 :(得分:0)
我的代码在下面,算法作为注释。甚至可以用于重复的元素。
//Find Min in Rotated Sorted Array
//Example: int array[10] = {7, 8, 9, 10, 11, 12, 3, 4, 5, 6};
// Min in the above array is 3
// Solution: Recursively search (Modified binary search) for the Pivot where is the smallest Element is present
// Algorithm:
// 1) Find the Mid of the Array
// 2) call the recursive function on segment of array in which there is a deviation in the order
// If (A[low] > A[mid]) array segment in which deviation in the order present is (low, mid)
// If (A[low] < A[mid]) array segment in which deviation in the order present is (mid + 1, high)
// Time Complexity: O(logn)
// Space Complexity: is of the recursive function stack that is being used
#define MIN(x,y) (x) <= (y) ? (x): (y)
int MininRotatedSortedArray(int A[], int low, int high)
{
if(low > high)
return -1;
if(low == high - 1)
return MIN(A[low], A[high]);
int mid = low + (high - low)/2;
if(A[low] > A[mid])
return MininRotatedSortedArray(A, low, mid);
else if(A[low] < A[mid])
return MininRotatedSortedArray(A, mid + 1, high);
else
return A[mid];
}
答案 4 :(得分:0)
这可以在O(1)时间最佳情况,O(n)时间最差情况和平均O(lg n)时间内完成。
对于旋转的排序数组,如果数组中的第一个元素小于数组中的最后一个元素,则排序的数组不会旋转(或旋转0位置)。最小元素只是第一个元素。
如果中间元素小于最后一个元素,则最小元素位于[first,middle]。
如果中间元素大于最后一个元素,那么最小元素在[middle + 1,last]中。
如果中间元素等于最后一个元素,则有两个子案例:
我用C ++编写了以下代码来解决这个问题,它应该处理所有情况(空数组,重复元素)。
template <typename Iterator>
Iterator rotated_min(Iterator begin, Iterator end)
{
while (begin != end)
{
if (*begin < *(end - 1))
{
return begin;
}
Iterator mid = begin + (end - 1 - begin) / 2;
if (*mid < *(end - 1))
{
end = mid + 1;
}
else if (*mid > *(end - 1))
{
begin = mid + 1;
}
else
{
if (*begin > *(end - 1))
{
end = mid + 1;
++begin;
}
else
{
//reduce to linear search
typename ::std::iterator_traits<Iterator>::value_type min_value = *begin;
Iterator min_element = begin;
for (Iterator i = begin + 1; i != end; ++i)
{
if (*i < min_value)
{
min_value = *i;
min_element = i;
}
}
return min_element;
}
}
}
return begin;
}
答案 5 :(得分:0)
在循环排序数组中查找最小索引
Example : [7,8,9,1,2,3,4,5,6]
int findMinIndex(int []a, int start, int end)
{
int mid = (start + end)/2;
if (start - end == 1)
if(a[start] < a[end])
return start;
else
return end;
if (a[mid] > a[end]){
return findMinIndex(a,mid,end);
}
else{
return findMinIndex(a,start,mid);
}
return -1; //Not found
}
答案 6 :(得分:0)
如果有人需要它..我在java中的实现..
负责排序/未排序的升序//降序用例..
缺点是它仍然会执行log n步骤来在没有旋转的完美排序集中查找min值。
/* package whatever; // don't place package name! */
import java.util.*;
import java.lang.*;
import java.io.*;
/* Name of the class has to be "Main" only if the class is public. */
class Ideone
{
public static void main (String[] args) throws java.lang.Exception
{
int [] a = {3,3,0,2,2,2,2,1,2,2,2,2,2,2,2,2,2};
System.out.println(recursiveSplit(a,0,a.length-1));
}
public static int findMin(int x, int y){
if(x<=y){
return x;
}else{
return y;
}
}
public static int recursiveSplit(int[] arr , int a , int b){
int mid = (int) Math.floor(a + (b-a)/2);
int h1_l = a;
int h1_u = mid;
int h2_l = mid+1;
int h2_u = b;
int x=0;
int y=0;
//single element
if(a==b){
return arr[a];
}
//adjacent positions
if(h1_u-h1_l==1){
x=findMin(arr[h1_u],arr[h1_l]);
}else{
//else split
x=recursiveSplit(arr,h1_l,h1_u);
}
if(h2_u-h2_l==1){
y=findMin(arr[h2_u],arr[h2_l]);
}else{
y=recursiveSplit(arr, h2_l,h2_u);
}
return findMin(x, y);
}
}
欢迎使用错误/建议/失败的用例
答案 7 :(得分:0)
public int findMin(int[] num) {
return findMin(num, 0, num.length-1);
}
public int findMin(int[] num, int left, int right){
if(left==right) return num[left];
if(left+1==right) return Math.min(num[left], num[right]);
int mid = (left+right)/2;
if(num[mid]>num[right]){
return findMin(num,mid+1,right);
}else if(num[mid]<num[right]){
return findMin(num,left,mid);
}else{
if(num[mid]==num[left]){
return Math.min(findMin(num,left,mid), findMin(num,mid,right));
}else{
return findMin(num,left,mid);
}
}
}
答案 8 :(得分:0)
以下算法需要log(n)时间。假设数组没有重复。
public int findMin(int[] num) {
if(num.length == 0) return -1
int r = num.length-1, l = 0;
while(l<r){
if(num[l]<=num[r]) return num[l]; //when not rotated, return the left most value
int mid = (r+l)/2;
if(num[mid]<num[r]){
r = mid;
}else{
l = mid+1;
}
}
return num[l];
}
答案 9 :(得分:0)
我是使用略微修改的二进制搜索版本完成的。我在这里做的是根据最小值的不同向左或向右移动。例如,如果中间元素小于最左边的元素,则在升序数组中,最小值可能在左侧。在通过数组递归时,我也会跟踪最小值。递归一直持续到结束,然后返回最新的min。这也适用于重复的元素。
public static void main(String[] args) throws IOException {
int[] rotated = {6, 7, 8, 1, 2, 3, 4, 5};
int min = findMin(rotated);
System.out.println(min);//1
}
public static int findMin(int[] sorted) {
return findMinRecursively(sorted, sorted[0], 0, (sorted.length - 1));
}
private static int findMinRecursively(int[] sorted, int min, int leftIndex, int rightIndex) {
if (leftIndex > rightIndex) {
return min;
}
int midIndex = (leftIndex + rightIndex) / 2;
if (sorted[midIndex] < min) {
min = sorted[midIndex];
}
if (sorted[midIndex] < sorted[leftIndex]) {
return findMinRecursively(sorted, min, leftIndex, (midIndex - 1));
} else {
return findMinRecursively(sorted, min, (midIndex + 1), rightIndex);
}
}
答案 10 :(得分:0)
问题:在已排序的旋转数组中找到最小值。 解决方案1:使用二进制搜索
class Test18 {
public static void main(String[] args) {
int[] a = { 5, 6, 7, 8, 9, 10, 1, 2, 3 };
System.out.println(findmin(a));
}
// find min in a sorted rotated array
private static int findmin(int[] a) {
int start = 0;
int last = a.length - 1;
while (start + 1 < last) {
int mid = start + (last - start) / 2;
if (a[mid] > a[last]) {
start = mid + 1;
}
if (a[mid] < a[last]) {
last = mid;
} else {
mid--;
}
} // while
if (a[start] > a[last]) {
return a[last];
} else {
return a[start];
}
}
}
答案 11 :(得分:0)
def searchinrotatedarray(arr1,l,h):
if l>h:
return arr1[0]
if h==l:
return arr1[l]
mid=(l+h)//2
if mid<h and arr1[mid+1]<arr1[mid]:
return arr1[mid+1]
elif mid>l and arr1[mid-1]<arr1[mid]:
return arr1[mid]
elif arr1[mid]<arr1[h]:
return searchinrotatedarray(arr1,l,mid-1)
else:
return searchinrotatedarray(arr1,mid+1,h)
首先,if语句检查偶数数组是否完全旋转。在这种情况下,第一个元素是min。如果list的长度为1,则该元素为min。 否则,如果中元素小于最后一个元素,则继续在下半部分查找,否则在上半部分查找
答案 12 :(得分:0)
df<-read.table(header=TRUE, text="uniqueID favFruits favVeggie State favColor
john@mail.com NA carrots CA Green
jill@mail.com apples NA FL NA
john@mail.com grapes beets CA Red
jill@mail.com cherries beans FL Blue
jill@mail.com pineapple beans FL Blue
john@mail.com grapes beets CA Yellow")
library(dplyr)
answer<- df %>% group_by(uniqueID) %>% summarize_all(list(~toString(unique(.))) )
print(answer)
# A tibble: 2 x 5
uniqueID favFruits favVeggie State favColor
<fct> <chr> <chr> <chr> <chr>
1 jill@mail.com apples, cherries, pineapple NA, beans FL NA, Blue
2 john@mail.com NA, grapes carrots, beets CA Green, Red, Yellow
答案 13 :(得分:0)
这是我使用递归的pythonic解决方案:
时间复杂度为O(log(n))&空间复杂度为O(1)
class Solution(object):
def findMin(self, nums):
left = 0
right = len(nums) -1
mid = len(nums) // 2
if len(nums) == 0:
return -1
if len(nums) == 1:
return nums[left]
if len(nums) == 2:
return min(nums[left], nums[right])
if nums[left] < nums[right]:
return nums[left]
elif nums[mid] > nums[left]:
return self.findMin(nums[mid + 1: ])
elif nums[mid] < nums[left]:
return self.findMin(nums[: mid + 1])
答案 14 :(得分:0)
这是一个非常简单的答案,它将适用于所有测试用例:
int a[] = {5,6,7,1,2,3,4};
int a[] = {1,2,3};
int a[] = {3,2,1};
int a[] = {3,1,2};
int a[] = {2,2,2,2};
public class FindSmallestNumberInSortedRotatedArray {
public static void main(String[] args) {
int a[] = { 4, 5, 6, 7, 1, 2, 3 };
int j = a.length - 1;
int i = 0;
while (i < j) {
int m = (i + j) / 2;
if (a[m] < a[m + 1] && a[m] < a[m - 1]) {
System.out.println(a[m] + "is smallest element ");
break;
} else if (a[m] > a[m + 1] && a[m - 1] > a[m + 1]) {
i = m + 1;
} else {
j = m - 1;
}
}
if (i == j)
System.out.println(a[i] + " is smallest element");
}
答案 15 :(得分:0)
使用递归二进制搜索方法,对具有重复项和不具有重复项的两个数组进行求解。
var min = (A, l, h) => {
if(l >= h) return A[l];
let m = Math.floor((l + h) / 2);
// as its unique
if(A[m] > A[h]) {
// go towards right as last item is small than mid
return min(A, m + 1, h);
} else if(A[m] > A[m - 1]) {
// go towards left as prev item is smaller than current
return min(A, l, m - 1);
} else {
// right and left is greater than current
return A[m];
}
}
/**
* @param {number[]} nums
* @return {number}
*/
var findMin = function(nums) {
// If array is rotated nums.length time or same as it is
if(nums[0] < nums[nums.length - 1]) return nums[0];
return min(nums, 0, nums.length - 1);
};
var min = (A, l, h) => {
if(l >= h) return A[l];
// traverse from left "and right" to avoid duplicates in the end
while(A[l] == A[l+1]) {
l++;
}
let m = Math.floor((l + h) / 2);
// as its unique
if(A[m] > A[h]) {
// go towards right as last item is small than mid
return min(A, m + 1, h);
} else if(A[m] >= A[m - 1]) {
// go towards left as prev item is smaller than current
return min(A, l, m - 1);
} else {
// right and left is greater than current
return A[m];
}
}
/**
* @param {number[]} nums
* @return {number}
*/
var findMin = function(nums) {
// If array is rotated nums.length time or same as it is
if(nums[0] < nums[nums.length - 1]) return nums[0];
return min(nums, 0, nums.length - 1);
};