zoukankan      html  css  js  c++  java
  • leetcode 704 Java二分查找的三种解法

    leetcode 704 Java二分查找的三种解法

    题目

    给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。

    示例 1:

    输入: nums = [-1,0,3,5,9,12], target = 9
    输出: 4
    解释: 9 出现在 nums 中并且下标为 4
    示例 2:

    输入: nums = [-1,0,3,5,9,12], target = 2
    输出: -1
    解释: 2 不存在 nums 中因此返回 -1

    提示:

    你可以假设 nums 中的所有元素是不重复的。
    n 将在 [1, 10000]之间。
    nums 的每个元素都将在 [-9999, 9999]之间。

    来源:力扣(LeetCode)
    链接:https://leetcode-cn.com/problems/binary-search
    著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。


    相信所有科班的同学对二分查找肯定不陌生,说起来有三种解法,本质上来讲是两种,方法一和方法二是本质上都是递归解法,比较简单,但确实是细节比较多。

    方法一:Java的Arrays.binarySearch()

    可以直接使用Java中的API解决,只不过Java中的API需要手动处理一下结果。JavaAPI如下:

    在这里插入图片描述

    注意一下返回值,按照本题来讲,如果找不到的话,直接返回-1,但是在API中返回的不是-1。比如在数组[1,4,2,6,11,32]中,经过排序之后[1,2,4,5,11,32],如果查找13,它会直接返回-6,解释为:从第一个元素之前标为-1,直到第一个大于target数字的元素之前为止,返回负值。可以详细查看下API中的描述,描述中的插入位置很奇妙,其实就跟集合中的remove的API一样,在删除元素之前进行操作。

    当然,也可以查看下binarySearch的源码,里面的/2操作也是可以值得借鉴的。

    int mid = (low + high) >>> 1;
    

    代码:

    package com.yamon.test;
    
    import java.util.Arrays;
    public class Search {
    
        public int search(int[] nums, int target) {
            int binarySearch = Arrays.binarySearch(nums, target);
            if (binarySearch<0){
                return -1;
            }else{
                return binarySearch;
            }
        }
    
        public static void main(String[] args) {
            int[] arr = {1,2,4,5,11,32};
            System.out.println(Arrays.binarySearch(arr, 13));
    //        System.out.println(new Search().search(arr, 13));
        }
    }
    
    

    方法二:迭代处理

    标准的迭代操作:

    package com.yamon.test;
    import java.util.Arrays;
    public class Search2 {
        public int search(int[] nums, int target) {
            int low = 0;
            int high=nums.length-1;  //注意这里
    
            while (low<=high){   //还有这里 要小于等于,要不然会报数组越界异常。
                int mid = low+(high-low)>>1;
                if (nums[mid] == target){
                    return mid;
                }else if (target>nums[mid]){
                    low = mid +1;
                }else {
                    high= mid-1;
                }
            }
            return -1;
        }
    
        public static void main(String[] args) {
            int[] arr = {-1,0,3,5,9,12};
    
            System.out.println(new Search2().search(arr, 3));
    
        }
    }
    

    没什么可讲的,就是细节比较多。

    方法三:递归处理

    到现在,递归给我的感觉其实也就是for循环或者while循环,只不过用空间来换时间了而已。仔细体会下,尤其是注意一下low和high的变化,是不是跟while或者for循环里面类似。

    package com.yamon.test;
    public class Search3 {
        public int search(int[] nums, int target) {
            return backtrack(0, nums.length - 1, nums, target);
        }
        private int backtrack(int low, int high, int[] nums, int target) {
            if (low > high) return -1;
            int mid = low + ((high - low) >> 1);
            if (nums[mid] == target) {
                return mid;
            }
            if (target > nums[mid]) {
                return backtrack(mid + 1, high, nums, target);
            }
            if (target < nums[mid]){
                return backtrack(low, mid - 1, nums, target);
            }
            return -1;
        }
        public static void main(String[] args) {
            int[] arr = {-1, 0, 3, 5, 9, 12};
            System.out.println(new Search3().search(arr, 9));
        }
    }
    

    说一下我存在的问题:将递归看成一个循环的问题,循环的是问题的子问题,那么就不用再在子问题(递归函数)里面用循环了;既然是个子问题,那么必然有return值,在这里的话每个if中要有return值;最后一个就是深化递归的思想,递归要有终止条件和子问题的解法。

    总结

    有什么可以总结的吗?有,不过都在文中了。

    博客网站 https://yamon.top 个人网站 https://yamon.top/resume GitHub网站 https://github.com/yamonc 欢迎前来访问
  • 相关阅读:
    AGC 015 E
    CF 1041 F. Ray in the tube
    AGC 005 D
    CF 348 D. Turtles
    2069: [POI2004]ZAW
    AGC 007 D
    zhengruioi 470 区间
    2653: middle
    Django 源码安装及使用
    Django MTV模型思想
  • 原文地址:https://www.cnblogs.com/chenyameng/p/14886197.html
Copyright © 2011-2022 走看看