美文网首页
求解有序数组中只出现一次的数字(Leetcode540)

求解有序数组中只出现一次的数字(Leetcode540)

作者: zhouwaiqiang | 来源:发表于2018-12-07 13:56 被阅读0次

    题目

    • 给定一个只由数字组成的有序数组,除了其中一个元素只出现一次别的都会出现两次,找出只出现一次的那个元素。
    • 比如输入[1,1,2,3,3,4,4,8,8],输出2
    • 输入[3,3,7,7,10,11,11],输出10

    解题思路

    • 这道题常规做法可以参考之前的single number用异或操作即可获得结果,但是时间复杂度为O(n)与题目要求O(logn)不符合
    • 根据log(n)的要求可以猜测使用二分查找,此时我们需要辨别一下规律,题意中给出的数组是有序的如果按照常规的两两出现比如[0,0,1,1],此时的下标对应的应该是 0,1,2,3。也即是重复的数字下标是偶奇偶奇的组合(从0开始),但是如果中间多了一个单次的数字比如3,此时数组变为[0,0,3,1,1]那么此时下标0,1,2,3,4后面两个数字1,1表示的数字就变成了3,4(下标奇偶特性)。
    • 由以上所述我们可以二分查找首先确定mid的奇偶性,然后再判断相等的两个数连续的奇偶性,举例来说当mid%2==0时,此时表示mid是偶数下标,那么如果按照原始两两排列应该是偶奇特性,此时就用nums[mid]和nums[mid+1]比较,如果相等那么表示mid之前的序列都是两两出现的,并没有破坏平衡性,此时low更新为mid,相反的就是mid和mid-1相等,或者mid是单独的数字,直接将high更新为mid。同理可以更改mid为奇数下标时的情况。
    • 采用二分查找整体时间复杂度为O(logn)

    源代码实现

    class Solution {
        public int singleNonDuplicate(int[] nums) {
            int low = 0, high = nums.length-1;
            while (low < high) {
                int mid = low + (high - low)/2;
                //前后都不等那么nums[mid]就是要查找的数据
                if (nums[mid] != nums[mid-1] && nums[mid] != nums[mid+1]) return nums[mid];
                //mid表示偶数位置(从0开始)
                if (mid % 2 == 0) {
                    if (nums[mid] == nums[mid+1]) low = mid;
                    else high = mid;
                }
                else {
                    if (nums[mid] == nums[mid-1]) low = mid+1;
                    else high = mid-1;
                }
            }
            return nums[low];
        }
    }
    

    相关文章

      网友评论

          本文标题:求解有序数组中只出现一次的数字(Leetcode540)

          本文链接:https://www.haomeiwen.com/subject/szjthqtx.html