[数组]旋转数组

旋转数组起始就是数组元素的循环左移或者循环右移。例如:{3,4,5,1,2}为{1,2,3,4,5}的一个旋转数组。旋转数组是在非降序数组的基础上得到的,所以数组原本应该是有序的。

有序数组到旋转数组

如果真的利用循环左移或者循环右移来实现旋转数组,那么将有大量的元素要移动,所以一个好的方法要尽量的减少数组中元素的移动。

方法:

1.对数组的前部分元素做逆序操作
2.对数组的后部分元素做逆序操作
3.对数组的所有元素整体做逆序操作

逆序操作利用两个指针,一个头指针一个尾指针,都往中间移动,一次交换逆序。

旋转数组的最小值

查找最小值可以遍历一次,时间复杂度为O(n),但是还可以更快的算法,看一下旋转数组的特性:

1.旋转数组是部分有序的
2.前面的部分>后面的部分
3.最小元素出现在两部分的边界

  根据旋转数组的部分有序的特点,可以使用折半查找。

两个指针限定要查找的范围,分别是start和end
1.如果旋转数组等于原来的数组,也就是没有任何元素循环移动,也就是start对应的元素小于end对应的元素。
	那么第一个元素就是最小元素。
2.折半查找的终止条件:如果end-start=1,那么end对应的元素就是最小元素
3.取中间元素为mid=(start+end)/2
	如果mid对应的值等于start对应的值等于end对应的值,那么将是这种情况:{1,0,1,1,1,},这时
		不能确定下表2对应的1,属于前半部分升序还是后半部分升序。折半查找失效,利用顺序查找。
	如果mid对应的值大于或者等于start对应的值,说明mid对应的值仍然在第一个升序的部分,
		那么start=mid(不能等于mid+1,因为终止条件是两者相隔1)
	如果mid对应的值小于或者等于end对应的值,那说明mid对应的值在第二个升序的部分,
		那么end=mid(不能等于mid-1,因为mid可能是最小元素)

代码实现:

int minNumberInRotateArray(vector<int> rotateArray)
    {
        if(rotateArray.size() == 0)
            return 0;

        int index1 = 0;
        int index2 = rotateArray.size() - 1;
        int indexMid = index1;

        //数组元素循环移动量为0
        if(rotateArray[index1] < rotateArray[index2])
            return rotateArray[index1];

        while(index1 < index2)
        {
            if(index2 - index1 == 1)
            {
                indexMid = index2;
                break;
            }//if

            indexMid = (index1 + index2) / 2;
            //顺序查找的条件
            if(rotateArray[index1] == rotateArray[index2] && rotateArray[index1] == rotateArray[indexMid])
            {
                return MinInOrder(rotateArray, index1, index2);
            }

            if(rotateArray[indexMid] >= rotateArray[index1])
            {
                index1 = indexMid;
            }
            else if(rotateArray[indexMid] <= rotateArray[index2])
            {
                index2 =  indexMid;
            }
        }//while

        return rotateArray[indexMid];

    }

    //顺序查找
    int MinInOrder(vector<int>& nums, int index1, int index2)
    {
        int result = nums[index1];
        for(int i = index1 + 1; i <= index2; i++)
        {
            if(result > nums[i])
            {
                result = nums[i];
            }
        }

        return result;
    }

十分注意这道题目的Test Case:

1.输入的数组的元素个数为0
2.数组只有一个元素
3.升序的数组(循环移动量为0)
4.有重复元素的循环数组(顺序查找)

  

  

 

时间: 2024-11-05 18:53:39

[数组]旋转数组的相关文章

leecode刷题(3)-- 旋转数组

leecode刷题(3)-- 旋转数组 旋转数组 给定一个数组,将数组中的元素向右移动 K 个位置,其中 K 是非负数. 示例: 输入: [1,2,3,4,5,6,7] 和 k = 3 输出: [5,6,7,1,2,3,4] 解释: 向右旋转 1 步: [7,1,2,3,4,5,6] 向右旋转 2 步: [6,7,1,2,3,4,5] 向右旋转 3 步: [5,6,7,1,2,3,4] 说明: 尽可能想出更多的解决方案,至少有三种不同的方法可以解决这个问题. 要求使用空间复杂度为 O(1) 的原

旋转数组的最小数字

题目描述 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转.输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素.例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1.NOTE:给出的所有元素都大于0,若数组大小为0,请返回0. class Solution { public: int minNumberInRotateArray(vector<int> rotateArray) { if(rotateArray.size()==0) re

算法练习:一维数组旋转

题目描述:求一个一维数组向右旋转K个位置后的结果.比如,一维数组{1, 2, 3, 4, 5},当k = 2时,求得的结果为{4, 5, 1, 2, 3}.要求常数级空间复杂度,允许修改原有数组. 一.使用额外的空间(在不要求常数级空间复杂度的情况下) 这样很简单,使用一个额外的空间,保存原有数组的元素,然后可以错位复制原有数组 元素,即可达到题目的要求.比如数组{1, 2, 3, 4, 5},当k = 2时,先将4,5复制到结果数组,然后将1,2,3复制到结果数组的后面部分. //使用额外空间

(每日算法)LeetCode --- Search in Rotated Sorted Array(旋转数组的二分检索)

Search in Rotated Sorted Array I && II Leetcode 对有序数组进行二分查找(下面仅以非递减数组为例): int binarySort(int A[], int lo, int hi, int target) { while(lo <= hi) { int mid = lo + (hi - lo)/2; if(A[mid] == target) return mid; if(A[mid] < target) lo = mid + 1;

【剑指offer】旋转数组的最小数字

题目描述: 把一个数组最开始的若干个元素搬到数组的末尾,称之为数组的旋转.输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素.例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1. 分析描述: 求一个数组中的最小值,最简单的办法就是逐个比较数组中各个元素的值,遍历完整个数组,即可得数组中最小元素.但这种方法存在的问题是时间复杂度为O(n). 利用题目中给出的条件:递增排序数组的旋转.利用递增排序的特点,可以用二分查找方法实现时间复杂度为O(logn)的查找.

剑指offer java -查找旋转数组的最小数字

/** * Created by wqc on 2017/7/18. * 查找旋转数组的最小数字 * 把一个数组最开始的若干个元素搬到数组的末尾,称为数组的旋转 * 输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素 * 如:3,4,5,1,2 为1,2,3,4,5的一个旋转,最小值为1 */public class Problem8_findMinNumber { public Integer findMinNum(int[] array) { if(array == null) { r

《剑指offer》— JavaScript(6)旋转数组的最小数字

旋转数组的最小数字 题目描述 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转. 输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素.例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1. NOTE:给出的所有元素都大于0,若数组大小为0,请返回0. 实现代码 function minNumberInRotateArray(rotateArray) { var len=rotateArray.length; if(len== 0 || !r

旋转数组的最小数字 - 剑指offer 面试题8

题目描述: 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转.输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素.例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1.NOTE:给出的所有元素都大于0,若数组大小为0,请返回0. class Solution { public: int minNumberInRotateArray(vector<int> rotateArray) { if (rotateArray.size() == 0

旋转数组,求最小元素

题目描述 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转.输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素.例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1.NOTE:给出的所有元素都大于0,若数组大小为0,请返回0. 如果,要求在排序的数组中查找一个数字或者统计某个数字出现的次数,都可以尝试二分查找算法 分析: 旋转之后的数组实际上可以划分成两个有序的子数组:前面子数组的大小都大于后面子数组中的元素 注意到实际上最小的元素就是两个