二分查找搜索要插入位置

leetcode题目: https://leetcode-cn.com/problems/search-insert-position/submissions/
 
int searchInsert(int* nums, int numsSize, int target){
       int n = numsSize;
        int left = 0, right = n - 1,ans=n;
        while (left <= right) {
            int mid = (right + left) >> 1;
            if (nums[mid]>=target) {
            right = mid - 1;
            ans=mid;
            
            } else if (nums[mid]<target){
                   left = mid + 1;
                
            }
           
        }
        return ans;
        }

 

以下根据官方题解思考过程:
-----》一开始在二分查找(只是查找已经存在值的位置)的基础上,
int searchInsert(int* nums, int numsSize, int target){
       int n = numsSize;
        int left = 0, right = n - 1;//ans = n;
        while (left < right) {
            int mid = (right + left) >> 1;
            if (target < nums[mid]) {
            right = mid - 1;
            
            } else if (target > nums[mid]){
                   left = mid + 1; 
                
            }
            else if (target == nums[mid]){
                   return mid;
                
            }
        }
}
----》但是如果不存在就无法查找位置,如 于是发现在不存在时left和right重合的位置就是要找的插入位置(是比插入值大的一边)
即mid=left=right>target
int searchInsert(int* nums, int numsSize, int target){
       int n = numsSize;
        int left = 0, right = n - 1;
        while (left < right) {
            int mid = (right + left) >> 1;
            if (target < nums[mid]) {
            right = mid - 1;
            
            } else if (target > nums[mid]){
                   left = mid + 1; 
                
            }
            else if (target == nums[mid]){
                   return mid;
                
            }
        }
}
       int mid = (right + left) >> 1;
        return mid;
        }
 
 
-----》但是当要插入值比数组中所有值都大时,如果还是靠right初始为n-1,和while破除条件left==right这种情况就不能考虑到,因为mid==right==left最大为n-1。 所以将while的破除条件设为left>right即while(left<=right)
思考:不考虑插入值比数组中所有值都大的情况的,其他情况:target能在数组中找到相同的数,即插入位置为该相同数的位置和 target在数组中两个数之间,插入位置为较大数的位置;
1.target能在数组中找到相同的数(这里包括了在第一个位置上插入比所有数都小的情况,可以自行举例如1,3,4,6 插0
需要经过 :
(mid上的数<target )——(mid上的数>target)——(mid上的数==target)或(mid上的数>target)——(mid上的数==target)或(mid上的数<target)——(mid上的数==target)或直接(mid上的数==target)....不管怎么说最后一定是(mid上的数==target)
 
2.而插入位置为该相同数的位置和 target在数组中两个数之间时,需要经过,这里举例:
1,3,4,6 插5 (mid上的数<target )——(mid==left==right,mid上的数>target)或 如1,3,4,6插2(mid上的数>target,其实得到答案)——(mid==left==right,mid上的数<target,在下一步就要破除了)
以上两种找到的位置1.mid上的数==target,mid==right==left,2.要么mid上的数>target,mid==right==left;要么只是mid上的数>target(如果是先(mid上的数>target)又再 (mid上的数<target )找到(mid==right==left)就不符合了,因为既破除了,又找的不是较大数的位置)  
综上,我们要找的位置都是集中在mid上的数>=target的位置,为了防止破除了也没找到,我们需要不断记录mid上的数>target时mid的值,连带着mid上的数==target。于是就有
if (nums[mid]>=target) {
            right = mid - 1;
            ans=mid;
最后return ans;
-----》这个记录ans的初始值如果为n,即int ans=n;就满足了当要插入值比数组中所有值都大时,插入在这些数(下标0~n-1)的最后面,同时target始终>mid上的数,返回ans时保证了为n。
 
还是要多举列子验证过程呀~

posted on 2020-12-06 15:36  wang_dahua  阅读(171)  评论(0)    收藏  举报

导航