zoukankan      html  css  js  c++  java
  • 面试随缘刷题--day3 二分专题

    leetcode no.33 搜索旋转排序数组

    • 二分问题,注意边界和只有两个的考虑情况。
    • 因为mid是起到向下取整的效果,因此要考虑好a[left]=a[mid]的情况
    • 退出的条件为a[mid]==target或者l>r
    • 对较大的部分的定义 4 5 6 7 1 2 3  此时4 5 6 7是较大的部分,判断mid所处单元用其与left处关系对比判断哦
    • 大范围先判断mid和target的关系,进入分支以后确定mid是在较大还是正常部分,再去执行下一步操作。
    • a[mid]>target时,可能出现的情况:a[mid]在较大的那部分,那么说明前面都比a[mid]小,(此时若a[left]<=target),那么结果一定在[left,mid]中,注意带等号,不然就空掉了left处正好是target,反之,如果a[left]>target,那么结果一定在右半部分。而如果a[mid]在较小的部分,还是比target大,那么只有其左侧的部分才有可能。(7 1 2 3 4 5 6)这种序列
    • a[mid]<target的时候,如果mid在较小的单元,那么可能在左侧的较大部分出现,也可能在右侧正常递增中出现,如果a[right]>=target,一定会出现在右侧。如果mid在较大单元,那么一定是在其右侧出现。
    • 因为在left和mid相同 && mid<target,那么说明这部分较大的也比target小,可能没结果可能是顺序的数组(因为left和mid同只能出现在leftright差值0或者1),这时候都是要往l=mid+1走,所以没必要加等号的(a[left]<=a[mid]等号加不加都可以,已测试,但单独从理清思路来说还是应该加上的)
    • 但如果是mid>target,left和mid同(left和mid之间就代表了较大部分),right那边较小的还是有可能的,所以判断较大区间要加上等号,不然直接认为是left和mid中有较大和较小,那么直接r=mid-1了显然不对
    class Solution {
    public:
        int search(vector<int>& nums, int target) {
            int len=nums.size();
            int l,r,mid;
            l=0;
            r=len-1;
            mid=(l+r)/2;
            while(l<=r)
            {
                //printf("%d %d
    ",l,r);
                if(nums[mid]==target)
                    return mid;
                if(nums[mid]>target)
                {
                    //printf("hah1");
                    if(nums[l]<=nums[mid])//4 5 6 7 1 2 3
                    {
                        //printf("hah2");
                        if(nums[l]<=target)
                            r=mid-1;
                        else
                            l=mid+1;
                    }
                    else
                        r=mid-1;
                }
                else//nums[mid]<target
                {
                    if(nums[l]<nums[mid])
                        l=mid+1;
                    else
                    {
                        if(nums[r]>=target)
                        {
                            l=mid+1;
                        }
                        else
                            r=mid-1;
                    }
                }
                mid=(l+r)/2;
            }
            return -1;
        }
    };
    View Code

     leetcode no.34 在排序数组中查找元素的第一个元素和最后一个元素位置

    • 这个拆分成两个独立的问题,最后是用到了两轮二分
    • 在判断的时候将等号加起来,在等号的时候是right=mid或者left=mid(注意left=mid的时候有可能出现死循环,在left和right差1的时候第二次进入特判退出),不等于的时候就-1和+1正常
    • 如果找第一个元素失败了,那么最后一个元素一定是失败的,直接返回退出
    • 注意vector为空的不存在情况
    • 第一轮结束后再次用left和right记得重置,第二轮的left可以保存为第一次的结果不用重置。
    class Solution {
    public:
        vector<int> searchRange(vector<int>& nums, int target) {
            vector<int>ans;
            int left,mid,right;
            int len=nums.size();
            if(len==0){
                ans.push_back(-1);
                ans.push_back(-1);
                return ans;
            }
            left=0;
            right=len-1;
            while(left<right){
                mid=(left+right)/2;
                if(nums[mid]>=target)
                    right=mid;
                else
                    left=mid+1;
                //printf("%d %d
    ",left,right);
            }
            if(nums[left]==target)
                ans.push_back(left);
            else {
                ans.push_back(-1);
                ans.push_back(-1);
                return ans;
            }
            left=0;
            right=len-1;
            while(left<right){
                mid=(left+right)/2;
                if(nums[mid]<=target){
                    if(left!=mid)
                        left=mid;
                    else{
                        if(nums[right]!=target)
                            right=left;
                        break;
                    }
                }
                else
                    right=mid-1;
                //printf("second:%d %d
    ",left,right);
            }
            ans.push_back(right);
            return ans;
        }
    };
    View Code
    时间才能证明一切,选好了就尽力去做吧!
  • 相关阅读:
    git log
    [转]深入详解javascript之delete操作符
    js性能优化文章集锦
    [转]A记录和CNAME记录的区别
    [转]200 OK (from cache) 与 304 Not Modified------没有这个规则(ETag是否移除)!!!from cache和304,请查看顶部的流程图!
    nodejs渲染到页面的理解
    git之reset
    Mayavi入门
    OpenAcc笔记——update
    Qt笔记——数据库的图形界面
  • 原文地址:https://www.cnblogs.com/tingxilin/p/13430525.html
Copyright © 2011-2022 走看看