数组follow-up

1.Sort Colors
[Sort Colors]https://leetcode.com/problems/sort-colors/description/
Solution:因为题目中已经限定了红白蓝,也就是说整个数组就是0,1,2组成了,因此直接的想法就是交换。还有hashmap的做法,这里不做赘述

class Solution {
    public void sortColors(int[] nums) {
        if (nums == null && nums.length <= 1) {
            return;
        }
        int left = 0, right = nums.length - 1;
        int i = 0;
        while (i <= right) {
            if (nums[i] == 0) {
                swap(nums, left , i);
                left++;
                i++;
            } else if (nums[i] == 1 ) {
                i++;
            } else {
                swap(nums,i,right);
                right--;
            }
        }
    }
    private void swap(int[] nums, int i ,int j) {
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    }
}

2.Maximum subarray
[Maximum subarray]https://leetcode.com/problems/maximum-subarray/description/
solution:用一个sum和最大值比较

class Solution {
    public int maxSubArray(int[] nums) {
        int max = Integer.MIN_VALUE;
        int sum = 0;
        for (int i = 0; i < nums.length; i++) {
            sum = sum > 0 ? sum + nums[i] : nums[i];
            max = sum > max ? sum : max;
        }
        return max;
    }
}

3.Remove Duplicates from Sorted Array
solution : 排好序的数组,那么重复的元素肯定连在一起。两个指针,一个维护当前数组的长度,一个去遍历数组,跳过重复元素

class Solution {
    public int removeDuplicates(int[] nums) {
        if (nums == null || nums.length == 0) {
            return 0;
        }
        int size = 1;
        for (int i = 1; i < nums.length; i++) {
            if (nums[i] != nums[i - 1]) {
                nums[size++] = nums[i];//跳过重复元素
            }
        }
        return size;
    }
}

4.Maximum SubArray
[连续数组的最大和]https://leetcode.com/problems/maximum-subarray/description/
solution:举例分析数组的规律,例如输入的数组{1,-2,3,10,-4,7,2,-5},试着从头到尾逐个累加示例数组中的每个数字

class Solution {
    public int maxSubArray(int[] nums) {
        int max = Integer.MIN_VALUE;
        int sum = 0;
        for (int i = 0; i < nums.length; i++) {
            sum = sum > 0 ? sum + nums[i] : nums[i];
            max = sum > max ? sum : max;
        }
        return max;
    }
}

5.Majority Elements
[数组中出现次数超过一半的数字]https://leetcode.com/problems/majority-element/description/
solution:数组中有一个数字出现的次数超过了数组长度的一半。那么它出现的次数比其他数字出现次数的和还要多。因此在遍历数组的时候考虑保存两个值,一个是数组中的数字,一个是出现次数。当次数为0的时候,说明前面的数字出现次数正好抵消。那么当nums[i]等于当前值的时候,count + 1,否则-1

class Solution {
    public int majorityElement(int[] nums) {
        if (nums.length  == 0 || nums == null) {
            return 0;
        }
        int current = 0;
        int count = 0;
        for (int i = 0; i < nums.length; i++) {
            if (count == 0) {
                current = nums[i];
                count += 1;
            } else {
                if (nums[i] == current) {
                    count += 1;
                } else {
                    count -= 1;
                }
            }
        }
        return current;        
    }
}

6.数组中重复的数字
[ Find the Duplicate Number]https://leetcode.com/problems/find-the-duplicate-number/description/
solution:我们注意到数组中的数字都在0到n-1的范围内。如果这个数组中没有重复的数字,那么当数组排序之后数字i将出现在下标为i的位置。由于数组中有重复的数字,有些位置可能存在多个数字,同时有些位置可能没有数字。从头到尾依次扫描这个数组中的数字,当扫描到下标为i的数字时,首先比较这个数字(用m表示)是不是等于i,如果是,接着扫描下一个数字。如果不是,拿它和第m个数字比较。如果它和第m个数字相等,就找到了一个重复的数字(该数字的下标为i和m的位置都出现了)。如果它和第m个数字数字不相等,就把第i个数字和第m个数字交换,把m放到属于它的位置。重复。

