LeetCode 540. 有序数组中的单一元素题解

540. 有序数组中的单一元素题解

题目来源:540. 有序数组中的单一元素

2022.02.14 题解

首先祝大家情人节快乐♥,有对象的祝99 .没有对象的祝转角遇到爱,嘿嘿

本题目是要求在有序数组之中找到只出现一次的数字是什么,但是附带了额外的要求就是时间复杂度要求是 O ( l o g n ) O(logn) O(logn),空间复杂度是 O ( 1 ) O(1) O(1)

首先脑海之中第一个想法就是遍历数组,找到只出现一次的数字,但是这种方式的时间复杂度是 O ( n ) O(n) O(n)大于要求的 O ( l o g n ) O(logn) O(logn),所以直接遍历的方式是行不通的。

那我们就换一种思考方式,时间复杂度是 O ( l o g n ) O(logn) O(logn),这个时间复杂度,用二分的查找方法刚刚好。

接下来就思考思考,用二分法查找,如何判断这个数字是不是重复的,根据题意,除了需要查找的数字,其余的数字均会出现 2 次,因此,要查找的的数字左右必然也是偶数,将数字排列开,会发现,要查询的数字的左侧的所有数字的下标都是一次偶数,一次奇数,而要查询数字的右侧所有的下标都是一次奇数,一次偶数,因此只需要判断两个相同数字的次序就能不断缩小查找范围,

就以左侧为例,如果 mid 是奇数,就判断 nums[mid] 与 nums[mid - 1] 是否相等

如果如果 mid 是偶数,就判断 nums[mid] 与 nums[mid + 1] 是否相等

同时还可以使用异或来进行判断,令 mid 与 1 进行异或操作就可以进行判断。

具体代码以及注释如下:

class Solution {
public:
    int singleNonDuplicate(vector<int>& nums) {
        // 将两个变量作为两个边界
        int l = 0, r = nums.size() - 1;
        // 开始进行查找循环
        while (l < r) {
            // 查找 mid
            int mid = (r - l) / 2 + l;
            // 判断 nums[mid] 是否在要查找的数字的左侧
            if (nums[mid] == nums[mid ^ 1]) {
                // 如果是就改变左边界
                l = mid + 1;
            } else {
                // 如果不是,就改变右边界
                r = mid;
            }
        }
        // 返回答案
        return nums[l];
    }
};
class Solution {
    public int singleNonDuplicate(int[] nums) {
        // 将两个变量作为两个边界
        int l = 0, r = nums.length - 1;
        // 开始进行查找循环
        while (l < r) {
            // 查找 mid
            int mid = (r - l) / 2 + l;
            // 判断 nums[mid] 是否在要查找的数字的左侧
            if (nums[mid] == nums[mid ^ 1]) {
                // 如果是就改变左边界
                l = mid + 1;
            } else {
                // 如果不是,就改变右边界
                r = mid;
            }
        }
        // 返回答案
        return nums[l];
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值