问题描述:反转序列,但是有重复的元素,例如序列13111。
算法思路:如果元素有重复,那么left-mid,就不一定是有序的了,所以不能利用二分搜索,二分搜索必须是局部有序。针对有序序列的反转,如果有重复数据的话,那么必然是nums[left]=nums[mid]=nums[right],增加对这种情况的讨论即可。
1 public boolean search(int[] nums, int target) 2 { 3 return binarySearch(nums, 0, nums.length - 1, target); 4 } 5 //递归方法 6 public boolean binarySearch(int[] nums, int left, int right, int target) 7 { 8 //不要忘了这个边界条件。 9 if(left > right) 10 { 11 return false; 12 } 13 int mid = (left + right)/2; 14 if(target == nums[mid]) 15 { 16 return true; 17 } 18 19 //假设序列为13111,那么nums[mid]=nums[right]=nums[left],left和mid之间就不是有序序列了。 20 //并且这种特殊情况,只可能是nums[mid]=nums[left]=nums[right],所以,移动left和right. 21 //二分查找的关键就是要局部序列有序。 22 if(nums[left] == nums[mid] && nums[mid] == nums[right]) 23 { 24 return binarySearch(nums, left + 1, right - 1, target); 25 } 26 27 else if(nums[left] <= nums[mid])//做连续,要包含"="的情况,否则出错。 28 { 29 if(target >= nums[left] && target < nums[mid])//target上下限都要有 30 { 31 return binarySearch(nums, left, mid - 1, target);//记得return 32 } 33 else 34 { 35 return binarySearch(nums, mid + 1, right, target); 36 } 37 } 38 else 39 { 40 if(target > nums[mid] && target <= nums[right]) 41 { 42 return binarySearch(nums, mid + 1, right, target); 43 } 44 else 45 { 46 return binarySearch(nums, left, mid - 1, target); 47 } 48 } 49 } 50 51 52 //迭代方法 53 public boolean binarySearch2(int[] nums, int left, int right, int target) 54 { 55 56 while(left <= right) 57 { 58 int mid = (left + right)/2; 59 if(target == nums[mid]) 60 { 61 return true; 62 } 63 if(nums[left] == nums[mid] && nums[mid] == nums[right]) 64 { 65 left ++; 66 right --; 67 } 68 else if(nums[left] <= nums[mid]) //左连续,所以要包含=的情况。否则出错。 69 { 70 if(target >= nums[left] && target < nums[mid]) 71 { 72 right = mid - 1; 73 } 74 else 75 { 76 left = mid + 1; 77 } 78 } 79 else 80 { 81 if(target > nums[mid] && target <= nums[right]) 82 { 83 left = mid + 1; 84 } 85 else 86 { 87 right = mid - 1; 88 } 89 } 90 } 91 return false; 92 }