二分查找小结

在做leetcode二分查找类型题目时写while条件总担心写错,也确实好几次都是得到Wrong Answer之后再修改对的。在做Search for a range一题时,虽然被Accept了,但看网上其他同学的解析并不是特别理解,终于下决心去好好研究下最经典的二分查找算法,搞清楚不同情况下为什么while条件写法不一样。很幸运,很快便找到一遍总结得很棒的博客: 
http://blog.csdn.net/daniel_ustc/article/details/17307937 
拜读后自己实现了下,实现过程中对while条件不同情况下为什么不一样理解得更深刻了。 

实现的三个二分查找方法分别解决如下问题: 
1)查找数组中target出现的下标,不存在返回-1 
2)查找数组中target第一次出现的下标位置,若不存在返回-1 
3)查找数组中target最后一次出现的下标位置,若不存在返回-1 
PS: 数组升序排列,可能有重复元素 

 1 package org.work.basic.binarysearch;
 2 
 3 import junit.framework.Assert;
 4 import org.junit.Test;
 5 
 6 public class BinarySearchCore {
 7 
 8     @Test 
 9     public void testBinarySearch() {
10         int[] nums = {0,1,1,1,2};
11         Assert.assertEquals(2, binarySearch(nums, 1));
12         Assert.assertEquals(1, binarySearchFirst(nums, 1));
13         Assert.assertEquals(3, binarySearchLast(nums, 1));
14         int[] nums1 = {1};
15         Assert.assertEquals(0, binarySearch(nums1, 1));
16         Assert.assertEquals(0, binarySearchFirst(nums1, 1));
17         Assert.assertEquals(0, binarySearchLast(nums1, 1));
18         int[] nums2 = {1,1};
19         Assert.assertEquals(0, binarySearch(nums2, 1));
20         Assert.assertEquals(0, binarySearchFirst(nums2, 1));
21         Assert.assertEquals(1, binarySearchLast(nums2, 1));
22         
23     }
24     // 查找target在nums[]中的下标,若有重复,返回任意一个即可,若找不到返回 -1
25     public int binarySearch(int[] nums, int target) {
26         if (nums == null || nums.length == 0)
27             return -1;
28         int left = 0, right = nums.length - 1;
29         int mid = 0;
30         while (left <= right) {
31             mid = left + ((right - left) >> 1);
32             if (target == nums[mid])
33                 return mid;
34             else if (target < nums[mid])
35                 right = mid - 1;
36             else 
37                 left = mid + 1;
38         }
39         return -1;
40     }
41     // 查找target在nums[]中第一次出现的下标,若找不到返回-1
42     public int binarySearchFirst(int[] nums, int target) {
43         if (nums == null || nums.length == 0)
44             return -1;
45         int left = 0, right = nums.length - 1;
46         int mid = 0;
47         while (left < right) { // 此处不能有等号,否则可能在right=mid处死循环,考虑case:[1], 1
48             mid = left + ((right - left) >> 1);
49             if (target > nums[mid])
50                 left = mid + 1;
51             else
52                 right = mid;
53         }
54         if (nums[left] == target)
55             return left;
56         return -1;
57     }
58     // 查找target在nums[]中最后一次出现的下标,若找不到返回-1
59     public int binarySearchLast(int[] nums, int target) {
60         if (nums == null || nums.length == 0)
61             return -1;
62         int left = 0, right = nums.length - 1;
63         int mid = 0;
64         while (left + 1 < right) { // 循环只处理元素个数大于两个的情况,两个以下元素时可能在left=mid处死循环(两个元素时left==mid),考虑case:[1,1],1
65             mid = left + ((right - left) >> 1);
66             if (target < nums[mid])
67                 right = mid - 1;
68             else
69                 left = mid;
70         }
71         if (nums[right] == target)
72             return right;
73         else if(nums[left] == target)
74             return left;
75         return -1;
76     }
77 }

 

posted @ 2015-09-05 11:03  abcxyz00  阅读(156)  评论(0编辑  收藏  举报