class Solution {
    public int findDuplicate(int[] nums) {
        int duplicate = 0;
        
        if (nums.length == 0 || nums == null) {
            return 0;
        }
        
        for (int i = 0; i < nums.length - 1; i++) {
            if (nums[i] < 0 || nums[i] > nums.length - 1) {
                return 0;
            }
        }
        
        for (int i = 0; i < nums.length - 1; i++) {
            while (nums[i] != i) {
                if (nums[i] == nums[nums[i]]) {
                    duplicate = nums[i];
                    return duplicate;
                }
                // swap nums[i] and nums[nums[i]]
                int temp = nums[i];
                nums[i] = nums[j];
                nums[j] = temp;
            }
        }
        return duplicate;
    }
}

Python版:

class Solution:
    def findDuplicate(self, nums: List[int]) -> int:
        if len(nums) == 0 or nums is None:
            return 0
        
        print(nums)
        duplicate = 0
        temp = 0
        
        # 注意题解,只有一个重复的整数,也就是找到一个就退出好了,因此i始终为0,因为交换操作保证了在当前循环下每个数都可以遇到      
        for i in range(len(nums)):
            while nums[i] != i:
                if nums[i] == nums[nums[i]]:                   
                    duplicate = nums[i]
                    return duplicate            
                # 此处交换即把num[i]的值与nums[temp]的值位置进行交换,此处就是nums[0]
                temp = nums[i]
                nums[i] = nums[temp]
                nums[temp] = temp

        return duplicate

7.旋转数组的最小数字
[ Find Minimum in Rotated Sorted Array]https://leetcode.com/problems/find-minimum-in-rotated-sorted-array/description/
solution:二分。用两个指针分别指向数组的第一个元素和最后一个元素。按题目中旋转的规则,第一个元素应该是大于或者等于最后一个元素的(这是一般情况,代码有考虑特殊情况)。接着找到数组中间的元素,如果该中间元素位于前面的递增子数组,那么它应该大于或者等于第一个指针指向的元素。此时数组中最小的元素应该位于中间元素的后面。这样把第一个指针指向该中间元素,缩小范围。同样,如果中间元素位于后面的递增子数组,那么它应该小于或者等于第二个指向的元素,此时该数组中最小的元素应该位于中间元素的前面。这样把第二个指针指向该中间元素,缩小范围。这样,第二个指针指向刚好就是最小的元素,结束循环。其他看注释。

class Solution {
    public int findMin(int[] nums) {
        if (nums.length  == 0 || nums == null) {
            return 0;
        }
        int left = 0;
        int right = nums.length - 1;
        int mid = left;//排序数组的前面的0个元素搬到最后面,即排序数组本身,也是数组的一个旋转
        
        while (nums[right] <= nums[left]) {
            if (right - left == 1) {
                mid = right;
                break;
            }
            mid = (left + right) / 2;
            //如果下标为left, right和mid指向的三个数字相等,则只能顺序查找
            if (nums[left] == nums[right] && nums[mid] == nums[left]) {
                return minInOrder(nums, left, right);
            }
            if (nums[mid] >= nums[left]) {
                left = mid;
            }
            else if (nums[mid] <= nums[right]) {
                right = mid;
            }           
        }
        return nums[mid];
    }
    //顺序查找
    private int minInOrder(int[] nums, int left, int right) {
        int result = nums[left];
        for (int i = left; i < right - 1; i++) {
            if (nums[i] < result) {
                result = nums[i];
            }
        }
        return result;
    }
}

8.数组中只出现一次的数字
[Single Number]https://leetcode.com/problems/single-number/description/
solution:可利用异或特有的算数属性,任何一个数字异或它自己都等于0,也就是说,如果从头到尾依次异或数组中的每一个数字,那么最终的结果刚好是那个只出现一次的数字,因为那些出现两次的数字全部在异或中抵消掉了。

class Solution {
    public int singleNumber(int[] nums) {
        int temp = 0;
        for (int i = 0; i < nums.length; i++) {
            temp ^= nums[i];
        }
        return temp;
    }
}

进阶:一个整形数组中,每个数字都出现三次,只有一个数字出现一次,找出这个数字。考虑到整形数字在电脑中存储的时候是四个byte,即32位bit,每一个数字都可以表示成一个32位的0 1 串,那么如果用一个32位的数组,记录数组中所有数字,每一位1出现的次数。然后每一位对3取余,数组中不为0的地方就是那一个只出现一次的数字的二进制中1的位置。例如4出现3次。 4的二进制是 0000 0000 0000 0000 0000 0000 0000 0100 4出现三次的话,
统计的数组就把 数组中的第三位记为3,即 数组为 0000 0000 0000 0000 0000 0000 0000 0300,所有位对3取余,结果一定全为0。

