zoukankan      html  css  js  c++  java
  • LeetCode--搜索旋转排序数组

    LeetCode链接:https://leetcode-cn.com/problems/search-in-rotated-sorted-array/

    题目:

      假设按照升序排序的数组在某个未知的点上进行了旋转,例如,数组[0, 1, 2, 4, 5, 6, 7]可能变为[4, 5, 6, 7, 0, 1, 2]

      搜索一个给定的目标值,如果数组中存在这个目标值,则返回它的索引,否则返回-1;

      可以假设数组中不存在重复元素,要求算法的时间复杂度必须是O(log n)级别;

      我的想法是:先找到旋转点,再找目标值target在数组中的索引。这两个查找过程均使用二分查找,时间复杂度为O(log n);

        如果一个有序数组发生了旋转,整体上将不再有序,但是会得到两个部分有序的子数组,如上例中的[4, 5, 6, 7]和[0, 1, 2]这两个部分仍是有序的,所以可以使用二分查找,找到旋转点,旋转点也就是两个有序子数组的分界点;

        找到旋转点后再将target的值与nums[旋转点]的值进行比较,选择在哪个有序子数组里使用二分查找寻找target所对应的索引值

     1 public class Solution {
     2     public int search(int[] nums, int target) {
     3         if(nums == null || nums.length == 0) return -1;
     4         if(nums.length == 1) return nums[0] == target ? 0 : -1;
     5         int left = 0, right = nums.length - 1, mid = 0;
     6         // 先找到旋转点,旋转点也就是两个有序子数组的分界点
     7         int rotateIndex = findRotateIndex(nums);
     8         if(nums[left] > nums[right]) {  // 判断nums是否发生了旋转,如果发生了,那么判断应该在哪个有序子数组里查找
     9             if(target >= nums[left]) {
    10                 right = rotateIndex;
    11             }else {
    12                 left = rotateIndex + 1;
    13             }
    14         }
    15         while(left <= right) {       // 在有序子数组中查找目标值的索引
    16             mid = (left + right) / 2;
    17             if (target > nums[mid]) {
    18                 left = mid + 1;
    19             }
    20             else if(target < nums[mid]){
    21                 right = mid - 1;
    22             }
    23             else {
    24                 return mid;
    25             }
    26         }
    27         return -1;
    28     }
    29     
    30     public int findRotateIndex(int[] nums) {       // 查找旋转点的下标
    31         int left = 0, right = nums.length - 1, mid = 0;
    32         if(nums[left] <= nums[right]) return right;
    33         int rotateIndex = right;   // 记录旋转点,它始终指向的是数组元素的最大值
    34         while(left <= right) {
    35             if(nums[left] <= nums[right]) {          // 当条件成立时,说明该子数组是有序子数组,即找到了两个有序子数组的分界点
    36                 rotateIndex = right < mid ? right : left - 1;
    37                 return rotateIndex;
    38             }
    39             else {
    40                 mid = (left + right) / 2;
    41                 if(nums[left] <= nums[mid]) {
    42                     left = mid + 1;        // 说明旋转点在mid的右边
    43                 }
    44                 else {
    45                     right = mid - 1;       // 说明旋转点在mid的左边
    46                 }
    47             }
    48         }
    49         return rotateIndex;
    50     }
    51 }
  • 相关阅读:
    PAT (Advanced Level) Practice 1054 The Dominant Color (20 分)
    PAT (Advanced Level) Practice 1005 Spell It Right (20 分) (switch)
    PAT (Advanced Level) Practice 1006 Sign In and Sign Out (25 分) (排序)
    hdu 5114 Collision
    hdu4365 Palindrome graph
    单链表查找最大值、两个递增的链表合并并且去重
    蓝桥杯-最短路 (SPFA算法学习)
    蓝桥杯-最大最小公倍数
    Codeforces-470 div2 C题
    蓝桥杯-地宫取宝
  • 原文地址:https://www.cnblogs.com/OoycyoO/p/11756926.html
Copyright © 2011-2022 走看看