打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
二分查找的变体问题

之前一篇随笔介绍了二分查找的最最基本的实现,该实现要求待查找的数据是有序且不存在重复元素的数组。

而今天我们就要介绍二分查找的变体问题,待查找数据是有序但是存在重复元素的数组,主要有以下几个问题:

  1. 查找第一个等于指定值的元素的位置。
  2. 查找最后一个等于指定值的元素的位置。
  3. 查找第一个大于指定值的元素的位置。
  4. 查找最后一个小于指定值的元素的位置。

这个呢,就要比不存在重复元素的数组稍微复杂一些,但也不难,只要我们能够找好临界条件就事半功倍了。

原理呢,没有啥要讲的,可以直接看代码,很容易看懂,并且我同时写了通过递归实现和循环实现。

 

查找第一个等于指定值的元素的位置(第一种实现方式,该方式是找到了一个值之后,从该位置往前数看还有没有等于指定值的元素)

 1 package com.structure.search; 2  3 /** 4  * 二分查找法 5  * 6  * @author zhangxingrui 7  * @create 2019-02-15 21:29 8  **/ 9 public class BinarySearch_FirstValue {10 11     public static void main(String[] args) {12         int[] nums = new int[]{4, 6, 9, 9, 19, 19, 30, 30, 40, 500, 500, 500004, 500004};13         System.out.println(binarySearch(nums, 0, nums.length - 1, 30));14         System.out.println(binarySearch(nums, 30));15     }16 17     /**18      * @Author: xingrui19      * @Description: 二分查找法(针对有序数组且存在重复元素(找到第一个指定值的位置)-递归方式实现)20      * @Date: 21:37 2019/2/1521      */22     private static int binarySearch(int[] nums, int p, int r, int k){23         if(p > r)24             return -1;25 26         int mid = (p   r) / 2;27         if(nums[mid] == k)28             return getMinIndex(nums, mid, k);29 30         if(k > nums[mid])31             return binarySearch(nums, mid   1, r, k);32         else33             return binarySearch(nums, p,  mid - 1, k);34     }35 36     /**37      * @Author: xingrui38      * @Description: 二分查找法(针对有序数组且不存在重复元素(找到第一个指定值的位置)-循环实现)39      * @Date: 21:37 2019/2/1540      */41     private static int binarySearch(int[] nums, int k){42         int p = 0;43         int r = nums.length - 1;44         while (p <= r){45             int mid = (p   r) / 2;46 47             if(nums[mid] == k)48                 return getMinIndex(nums, mid, k);49 50             if(k > nums[mid])51                 p = mid   1;52             else53                 r = mid - 1;54         }55         return -1;56     }57 58     private static int getMinIndex(int[] numbers, int mid, int k){59         while (mid > 0 && numbers[mid - 1] == k){60             mid--;61         }62         return mid;63     }64 65 }

 

查找第一个等于指定值的元素的位置(第二种实现方式,该方式是找到了一个值之后,判断当前位置是否是临界元素,如果不是则继续执行)

 1 package com.structure.search; 2  3 /** 4  * 二分查找法 5  * 6  * @author zhangxingrui 7  * @create 2019-02-15 21:29 8  **/ 9 public class BinarySearch_FirstValue2 {10 11     public static void main(String[] args) {12         int[] nums = new int[]{4, 6, 9, 9, 19, 19, 30, 30, 30, 30, 40};13         System.out.println(binarySearch(nums, 0, nums.length - 1, 30));14         System.out.println(binarySearch(nums, 30));15     }16 17     /**18      * @Author: xingrui19      * @Description: 二分查找法(针对有序数组且存在重复元素(找到第一个指定值的位置)-递归方式实现)20      * @Date: 21:37 2019/2/1521      */22     private static int binarySearch(int[] nums, int p, int r, int k){23         if(p > r)24             return -1;25         int mid = (p   r) / 2;26 27         if(k > nums[mid])28             return binarySearch(nums, mid   1, r, k);29         else if(k < nums[mid])30             return binarySearch(nums, p,  mid - 1, k);31         if(mid == 0 || nums[mid - 1] != k)32             return mid;33         else34             return binarySearch(nums, p,  mid - 1, k);35     }36 37     /**38      * @Author: xingrui39      * @Description: 二分查找法(针对有序数组且不存在重复元素(找到第一个指定值的位置)-循环实现)40      * @Date: 21:37 2019/2/1541      */42     private static int binarySearch(int[] nums, int k){43         int p = 0;44         int r = nums.length - 1;45 46         while (p <= r){47             int mid = (p   r) / 2;48 49             if(k > nums[mid])50                 p = mid   1;51             else if(k < nums[mid])52                 r = mid - 1;53             else if(mid == 0 || nums[mid - 1] != k)54                 return mid;55             else56                 r = mid - 1;57         }58         return -1;59     }60 61 }

 