class Solution {
    public int singleNumber(int[] nums) {
        if (nums.length == 0 || nums == null) {
            return 0;
        }
        int bits[] = new int[32]; //定义一个32位数组       
        for (int i = 0; i < bits.length; i++) {
            bits[i]=0;          //初始化  数组中所有值为0
        }            
        for (int i = 0; i < nums.length; i++) {     //对数组中每一个数字                 
            for (int j = 0; j < bits.length; j++) { //这个数字的每一位          
                bits[j] += ((nums[i] >> j) & 1);//记录这个位上是否为1,为1的话 bits数组就加1     
            }
        }              
        int result = 0 ;               
        for (int j = 0; j < 32; j++) {                  
            if (bits[j] % 3 != 0)  //对3取余,是3的倍数的取余后都为0,剩下的就是我们要的
              result += (1 << j);  //把记录的二进制他转化成整形数字                 
        }   
        return result;
    }
}

举一反三

  • 如果一个数组中,每个数字都出现偶数次,只有一个数字出现一次,利用异或即可
  • 如果一个数组中,每个数字都出现奇数(大于1)次,只有一个数字出现一次,那么就用一个32位的数组,记录所有位中为1的个数,最后数组中每一个数字对这个奇数取余,不为0的,把它取出,按它的位数,转化成十进制的数字。

