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
    时间才能证明一切,选好了就尽力去做吧!
  • 相关阅读:
    evernote100个做笔记的好方法
    平衡二叉树的调整模版
    晨间日记的奇迹
    hdu 2952 Counting Sheep
    hdu 1535 Invitation Cards
    poj 3259 Wormholes(spfa)
    poj 2263 Heavy Cargo(floyd)
    poj 3268 Silver Cow Party(SPFA)
    hdu 1690 Bus System
    hdu 3631 Shortest Path(Floyd)
  • 原文地址:https://www.cnblogs.com/tingxilin/p/13430525.html
Copyright © 2011-2022 走看看