33、搜索旋转排序数组
class Solution {
public int search(int[] nums, int target) {
if(nums==null) return -1;
if(nums[0]==target) return 0;
if(nums[nums.length-1]==target) return nums.length-1;
int l=0;
int r=nums.length-1;
while(l<=r){
int mid=(l+r)/2;
if(nums[mid]==target) return mid;
if(nums[l]==target) return l;
if(nums[r]==target) return r;
if(nums[0] < nums[mid]){
if(nums[0]<=target&& target<nums[mid]){
//0到mid 有序 且target在范围中
r=mid-1;
}else{
//有序 但 target不在范围中
l=mid+1;
}
}else{
//0 到mid 无序 那么 另外一半 mid到r肯定有序
if(nums[mid]<target&& target<=nums[r]){
l=mid+1;
}else{
r=mid-1;
}
}
}
return -1;
}
}
分组之后 一定以某以结点 分为有序和无序
那么通过二分法查找之后,肯定是一半有序 一半无序,无序那一半还可以通过继续二分法进行查找
class Solution {
public int[] searchRange(int[] nums, int target) {
int[] out=new int[2];
out[0]=-1;
out[1]=-1;
if(nums==null) return out;
/*if(nums.length==1){
if(nums[0]==target){
out[0]=0;
out[1]=0;
return out;
}else{
return out;
}
}*/
/*if(nums.length==1&&nums[0]==target){
out[0]=0;
out[1]=0;
return out;
}*/
//升序
int left=0;
int right=nums.length-1;
int mid=0;
int temL=0;
int temR=0;
while(left<=right){
mid=(left+right)/2;
if(nums[mid]==target){
//向左寻找第一个 向右寻找最后一个
temL=mid;
while(0<=temL&&nums[temL]==target){
--temL;
}
out[0]=temL+1;
temR=mid;
while(temR<nums.length&&nums[temR]==target){
++temR;
}
out[1]=temR-1;
}
if(nums[mid]<target){
left=mid+1;
}else{
right=mid-1;
}
}
return out;
}
}
二分法查找原理
35搜索插入位置
这题解答一直没做全
个人的:
class Solution {
public int searchInsert(int[] nums, int target) {
if(nums==null) return 0;
if(target<=nums[0]) return 0;
if(target>nums[nums.length-1]) return nums.length;
if(nums.length==1){
if(target<=nums[0]) return 0;
if(target>nums[nums.length-1]) return nums.length;
}
int mid=0;
int left=0;
int right=nums.length-1;
while(left<right){
mid=(left+right)/2;
if(nums[mid]==target){
return mid;
}
if(nums[mid]<target) {//在mid 和right之间
left=mid+1;
if(nums[left]>target){//mid<target<left
return left;
}
}else if(nums[mid]>target) {//有可能 在mid和left或者right之间。
right=mid-1;
if(nums[right]<target){//在right<target<mid之间
return mid;
}
}
}
return 0;
}
}
官方:
class Solution {
public int searchInsert(int[] nums, int target) {
int left = 0, right = nums.length - 1;
while(left <= right) {
int mid = (left + right) / 2;
if(nums[mid] == target) {
return mid;
} else if(nums[mid] < target) {
left = mid + 1;
} else {
right = mid - 1;
}
}
return left;
}
}
81,搜索旋转排序数组II
class Solution {
public boolean search(int[] nums, int target) {
//原本升序
//翻转之后以target为界升序
//可能会有重复项
if(nums==null) return false;
if(nums.length==1 && nums[0]==target) return true;
int left=0;
int right=nums.length-1;
int mid=0;
while(left<=right){
// mid=(nums[left] + nums[right])/2;
//去重处理
while(left<right && nums[left]==nums[left+1]) left++;
while(left<right && nums[right]==nums[right-1]) right--;
mid=(left+right)/2;
if(nums[mid]==target) return true;
if(nums[left]==target) return true;
if(nums[right]==target) return true;
//判断左半部分是否有序
if(nums[left]<nums[mid]){
//左半部分有序
if(nums[left] <target && target <nums[mid]){
right=mid-1;
}else{
left=mid+1;
}//目标值在左半部分(有序)
}else{
//右半部分有序
if(nums[mid] < target && target <nums[right]){
left=mid+1;
}else{
right=mid-1;
}
}
/*else{
//右半部分有序
if(nums[mid] < target && target <nums[right]) left=mid+1;
if(nums[mid] < target) right=mid-1;
}*/
}
return false;
}
}
//重复的话 一部分有序的 可能都是一样的值 说明 相等也可能