9.数组中第K大的数
[Kth Largest Element in an Array]https://leetcode.com/problems/kth-largest-element-in-an-array/description/
solution:如果考虑海量数据和内存不够的话,采用最小堆(

class Solution {
    public int findKthLargest(int[] nums, int k) {
        if (k <= 0 || nums.length == 0 || nums == null) {
            return 0;
        }
        PriorityQueue<Integer> minHeap = new PriorityQueue<Integer>();
        for (int i = 0; i < nums.length; i++) {
            minHeap.add(nums[i]);
            if (minHeap.size() > k) {
                minHeap.poll();
            }
        }
        return minHeap.poll();
    }
}

solution:常规思路,partition思想
10.把数组排成最小的数
[Largest Number]https://leetcode.com/problems/largest-number/description/
solution:先把整形数组转换成String数组,然后将String数组排序,最后将排好序的字符串数组拼接出来。关键就是制定排序规则。排序规则如下:
若ab > ba,则a > b
若ab < ba,则a < b
若ab = ba,则a = b

import java.util.*;
class Solution {
    public String largestNumber(int[] nums) {
        if (nums == null || nums.length == 0) {
            return "";
        }
        int n = nums.length;
        String[] str = new String[n];
        StringBuilder sb = new StringBulider();
        //数组转化为字符串
        for (int i = 0; i < n; i++) {
            str[i] = String.valueOf(nums[i]);
        }
        Arrays.sort(str, new Comparator<String>() {
            @Override
            public int compare(String s1, String s2) {
                String c1 = s1 + s2;
                String c2 = s2 + s1;
                return c1.compareTo(c2);
            }
        }
        );
        for (int i = 0; i < n; i++) {
            sb.append(str[i]);
        }
        return sb.toString();
    }
}

11.二维数组中的查找
[Search a 2D Matrix]https://leetcode.com/problems/search-a-2d-matrix/description/
solutions:由于二维数组是排好序的,既行从左到右递增,列从上到下递增。因此每次选取右上角的元素与目标数字进行比较。如果大于目标数字,那么目标只可能在左边,于是删掉右上角元素所在的列

class Solution {
    public boolean searchMatrix(int[][] matrix, int target) {
        if(matrix == null || matrix.length == 0){
            return false;
        }
        
        if(matrix[0] == null || matrix[0].length == 0){
            return false;
        }
        int m = matrix.length;
        int n = matrix[0].length;
        int i = 0;
        int j = n - 1;
        while (i < m && j >= 0) {
            //i,j的定义已经在右上角了
            if (matrix[i][j] == target) {
                return true;
            } else if (matrix[i][j] > target) {
                j--;
            } else {
                i++;
            }
        }
        return false;
    }
}

12.数组中的逆序对
[ Count of Smaller Numbers After Self]https://leetcode.com/problems/count-of-smaller-numbers-after-self/description/
solution:先把数组分成子数组,先统计出子数组内部的逆序对的数目,然后再统计出两个相邻子数组之间的逆序对的数目。在统计逆序对的过程中,还需要对数组排序,归并排序。
剑指offer解法

public static int inversePairs(int[] data) {
        if (data == null || data.length < 1) {
            throw new IllegalArgumentException("Array arg should contain at least a value");
        }

        int[] copy = new int[data.length];
        System.arraycopy(data, 0, copy, 0, data.length);

        return inversePairsCore(data, copy, 0, data.length - 1);
    }

    private static int inversePairsCore(int[] data, int[] copy, int start, int end) {

        if (start == end) {
            copy[start] = data[start];
            return 0;
        }

        int length = (end - start) / 2;
        int left = inversePairsCore(copy, data, start, start + length);
        int right = inversePairsCore(copy, data, start + length + 1, end);

        // 前半段的最后一个数字的下标
        int i = start + length;
        // 后半段最后一个数字的下标
        int j = end;
        // 开始拷贝的位置
        int indexCopy = end;
        // 逆序数
        int count = 0;

        while (i >= start && j >= start + length + 1) {
            if (data[i] > data[j]) {
                copy[indexCopy] = data[i];
                indexCopy--;
                i--;
                count += j - (start + length); // 对应的逆序数
            } else {
                copy[indexCopy] = data[j];
                indexCopy--;
                j--;
            }
        }

        for (; i >= start;) {
            copy[indexCopy] = data[i];
            indexCopy--;
            i--;
        }

        for (; j >= start + length + 1;) {
            copy[indexCopy] = data[j];
            indexCopy--;
            j--;
        }
        return count + left + right;
    }

LeetCode变形解法https://leetcode.com/problems/count-of-smaller-numbers-after-self/description/
solution:Traverse from the back to the beginning of the array, maintain an sorted array of numbers have been visited. Use findIndex() to find the first element in the sorted array which is larger or equal to target number. For example, [5,2,3,6,1], when we reach 2, we have a sorted array[1,3,6], findIndex() returns 1, which is the index where 2 should be inserted and is also the number smaller than 2. Then we insert 2 into the sorted array to form [1,2,3,6].

class Solution {
    public List<Integer> countSmaller(int[] nums) {
        Integer[] ans = new Integer[nums.length];
        List<Integer> sorted = new ArrayList<Integer>();
        for (int i = nums.length - 1; i >= 0; i--) {
            int index = findIndex(sorted, nums[i]);
            ans[i] = index;
            sorted.add(index, nums[i]);
        }
        return Arrays.asList(ans);
    }
    private int findIndex(List<Integer> sorted, int target) {
    if (sorted.size() == 0) return 0;
    int start = 0;
    int end = sorted.size() - 1;
    if (sorted.get(end) < target) return end + 1;
    if (sorted.get(start) >= target) return 0;
    while (start + 1 < end) {
        int mid = start + (end - start) / 2;
        if (sorted.get(mid) < target) {
            start = mid + 1;
        } else {
            end = mid;
        }
    }
    if (sorted.get(start) >= target) return start;
    return end;
    }
}
  1. 乱序数组中的最长递增子序列
    题型A:输出最长递增子序列的数组(即包含的数)
    solution:给出两种解法,普通的dp,dp + 二分。具体看注释:
public class Problem_05_LIS {
 
    public static int[] lis1(int[] arr) {
        if (arr == null || arr.length == 0) {
            return null;
        }
        int[] dp = getdp1(arr);
        return generateLIS(arr, dp);
    }
//dp中放的是,对应数组中每个元素为输出序列的最后一个值时的最大长度
//方法一:O(n^2)复杂度,具体思路是:两层循环,外层为i时,内从从0到i,依次判断,
//当加入 arr[i]的值后,更新dp中最长子序列的长度,最长子序列更新,依赖于i前面的dp
//中的数组值,若是arr[i]比i之前的某个位置上的的数要大,则通过max(dp[i], dp[j] + 1);
//来更新第i位上的值。
   public static int[] getdp1(int[] arr) {
        int[] dp = new int[arr.length];
        for (int i = 0; i < arr.length; i++) {
            dp[i] = 1;
            for (int j = 0; j < i; j++) {
                if (arr[i] > arr[j]) {
                    //如果arr[i]比arr[j]要大,说明递增最长子序列要增加
                    dp[i] = Math.max(dp[i], dp[j] + 1);
                    //plus 1 since strictly speaking we need to count nodes on the paths
                }
            }
        }
        return dp;
    }
  //根据 dp 数组的值生成要打印的数组,作为最后结果的输出,
    public static int[] generateLIS(int[] arr, int[] dp) {
        int len = 0;
        int index = 0;
        for (int i = 0; i < dp.length; i++) {
            if (dp[i] > len) {
                len = dp[i];
                index = i;
            }
        }
        int[] lis = new int[len];
        lis[--len] = arr[index];
        for (int i = index; i >= 0; i--) {
            if (arr[i] < arr[index] && dp[i] == dp[index] - 1) {
                lis[--len] = arr[i];
                index = i;
            }
        }
        return lis;
    }
}
public static int[] lis2(int[] arr) {
        if (arr == null || arr.length == 0) {
            return null;
        }
        int[] dp = getdp2(arr);
        return generateLIS(arr, dp);
    }
//方法二,时间复杂度为O(N*logN),这个时间复杂度具体体现在一个for循环里套了一个二分查找
//dp中放的是,对应数组中每个元素为输出序列的最后一个值时的最大长度
//ends数组作为一个辅助数组,存放的是有效区的数值,ends[i]的含义是:
//当遍历到当前的数时,ends[i]表示的是,遍历到当前时刻,长度为i+1的子序列中的末尾元素值
//每次更新的是长度为i+1子序列的末尾元素的值,那么,可以通过二分法查找每个当前遍历到的
//元素在ends中应该所处的位置
//然后更新对应的位置上的元素值,然后根据i+1,就可以知道,当前元素作为子序列的末尾元素时,
//前面有几个数了(i)
//程序中的right值记录的是,有效区数组ends的长度,l为左边界,r为右边界,m为中间值
public static int[] getdp2(int[] arr) {
        int[] dp = new int[arr.length];
        int[] ends = new int[arr.length];
        ends[0] = arr[0];
        dp[0] = 1;
        int right = 0;
        int l = 0;
        int r = 0;
        int m = 0;
        for (int i = 1; i < arr.length; i++) {
            l = 0;
            r = right;
            while (l <= r) {
                m = (l + r) / 2;
                if (arr[i] > ends[m]) {
                    l = m + 1;
                } else {
                    r = m - 1;
                }
            }
            right = Math.max(right, l);  //更新有效区数组的边界值,若是所有的元素都小于当前的元素,则数组值往外扩充一个
            ends[l] = arr[i];
            dp[i] = l + 1;
        }
        return dp;
    }

[LeetCode版]https://leetcode.com/problems/longest-increasing-subsequence/description/ 只需返回最大长度即可,dp也可以做,但是直接使用二分更为简便。

class Solution {
    public int lengthOfLIS(int[] nums) {
        if (nums == null || nums.length == 0) {
            return 0;
        }
        int[] tails = new int[nums.length];
        int size = 0;
        for (int x : nums) {
            int i = 0;
            int j = size;
            while (i != j) {
                int m = (i + j) / 2;
                if (tails[m] < x) {
                    i = m + 1;
                } else {
                    j = m;
                }
            }
            tails[i] = x;
            if (i == size) {
                ++size;
            }
        }
        return size; 
    }
}

通俗解法:

public class solution {
    public int lengthOfLIS(int[] nums) {
        if (nums == null || nums.length == 0) {
            return 0;
        }
        int[] dp = new int[nums.length];
        dp[0] = nums[0];
        int len = 0;
        for (int i = 0; i < nums.length; i++) {
            
            //dp为辅助数组,第一个数字nums[0]放进去之后,形成第一个有效区
            //然后接下来的nums[i]在dp数组中寻找第一个比nums[i]自己大的数(二分)
           //dp[i]代表长度为i + 1的最长递增子序列的最小末尾
            int pos = binarySearch(dp, len, nums[i]);
            if (nums[i] < dp[pos]) {
                dp[pos] = nums[i];
            }
            if (pos > len) {
                len = pos;
                dp[len] = nums[i];
            }
        }
        return len + 1;
        //return dp;
    }
    private int binarySearch(int[] dp, int len, int val) {
        int left = 0;
        int right = len;
        while (left + 1 < right) {
            int mid = left + (right - left) / 2;
            if (dp[mid] == val) {
                return mid;
            } else {
                if (dp[mid] < val) {
                    left = mid;
                } else {
                    right = mid;
                }
            }

        }
        if (dp[right] < val) {
            return len + 1;
        } else if (dp[left] >= val) {
            return left;
        } else {
            return right;
        }
    }
}

附上二分查找的实现代码:

//二分基本思想:
//将n个元素分成个数大致相同的两半,取a[n/2]与欲查找的x作比较,
//如果x=a[n/2]则找到x,算法终止。如果x<a[n/2],
//则我们只要在数组a的左半部继续搜索x(这里假设数组元素呈升序排列)
//如果x>a[n/2],则我们只要在数组a的右 半部继续搜索x


//非递归
class BinarySearch {
    public static int binarySearch(int[] nums, int low , int high, int value) {
        //value是欲查找的值
        int left = low;
        int right = high - 1;
        while (left <= right) {
            int mid = left + (right - left) / 2;
            if (value < nums[mid]) {
                high = mid - 1;
            } else if (value > nums[mid]) {
                low = mid + 1;
            } else {
                return mid; 
            }
        }
        return - 1;
    }
}

//递归
class BinarySearch {
    public static int binarySearch(int[] nums, int low, int high, int value) {
        if (low > high) {
            return -1;
        }
        int mid = left + (right - left) / 2;
        if (value < nums[mid]) {
            return binarySearch(nums, low, mid - 1, value);
        } else if(value > nums[mid]) {
            return binarySearch(nums, mid + 1, high, value);
        } else {
            return mid;
        }
    }
}
  1. 数组的全排列
    [Permutations]https://leetcode.com/problems/permutations/description/
    solution:递归,DFS。题意:给定一个数组,返回这个数组可能出现的所有组合。两个列表形式(结果集,加小子集)。具体做法看注释。
public class Solution {
    List<List<Integer>> res = new ArrayList<List<Integer>>();
    
    public List<List<Integer>> permute(int[] nums) {
        int len = nums.length;
        if (nums == null || len == 0) {
            return res;
        }
        //前后交换元素
        exchange(nums, 0, len);
        return res;
    }
    
    public void exchange(int[] nums, int i, int len) {
        //当前数组加到结果集中
        //如果已经到最后一个元素,前面的数已经排好,输出
        if (i == len - 1) {
            //注意这里list与上面res的写法不同之处
            List<Integer> list = new ArrayList<>();
            for (int j = 0; j < len; j++) {
                list.add(nums[j]);
            }
            res.add(list);
            return;
        }
        //思考场景,定了第一个数之后后面的解已经有了。那么交换前后元素
        //从当前位置的数跟后面的数交换
        for (int j = i; j < len; j++) {
            swap(nums, i, j);
            exchange(nums, i + 1, len);
            swap(nums, i, j);
        }
    }
    
    public void swap(int[] nums, int i, int j) {
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    }
}

15、搜索旋转数组
搜索旋转排序数组
solution:
题目要求O(logN)的时间复杂度,基本可以断定本题是需要使用二分查找,怎么分是关键
由于题目说数字了无重复,举个例子
1 2 3 4 5 6 7 可以大致分为两类,
第一类 2 3 4 5 6 7 1这种,也就是nums[start] <= nums[mid]。此例子中就是2 <= 5。这种情况下,前半部分有序。因此如果 nums[start] <=target<nums[mid]。则在前半部分找,否则去后半部分找。
第二类 6 7 1 2 3 4 5这种,也就是nums[start] > nums[mid]。此例子中就是6 > 2
这种情况下,后半部分有序。因此如果 nums[mid] <target<=nums[end]。则在后半部分找,否则去前半部分找。

class Solution:
    def search(self, nums: List[int], target: int) -> int:
        if len(nums) == 0 or nums is None:
            return -1
        
        left = 0
        right = len(nums) - 1
        
        while left <= right:
            mid = left + (right - left) // 2
            if nums[mid] == target:
                return mid
            
            if nums[left] <= nums[mid]:
                if target <= nums[mid] and target >= nums[left]:
                    right = mid - 1
                else:
                    left = mid + 1
            else:
                if target >= nums[mid] and target <= nums[right]:
                    left = mid + 1
                else:
                    right = mid - 1
        
        return -1
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,294评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,493评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,790评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,595评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,718评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,906评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,053评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,797评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,250评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,570评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,711评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,388评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,018评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,796评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,023评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,461评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,595评论 2 350

推荐阅读更多精彩内容