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

100 阅读2分钟

旋转数组的最小数字__牛客网 (nowcoder.com)

image.png

找规律: [1,2,3,4,5]->a翻转:[3,4,5,1,2]->b [1,2,3,4,5]->a翻转:[4,5,1,2,3]->c 观察a翻转为b或者c, b可以看为两段: 第一段:3,4 ,5(递增) 第二段:1,2(递增) 1是第一段递增的结尾,第二段递增的开头,即1是最小值

c可以看为两段: 第一段:4,5(递增) 第二段:1,2,3(递增) 1是第一段递增的结尾,第二段递增的开头,即1是最小值

image.png

 private:


 public:
  /**
   * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
   *
   *
   * @param nums int整型vector
   * @return int整型
   */
  int minNumberInRotateArray(vector<int>& nums) {
    // write code here

    //左指针指向左边第一个数,有指针指向右边最后一个;
    int right = nums.size() - 1;
    int left = 0;

    int mid = (right+left)/2;
    //判空
    if (nums.size()==0)return 0;
    
    
    while (nums[left] >= nums[right]) {
    
  //当左右指针相邻时,那么最小值就是右指针的位置
 if (right - left == 1) { mid = right; break; }

      //如果mid>left,那么left就到mid的位置
      if (nums[mid] >= nums[right]) {
       left = mid;此时最小值就是left
      }

      //如果右尾指针大于mid,那么就挪到Mid
      if (nums[right] >= nums[mid]) {
          right = mid;此时最小值就是right
      }

    }
    //所以最小值也是mid
    return nums[mid];
  }


};js

但是代码到目前为止还是不完善:

我们看一组例子:{1,0,1,1,1} 和 {1,1, 1,0,1} 都可以看成是递增排序数组{0,1,1,1,1}的旋转。

但是最小值有好多个,我们还需要写一段代码返回这里面最小值的第一个:

image.png

      ``if (nums[left] == nums[right] &&

          ``nums[left] == nums[mid]) {

        ``return MinOrder(nums, left, right);

      ``}

image.png

 ``int MinOrder(vector<int >& num, int left, int right) {

    int result = num[left];

    for(int i = left + 1; i < right; ++i) {

      if (num[i] < result) {

        result = num[i];

`      }

    }

全部代码:

 private:


 public:
  /**
   * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
   *
   *
   * @param nums int整型vector
   * @return int整型
   */
  int minNumberInRotateArray(vector<int>& nums) {
    // write code here

    //左指针指向左边第一个数,有指针指向右边最后一个;
    int right = nums.size() - 1;
    int left = 0;

    int mid = 0;
    //判空
    if (nums.size()==0)return 0;

    while (nums[left] >= nums[right]) {

      if (right - left == 1) {
        mid = right;
        break;
      }

      mid = (left + right) / 2;



      if (nums[left] == nums[right] &&
          nums[left] == nums[mid]) {
        return MinOrder(nums, left, right);
      }

      //如果mid>left,那么left就到mid的位置
      if (nums[mid] >= nums[right]) {
       left = mid;
      }

      //如果右尾指针大于mid,那么就挪到Mid
      if (nums[right] >= nums[mid]) {
          right = mid;
      }

    }
    //此时最小值就是right
    return nums[mid];
  }
  int MinOrder(vector<int>& num, int left, int right) {
    int result = num[left];
    for (int i = left + 1; i < right; ++i) {
      if (num[i] < result) {
        result = num[i];
      }//if
    }//for
    return result;
  }

};js