查找最后一个等于指定值的元素的位置(第一种实现方式,该方式是找到了一个值之后,从该位置往后数看还有没有等于指定值的元素

 1 package com.structure.search; 2  3 /** 4  * 二分查找法 5  * 6  * @author zhangxingrui 7  * @create 2019-02-15 21:29 8  **/ 9 public class BinarySearch_LastValue {10 11     public static void main(String[] args) {12         int[] nums = new int[]{4, 6, 9, 9, 19, 19, 30, 30, 40, 500, 500, 500004, 500004};13         System.out.println(binarySearch(nums, 0, nums.length - 1, 30));14         System.out.println(binarySearch(nums, 30));15     }16 17     /**18      * @Author: xingrui19      * @Description: 二分查找法(针对有序数组且存在重复元素(找到第一个指定值的位置)-递归方式实现)20      * @Date: 21:37 2019/2/1521      */22     private static int binarySearch(int[] nums, int p, int r, int k){23         if(p > r)24             return -1;25 26         int mid = (p   r) / 2;27         if(nums[mid] == k)28             return getMaxIndex(nums, mid, k);29 30         if(k > nums[mid])31             return binarySearch(nums, mid   1, r, k);32         else33             return binarySearch(nums, p,  mid - 1, k);34     }35 36     /**37      * @Author: xingrui38      * @Description: 二分查找法(针对有序数组且不存在重复元素(找到第一个指定值的位置)-循环实现)39      * @Date: 21:37 2019/2/1540      */41     private static int binarySearch(int[] nums, int k){42         int p = 0;43         int r = nums.length - 1;44         while (p <= r){45             int mid = (p   r) / 2;46 47             if(nums[mid] == k)48                 return getMaxIndex(nums, mid, k);49 50             if(k > nums[mid])51                 p = mid   1;52             else53                 r = mid - 1;54         }55         return -1;56     }57 58     private static int getMaxIndex(int[] numbers, int mid, int k){59         int length = numbers.length;60         while (mid < length && numbers[mid   1] == k){61             mid  ;62         }63         return mid;64     }65 66 }

 

查找最后一个等于指定值的元素的位置(第二种实现方式,该方式是找到了一个值之后,判断当前位置是否是临界元素,如果不是则继续执行)

 1 package com.structure.search; 2  3 /** 4  * 二分查找法 5  * 6  * @author zhangxingrui 7  * @create 2019-02-15 21:29 8  **/ 9 public class BinarySearch_LastValue2 {10 11     public static void main(String[] args) {12         int[] nums = new int[]{4, 6, 9, 9, 19, 19, 30, 30, 30, 30, 40};13         System.out.println(binarySearch(nums, 0, nums.length - 1, 30));14         System.out.println(binarySearch(nums, 30));15     }16 17     /**18      * @Author: xingrui19      * @Description: 二分查找法(针对有序数组且存在重复元素(找到第一个指定值的位置)-递归方式实现)20      * @Date: 21:37 2019/2/1521      */22     private static int binarySearch(int[] nums, int p, int r, int k){23         if(p > r)24             return -1;25         int mid = (p   r) / 2;26 27         if(k > nums[mid])28             return binarySearch(nums, mid   1, r, k);29         else if(k < nums[mid])30             return binarySearch(nums, p,  mid - 1, k);31         if(mid == nums.length - 1 || nums[mid   1] != k)32             return mid;33         else34             return binarySearch(nums, mid   1, r, k);35     }36 37     /**38      * @Author: xingrui39      * @Description: 二分查找法(针对有序数组且不存在重复元素(找到第一个指定值的位置)-循环实现)40      * @Date: 21:37 2019/2/1541      */42     private static int binarySearch(int[] nums, int k){43         int p = 0;44         int r = nums.length - 1;45 46         while (p <= r){47             int mid = (p   r) / 2;48 49             if(k > nums[mid])50                 p = mid   1;51             else if(k < nums[mid])52                 r = mid - 1;53             else if(mid == nums.length - 1 || nums[mid   1] != k)54                 return mid;55             else56                 p = mid   1;57         }58         return -1;59     }60 61 }

 

查找第一个大于指定值的元素的位置

 1 package com.structure.search; 2  3 /** 4  * 二分查找法 5  * 6  * @author zhangxingrui 7  * @create 2019-02-15 21:29 8  **/ 9 public class BinarySearch_FirstGreaterValue {10 11     public static void main(String[] args) {12         int[] nums = new int[]{4, 6, 9, 9, 19, 19, 30, 30, 30, 30, 40};13         System.out.println(binarySearch(nums, 0, nums.length - 1, 9));14         System.out.println(binarySearch(nums, 9));15     }16 17     /**18      * @Author: xingrui19      * @Description: 二分查找法(针对有序数组且存在重复元素(找到第一个大于指定值的位置)-递归方式实现)20      * @Date: 21:37 2019/2/1521      */22     private static int binarySearch(int[] nums, int p, int r, int k){23         if(p > r)24             return -1;25         int mid = (p   r) / 2;26 27         if(k >= nums[mid])28             return binarySearch(nums, mid   1, r, k);29         else{30             if(mid == nums.length - 1 || nums[mid - 1] <= k)31                 return mid;32             else return binarySearch(nums, p, mid - 1, k);33         }34     }35 36     /**37      * @Author: xingrui38      * @Description: 二分查找法(针对有序数组且不存在重复元素(找到第一个大于指定值的位置)-循环实现)39      * @Date: 21:37 2019/2/1540      */41     private static int binarySearch(int[] nums, int k){42         int p = 0;43         int r = nums.length - 1;44 45         while (p <= r){46             int mid = (p   r) / 2;47 48             if(k >= nums[mid])49                 p = mid   1;50             else if(k < nums[mid]){51                 if(mid == nums.length - 1 || nums[mid - 1] == k)52                     return mid;53                 else54                     r = mid - 1;55             }56         }57         return -1;58     }59 60 }

 

查找最后一个小于指定值的元素的位置

 1 package com.structure.search; 2  3 /** 4  * 二分查找法 5  * 6  * @author zhangxingrui 7  * @create 2019-02-15 21:29 8  **/ 9 public class BinarySearch_LastLessValue {10 11     public static void main(String[] args) {12         int[] nums = new int[]{4, 6, 9, 9, 19, 19, 30, 30, 30, 30, 40};13         System.out.println(binarySearch(nums, 0, nums.length - 1, 30));14         System.out.println(binarySearch(nums, 30));15     }16 17     /**18      * @Author: xingrui19      * @Description: 二分查找法(针对有序数组且存在重复元素(找到第一个大于指定值的位置)-递归方式实现)20      * @Date: 21:37 2019/2/1521      */22     private static int binarySearch(int[] nums, int p, int r, int k){23         if(p > r)24             return -1;25         int mid = (p   r) / 2;26 27         if(k <= nums[mid]){28             return binarySearch(nums, p, mid - 1, k);29         }30         else{31             if(mid == 0 || nums[mid   1] == k)32                 return mid;33             else34                 return binarySearch(nums, mid   1, r, k);35         }36     }37 38     /**39      * @Author: xingrui40      * @Description: 二分查找法(针对有序数组且不存在重复元素(找到第一个大于指定值的位置)-循环实现)41      * @Date: 21:37 2019/2/1542      */43     private static int binarySearch(int[] nums, int k){44         int p = 0;45         int r = nums.length - 1;46 47         while (p <= r){48             int mid = (p   r) / 2;49 50             if(k <= nums[mid])51                 r = mid - 1;52             else if(k > nums[mid]){53                 if(mid == 0 || nums[mid   1] == k)54                     return mid;55                 else56                     p = mid   1;57             }58         }59         return -1;60     }61 62 }

 

  以上就是关于二分查找的几个变体问题了,代码还是比较详细的。

 

来源:http://www.icode9.com/content-4-118351.html
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
Java中的Arrays.binarySearch()方法详解
面试前必知必会的二分查找及其变种
排序算法--折半插入排序(二分查找排序)
C语言中数组的一些基本知识小结
419,剑指 Offer-旋转数组的最小数字
LeetCode 215.数组中的第K个最大元素
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服