LeetCode——540.有序数组种的单一元素

该博客介绍了如何在有序数组中找到一个只出现一次的元素,要求时间复杂度为O(logn),空间复杂度为O(1)。通过使用二分查找法,根据数组中重复元素的特点,判断向左或向右移动指针,最终找到目标元素。伪代码和Java代码示例给出了具体的实现过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

通过万岁!!!

  • 题目:给你一个数组,数组是有序的,然后每个元素都会出现两次,但是唯独有一个不是。希望能能够找出来。要求时间复杂度O(logn),空间复杂度O(1)。
  • 思路:要是没有时间复杂度限制的话,直接就是遍历一遍。然后用一个数加上nums中的奇数,然后减去nums的偶数,得到的结果进行绝对值就行了。时间复杂度是O(n),空间复杂度是O(1)。然后看到这个时间复杂度,而且是一维数组,所以我们想到了二分查找。我们可以发现规律,数组长度一定是奇数,我们二分查找的话,主要是判断向左还是向右。我们可以发现存在几种情况。
    1. 中间这个元素跟中间(mid)的左边(mid-1)相同。例如:[1,1,2,3,3,4,4,8,8],[3,3,7,7,10,11,11]。这时候我们发现,我们要的目标有在左边的,也有在右边的,但是可以发现,这两个是有不同的,就是right的下标-mid是奇数和偶数。因此本题中我需要两个条件去判断往左边还是右边。
    2. 中间这个元素跟中间(mid)的右边(mid+1)相同。例如:[1,1,2,2,3]。这时候也是会有上面的情况。
  • 技巧:
    • 使用二分法,注意二分法主要的是需要判断分完以后去左边还是右边

伪代码

首先判断如果数组长度是1的话直接返回nums[0]即可。
然后就是定义l,r,mid三个变量。其中l=0,r=数组的长度-1,mid=(r+l)/2。
然后就是while循环,条件是r!=l
    如果mid指向的数与左边和右边都不相等,则直接返回nums[mid],这时候就是找到了
    如果mid与mid左边相等,则是上面的第一种情况
        然后判断r-mid是奇数还是偶数,如果是奇数
            左指针移动
        如果是偶数
            右指针移动,注意这里移动两个,因为左边第一个与mid是相同的。
    否则,就是mid与右边相同,是上面的情况二
        然后判断r-mid是奇数还是偶数,如果是奇数
            右指针移动
        如果是偶数
            左指针移动
    上面移动了指针,则这时候就需要更新mid了
最后返回nums[r],或者返回nums[l]。

java代码

class Solution {
    public int singleNonDuplicate(int[] nums) {
        if (nums.length == 1) return nums[0];
        // 数组的长度一定是奇数
        int l = 0, r = nums.length - 1;
        int mid = (l + r) / 2;// 中间元素的下标
        while (l != r) {
            if (nums[mid] != nums[mid - 1] && nums[mid] != nums[mid + 1]) return nums[mid];
            if (nums[mid] == nums[mid - 1]) {
                if ((r - mid) % 2 == 1)// 奇数,在右边
                    l = mid + 1;
                else
                    r = mid - 2;
            } else {
                if ((r - mid) % 2 == 1)
                    r = mid - 1;
                else
                    l = mid + 2;
            }
            mid = (l + r) / 2;
        }
        return nums[r];
    }
}
  • 题目不难,主要是有时间复杂度和空间复杂度的限制,但是也正好给我们了一个提示。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值