关于一个找单身狗的二分分析

文章介绍了如何在有序整数数组中找到唯一出现一次的数,利用二分查找和异或操作,在O(logn)的时间复杂度和O(1)的空间复杂度内解决问题。通过分析数组特性,确定中间值的异或操作可以帮助缩小搜索范围。

分析

具体题目

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

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

你设计的解决方案必须满足 O(log n) 时间复杂度和 O(1) 空间复杂度。

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

本来是感觉平平无奇的一个题目,一开始是没有思路的,并且准备放弃的。看了看官方解题,没忍住看了眼评论区。好家伙,原来这不是找单身狗的吗?还有人情人节抽到了这道题来做。然后提起来了兴趣,看了力扣的分析,感觉又行了,特此记录。

原力扣上地址,大家可以自行查阅。

分析题目

给的数据范围和格式

  • 1、自增(有序)
  • 2、不存在不存在的情况(不存在无解的情况)
  • 3、只会出现一个出现一次的数字,其他均为出现两次

要求

  • 1、你设计的解决方案必须满足 O(log n) 时间复杂度和 O(1) 空间复杂度
  • 2、请你找出并返回只出现一次的那个数。(不是下标,但是和下标其实时一样的)

开始解题

思路
1、如果是 仅存在一个单个的话,数组长度为奇数
2、而且当前位置为某个存在的成对数字,num[idx] = num[idx+1],即左边应为偶数。
3、相对于右边某个(假设和上面的是一对的)  即 num[idx] = num[idx-1]  右边应为偶数。
4、如果上面不符的话 ,应适当缩小范围,来达到二分的效果。

看到的解题的一个小技巧,对这道题还是很适用的,不过具体实现的原理我还没有理解,先简单分析一下。

技巧

具体的就是一个数字 num ^ 1 按位异或1的话,会出现以下的情况

  • 1、如果num为偶数的话 num ^ 1 = num + 1
  • 2、如果num为奇数的话 num ^ 1 = num - 1

这个具体和我们的题目有什么相关呢?我们可以不用担心二分中mid的奇偶性了因为我们只需要分析mid和他应该搭档的一对是否时一致的就行了,甚至不需要考虑数据的递增递减以及是否时有序的。

继续分析技巧
  • 1、中间值为偶数情况下。我们现在假设又这么个数组索引 0 1 2 3 4 5 6 7 8 9 10,暂时不考虑数组中的数据。我们按照二分来分析下,left = 0 ,right = 10 , mid = 5。继续分析,mid ^ 1 = mid - 1 = 4 ,即当前位置的异或下标为5。我们假设mid的左边全都是一对一对的,我们可以直观看到 0,1 2,3 4,5,这些下标位置应是对应的。
  • 2、mid为偶数情况同上
  • 3、 小结论:如果midmid^1 这两个下标的数字相同,我们左边就全部都是一对一对的,即我们要找的索引不在mid左边,此时lef应变为mid+1。单数要注意当不相等的时候,我们不能保证mid位置不为想要的数组下标,即如果不等,right=mid。

具体实现

具体其实就是一个二分,在这就不赘述了。

public int singleNonDuplicate(int[] nums) {
    int left = 0, right = nums.length - 1, mid = 0;
    while (left < right) {
        mid = left + (right - left) / 2;
        if (nums[mid] == nums[mid ^ 1]) {
            left = mid + 1;
        } else {
            right = mid;
        }
    }
    return nums[left];
}

总结

怎么说呢,做到最后好像就是一个普通的二分罢了。开始的时候除了遍历确实没有其他的思路了,也是看了官方解读。第一次关于按位与哪里没有看明白,后来就想着看不明白就不明白了,记住结论就行。推理按位与那里确实时按照最笨的方法推测可行性的。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值