数据结构学习 jz53_1 在排序数组中查找数字1 0 ~ n - 1 中缺失的数字

关键词:查找算法 二分法 映射 位运算

题目一:统计目标成绩的出现次数

方法一:我自己写的。[ 用时: 13 m 3 s ] 二分法+线性扫描

方法二:看了题解

方法一:

二分法+线性查找

思路:

先二分查找找到和target一样的数的位置,假设为i。

然后以i位置出发点,左右两边查找数据是否等于target。

复杂度计算:

时间复杂度O(logn+n)

空间复杂度O(1)

代码:

class Solution {
public:
    int countTarget(vector<int>& scores, int target) {
        int l=0;
        int r=scores.size()-1;
        while(l<=r)//二分查找
        {
            int mid=(l+r)/2;
            if(scores[mid]==target)
                break;
            else if(scores[mid]>target)
            {
                r=mid-1;
            }
            else//scores[mid]<target
            {
                l=mid+1;
            }
        }
        if(l>r)//找不到
        {
            return 0;
        }
        int tar_l=(l+r)/2;//左右线性查找
        while(tar_l>=0&&scores[tar_l]==target)
        {
            tar_l--;
        }
        int tar_r=(l+r)/2;
        while(tar_r<scores.size()&&scores[tar_r]==target)
        {
            tar_r++;
        }
        return tar_r-tar_l-1;
    }
};

方法二:

双二分法。

思路:

先用二分法找符合target这一堆数字的最左边。

然后再 二分法找符合target这一堆数字的最右边。

右-左+1就是结果。

复杂度计算:

时间复杂度O(logn)

空间复杂度O(1)

代码:

class Solution {
public:
    int countTarget(vector<int>& scores, int target) {
        if(scores.empty()) return 0;
        int tar_l=0;
        int tar_r=scores.size()-1;
        int l=0;
        int r=scores.size()-1;
        while(l<=r)//左
        {
            int mid=(l+r)/2;
            if(scores[mid]==target)
            {
                tar_l=mid;
                r=mid-1;
            }
            else if(scores[mid]>target)
            {
                r=mid-1;
            }
            else//scores[mid]<target
            {
                l=mid+1;
            }
        }
        if(scores[tar_l]!=target)
        {
            return 0;
        }
        l=0;
        r=scores.size()-1;
        while(l<=r)//右
        {
            int mid=(l+r)/2;
            if(scores[mid]==target)
            {
                tar_r=mid;
                l=mid+1;
            }
            else if(scores[mid]>target)
            {
                r=mid-1;
            }
            else//scores[mid]<target
            {
                l=mid+1;
            }
        }
        return tar_r-tar_l+1;
    }
};

题目二:点名

方法一:

[ 用时: 6 m 6 s ] 二分法 映射

思路:

映射法做。

映射:只要数字和下标不同,就说明这个数或者这个数之前的数缺了。

利用二分查找来找到我们想要的那个数。

复杂度计算:

时间复杂度O(logn)

空间复杂度O(1)

代码:

class Solution {
public:
    int takeAttendance(vector<int>& records) {
        int l=0,r=records.size()-1;
        while(l<=r)
        {
            int mid=(l+r)/2;
            if(records[mid]==mid)
            {
                l=mid+1;
            }
            else
            {
                r=mid-1;
            }
        }
        return l;
    }
};

方法二:

位运算 异或

只是炫技。时间上还不如二分。

思路:

如果两个数相同,异或为0,剩下的那个就是被单着的。

0,1,2,3,5和0,1,2,3,4,5异或,就会得到4了。

复杂度计算:

时间复杂度O(n)

空间复杂度O(1)

代码:

class Solution {
public:
    int takeAttendance(vector<int>& records) {
        if(records[0]!=0) return 0;
        int res=0;
        int i=0;
        for(const int&x:records)//0,1,2,3,5和0,1,2,3,4异或
        {
            res=res^i^x;
            i++;
        }
        return res^i;//别忘了最后一位5
    }
};

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值