数据结构与算法-LeetCode练习二分查找应用

LeetCode 153. Find Minimum in Rotated Sorted Array

查找循环排序数组的最小元素(循环排序数组可以理解,一个环状数组(0,1,2,4,5,6,7),从其中一个元素断开后4,5,6,7,0,1,2)。

查找一个数组的最小原始,我们知道最简单的方式就是循环遍历其中数字,时间复杂度O(n)肯定能找到这个元素。我们看循环排序数组的结构,我们发现我们的数组还不完全是一个乱序数组,我们通过分析数组的规律,我们可以看的出,我们的数组还是局部有序的,我们的数组可以出现以下三种情况:

  1. 左边有序(如:2,4,5,6,7,0,1)
  2. 右边有序(如:6,7,0,1,2,4,5)
  3. 整个有序(如:0,1,2,4,5,6,7)

分析以上情况,我们知道我们的元素至少部分还是有序的,我们可以尝试二分法来查找最小元素,实现如下:

public static int findMin(int[] nums) {
        return findMin(nums, 0, nums.length - 1);
    }

    /*
     * 二分查找的实现主体
     */
    public static int findMin(int[] arr, int left, int right) {
        if (left == right) {
            return arr[left];
        }
        int middle = (left + right) / 2;
        if (arr[left] <= arr[middle] && arr[right] <= arr[middle]) { //当元素左边有序的情况
            return findMin(arr, middle + 1, right);
        } else if (arr[left] >= arr[middle] && arr[right] >= arr[middle]) { //当元素右边有序的情况
            return findMin(arr, left, middle);
        } else { //此时元素全部有序
            return arr[left];
        }
    }

LeetCode 33. Search in Rotated Sorted Array
查找循环排序数组的存在某个元素,返回该元素的位置(索引),如果不存在该元素,就返回-1.

public static int findNums(int[] nums, int target) {
        return findNums(nums, 0, nums.length - 1, target);
    }

    /*
     * 二分查找的实现主体
     */
    public static int findNums(int[] arr, int left, int right, int target) {
        if (left > right) {
            return -1;
        }
        int middle = (left + right) / 2; 
        if (arr[left] == target) { //当前查找部分的left元素大小等于目标数字
            return left;
        }
        if (arr[right] == target) //当前查找部分的right元素大小等于目标数字
            return right;
        if (arr[middle] == target) { //当前查找部分的middle元素大小等于目标数字
            return middle;
        }
        if (arr[left] < arr[middle] && arr[right] < arr[middle]) { //当元素左边有序的情况
            if (arr[middle] > target) { //当中间元素大于目标元素
                //当最左边的元素大于目标元素,在右半部分查找,否则,在左半部分查找
                return arr[left] > target ? findNums(arr, middle + 1, right,
                        target) : findNums(arr, left, middle - 1, target); 
            } else { //当中间元素小于目标元素
                return findNums(arr, middle + 1, right, target);
            }
        } else if (arr[left] > arr[middle] && arr[right] > arr[middle]) {//当元素右边有序的情况
            if (arr[middle] > target) { //当中间元素大于目标元素
                return findNums(arr, left, middle - 1, target);
            } else { //当中间元素小于目标元素
                //当最右边的元素大于目标元素,在右半部分查找,否则,在左半部分查找
                return arr[right] > target ? findNums(arr, middle + 1, right,
                        target) : findNums(arr, left, middle - 1, target);
            }
        } else { //当元素整个有序的情况
            if (arr[middle] > target) {
                return findNums(arr, left, middle - 1, target);
            } else {
                return findNums(arr, middle + 1, right, target);
            }
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值