二分查找 个人做题心得

以剑指offerⅡ 068 查找插入位置为例:

给定一个排序的整数数组 nums 和一个整数目标值 target ,请在数组中找到 target ,并返回其下标。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。

请必须使用时间复杂度为 O(log n) 的算法。

示例 1:

输入: nums = [1,3,5,6], target = 5
输出: 2
示例 2:

输入: nums = [1,3,5,6], target = 2
输出: 1
示例 3:

输入: nums = [1,3,5,6], target = 7
输出: 4
示例 4:

输入: nums = [1,3,5,6], target = 0
输出: 0
示例 5:

输入: nums = [1], target = 0
输出: 0

提示:

1 <= nums.length <= 104
-104 <= nums[i] <= 104
nums 为无重复元素的升序排列数组
-104 <= target <= 104

标准的二分查找位置,因为题目给出的时间复杂度为O(log n)
代码为

class Solution {
public:
    int searchInsert(vector<int>& nums, int target) {
        // cout << target << endl;
        // int left = 0;
        // int right = nums.size()-1;
        // int i = 1;
        // while(left < right)
        // {
        //     int middle = (left + right)/2;
        //     cout << "i=" << i++ << endl;
        //     cout << "l=" << left << endl;
        //     cout << "r=" << right << endl;
        //     cout << "middle:" << middle << endl;
        //     // if(middle == 0)
        //     // {
        //     //     if(nums.size() == 1)
        //     //     {
        //     //         if(target <= nums[0])
        //     //             return 0;
        //     //         else
        //     //             return 1;
        //     //     }
        //     //     else if(nums.size() == 2)
        //     //     {
        //     //         if()
        //     //     }
        //     // }
        //     if(nums[middle] == target)
        //     {
        //         cout << 1 << endl;
                
        //         while(nums[middle-1] == nums[middle] && middle >= 1)
        //         {
        //             middle -= 1;
        //         }
        //         cout << "JIEGUO:" << middle << endl; 
        //         return middle;
        //     }
        //     else if(nums[middle] < target)
        //     {
        //         left = middle + 1;
        //         cout << 2 << endl;
        //     }
        //     else
        //     {
        //         right = middle;
        //         cout << 3 << endl;
        //     }
        // }
        // cout << "结果:" << left << endl;
        // return left;
        int l = 0;
        int r = nums.size() - 1;
        while(l < r)
        {
            int mid = (l + r)/2;
            if(nums[mid] >= target)
                r = mid;
            else
                l = mid+1;//左闭右开
        }
        return l == nums.size() - 1 && nums[l] < target ? l+1 : l;
    }
};

代码如下,前面注释掉的代码为本人第一次尝试与调试结果。
当时本人想如果找到nums[middle] = target
就向左遍历,直到没有相等的,因为要把新数据放在最左边。
但难以处理middle=0的情况。

所以采用下面的方法,不管target等于多少,一定要保证他在[left,right)这样的一个新的左闭右开区间中,最终单独判断一下最右边的情况就行。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值