leetcode-540.有序数组中的单一元素

二分查找


题目详情

**给你一个仅由整数组成的有序数组,其中每个元素都会出现两次,唯有一个数只会出现一次。
请你找出并返回只出现一次的那个数。
你设计的解决方案必须满足 O(log n) 时间复杂度和 O(1)空间复杂度。


示例1:

输入: nums = [1,1,2,3,3,4,4,8,8]
输出: 2

示例2:

输入: nums =  [3,3,7,7,10,11,11]
输出: 10

我的first代码:

惯性思维想到的是依次比较每一个数和他后面的一个数,一旦不同就是前面这个数是单一的,但是这种方法有很多特殊情况都通过不了,且复杂度不满足要求

class Solution 
{
public:
    int singleNonDuplicate(vector<int>& nums) 
    {
        int ji=0,ou=1,len=nums.size()-1;
        if(len==0)
        return nums[0];
        while(ji<len)
        {
            if(nums[ji]!=nums[ou])
            return nums[ji];

         ji+=2;
         ou+=2;
           
            
        }

        return 0;
    }
};

第11个用例[1,1,2]就无法通过,所以这种方法是不可行的


同样的我们可以利用二分查找,(寻找到一定规律):
例如示例一[1,1,2,3,3,4,4,8,8],我们把2补全后,[1,1,2,2,3,3,4,4,8,8]
可以看出偶数下标和奇数下标的值都是相等的,若有一个单一元素
则可通过二分查找,mid若是偶数,则比较midmid+1,若是奇数,则比较midmid-1,详细代码如下:

class Solution 
{
public:
    int singleNonDuplicate(vector<int>& nums) 
    {
       int l=0,r=nums.size()-1,mid;
       while(l<r)
       {
           mid=(l+r)/2;
           if(mid%2==0)                     //mid若是偶数
           {
               if(nums[mid]==nums[mid+1])   //mid和mid+1相等,则前面肯定是成双成对的
               l=mid+1;                     //所以单一元素位于[mid+1,r]
               else                         //若不相等,则位于[l,mid],例如示例一
               r=mid;

           }
           else                             //mid是奇数
           {
               if(nums[mid]==nums[mid-1])   //mid和mid-1相等,则前面肯定是成双成对的
               l=mid+1;                     //单一元素位于[mid+1,r]
               else                         //否则位于[l,mid],例如示例二
               r=mid;
           }
       }
        return nums[r];                     //最后肯定是从while跳出的,所以可以返回nums[l]
                                            //或者nums[r]
    }
};

涉及知识点:

1.二分查找

二分查找也常被称为二分法或者折半查找,每次查找时通过将待查找区间分成两部分并只取一部分继续查找,将查找的复杂度大大减少。对于一个长度为 O(n) 的数组,二分查找的时间复杂度为 O(log n)。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ggaoda

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值