LeeCode例题——二分查找

1.二分查找:(面对一个升序排列的数组)

class Soulution {
public:
  int search(vector<int>& nums, int target) {//函数名(数组,变量)
  int left = 0, right = nums.size() - 1;//声明变量left定义为数组的左边界,变量right定义为数组的右边界。
  while(left <= right){
    int mid = left + (right - left)/2;//取数组的中间位置,前面加上left是为了防止溢出
    int num = muns[mid];//取数组的中间位置的元素
    if (num == target){//当寻找的变量等于数组中间位置的元素时,返回为中间未知的下标
        return mid;
    }else if (target < num){//当寻找的变量小于mid时,将右边界定义为mid-1,下次while循环计算mid的位置时,mid代表左边界的中间,从数组的左边开始寻找
        right = mid -1
    }else {//当寻找的变量大于mid时,将左边界定义为mid+1,下次while循环计算mid的位置时,mid代表右边界的中间,从数组的右边开始寻找
        left = mid +1
    }
  }
  return -1;//查找无果则返回-1
};

为什么计算变量mid时要在前面加上left防止溢出:
假设数组从1到10,查找数字为7,第一次计算变量mid的值为5,左边界left为6,第二次计算mid的值为8,但如果不加上left,mid的值会变为2,原因是这里算法的查找方法是(右边界-左边界)/2,每一次计算mid后,左右边界都会比原来更靠近,换句话说,右边界-左边界的差值将随着每一次循环的进行而缩小。
显然,当从1到10查找数字7的情况下,如果我们不做什么改变,mid的值将会越来越小,根本查找不到7,那么又为什么要加left呢?
假设从1到10查找的数字为3,那么在查找的过程中,左边界是不移动的,右边界缩小,mid将会变得越来越小,而想要查找到数字3,正好就需要mid的值随循环而变小。同时,在查找数字为7的情况下,左边界缩小,右边界不动,mid的值加上left将变得越来越大。
当然聪明的人可能已经发现我说错了,在这个算法的每一次循环过程中并非只有左边界或者右边界移动的(实际去算就能知道),但从结果上来看,无非就是左边界向右边界移动或者右边界向左边界移动,移动到某一个位置,输出这个位置而已,上面的内容各位看官抽象的理解一下就行。

本算法耗时32ms,LeeCode上有更快的算法,最离谱的是有4ms的算法。
28ms:(可能是我才疏学浅,没看出这个和32ms的有什么区别)

class Solution {
public:
    int search(vector<int>& nums, int target) {
        int left = 0, right = nums.size() - 1;
        while(left <= right){
            int mid = (right - left) / 2 + left;
            int num = nums[mid];
            if (num == target) {
                return mid;
            } else if (num > target) {
                right = mid - 1;
            } else {
                left = mid + 1;
            }
        }
        return -1;
    }
};

24ms:
下面是我对这个算法快于32ms算法的理解:
1.这个算法在第一个if和第二个if中先处理了基准情况,按照书上的说法,应该是这样理解的吧。
2.在第三个if中加入break提前终止。

class Solution {
public:
    int search(vector<int>& nums, int target) {
        int m, start = 0, end = nums.size()-1;//和第一个算法一样,先定义左边界和右边界
        int flag = -1;
        int tmp = 0;
        while(start <= end){//当左边界小于右边界时
            m = (start + end ) / 2;//m为数组的中间位置
            tmp = nums[m];//tmp为数组中m位置上的数字
            if(start == end){//当左边界等于右边界时,即数组中只有一个数字
                if(target==nums[m]){//如果查找到变量target则返回m
                    return m;
                }else{
                    return -1;//没有则返回-1
                }
            }
            if (tmp == target){//当tmp==target时返回flag,且结束循环
                flag = m;
                break;
            }else if (tmp > target){//接下来和32ms算法同理
                end = m;
            }
            else {
                start = m+1;
            }
        }
        return flag;
    }
};

20ms:
1.相比于32ms的算法,这个算法只声明了两个变量,第四个变量num用nums[mid]代替,其他的原谅我才疏学浅,看不出来。

class Solution {
public:
    int search(vector<int>& nums, int target) {
            int left=0,right=nums.size()-1;
            while(left<=right)
            {
                int mid=(right-left)/2+left;
                    if(nums[mid]==target)
                    {
                        return mid;
                    }
                    else if(nums[mid]>target)
                    {
                        right=mid-1;
                    }
                    else
                    {
                        left=mid+1;
                    }
                }

            return -1;
    }
};

16ms:(好像和那个24ms的算法一样啊)

class Solution {
public:
    int search(vector<int>& nums, int target) {
        int m, start = 0, end = nums.size()-1;
        int flag = -1;
        int tmp = 0;
        while(start <= end){
            m = (start + end ) / 2;
            tmp = nums[m];
            if(start == end){
                if(target==nums[m]){
                    return m;
                }else{
                    return -1;
                }
            }
            if (tmp == target){
                flag = m;
                break;
            }else if (tmp > target){
                end = m - 1;
            }
            else {
                start = m + 1;
            }
        }
        return flag;
    }
};

12ms:

class Solution {
public:
    int search(vector<int>& nums, int target) {
        int n = nums.size();//初始化变量n为数组的长度
        if(n == 0 ) return -1;//这里优先处理了基准情况,当数组长度为0时直接返回-1
        int l = 0, r = n-1, mid ;//初始化变量为l,r为数组的左边界和右边界,声明变量mid为整型
        while(l <= r){//和32ms算法一样
            mid = (r+l)/2;
            if(nums[mid] == target) return mid;
            else if(nums[mid] < target) l = mid+1;
            else if(nums[mid] > target) r = mid-1;
        }
        return -1;
    }
};

8ms:
降维打击了。

int init = [] {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    ofstream out("user.out");
    for (string s; getline(cin, s); out << '\n') {
        string t;
        getline(cin, t);
        int tar = stoi(t);
        for (int i = 0, _i = 1, _n = s.length(); _i < _n; ++i, ++_i) {
            bool _neg = false;
            if (s[_i] == '-') ++_i, _neg = true;
            int v = s[_i++] & 15;
            while ((s[_i] & 15) < 10) v = v * 10 + (s[_i++] & 15);
            if (_neg) v = -v;

            if (v == tar) {
                out << i;
                goto next;
            }
            if (v > tar) break;
        }
        out << -1;
        next:;
    }
    out.flush();
    exit(0);
    return 0;
}();

class Solution {
public:
    int search(vector<int>, int) { return 0; }
};

4ms:

int init = [] {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    ofstream out("user.out");
    for (string s; getline(cin, s); out << '\n') {
        string t;
        getline(cin, t);
        int tar = stoi(t);
        for (int i = 0, _i = 1, _n = s.length(); _i < _n; ++i, ++_i) {
            bool _neg = false;
            if (s[_i] == '-') ++_i, _neg = true;
            int v = s[_i++] & 15;
            while ((s[_i] & 15) < 10) v = v * 10 + (s[_i++] & 15);
            if (_neg) v = -v;

            if (v == tar) {
                out << i;
                goto next;
            }
            if (v > tar) break;
        }
        out << -1;
        next:;
    }
    out.flush();
    exit(0);
    return 0;
}();

class Solution {
public:
    int search(vector<int>, int) { return 0; }
};

真是应了书上那句话,程序长的运行效率不一定低。

posted @ 2023-03-12 18:16  apeiriaDolce  阅读(17)  评论(0编辑  收藏  举报