有序数组中的单一元素

有序数组中的单一元素

题目链接

leetcode

题目描述

给你一个仅由整数组成的有序数组,其中每个元素都会出现两次,唯有一个数只会出现一次。

请你找出并返回只出现一次的那个数。

你设计的解决方案必须满足 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

提示:

1 <= nums.length <= 105
0 <= nums[i] <= 105

题目解法

第一种:全数组的二分查找,利用按位异或的性质,可以得到中间下标和相邻数的关系,当中间的数是偶数时,mid + 1 = min ^ 1,当中间的数是奇数时,mid - 1 = mid ^ 1

    public static int singleNonDuplicate(int[] nums) {
        int left = 0;
        int right = nums.length - 1;
        while (left < right) {
            int mid = (left + right) / 2;
            // 二进制中  ^ 两个数相同为0,不同为1
            if(nums[mid] == nums[mid ^ 1]) {
                left = mid + 1;
            }else {
                right = mid;
            }
        }
        return nums[left];
    }

第二种:偶数下标二分查找,数组的长度是奇数,数组是有序的,单一元素的下标肯定是偶数,可以在偶数下标范围内查找,二分查找的目标是找到满足nums[x] 不等于nums[x + 1] 的最小的偶数下标 x,则下标 x 处的元素是只出现一次的元素.二分查找时要考虑中间数(mid)和按位与运算,当mid是偶数时,mid & 1 = 0,当mid是奇数时,mid & 1 = 1;

    public static int singleNonDuplicate1(int[] nums) {
        int left = 0;
        int right = nums.length - 1;
        while (left < right) {
            int mid = (left + right) / 2;
            // 二进制中  & 两个数为1才为1,否则为0
            mid -= mid & 1;
            if(nums[mid] == nums[mid + 1]) {
                //当前数和下一个数相等,步数要加2,跳过相等的数
                left = mid + 2;
            }else {
                right = mid;
            }
        }
        return nums[left];
    }
posted @   China熊孩子  阅读(87)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· winform 绘制太阳,地球,月球 运作规律
· 上周热点回顾(3.3-3.9)

阅读目录(Content)

此页目录为空

点击右上角即可分享
微信分享提示