Loading

【leetcode】540. Single Element in a Sorted Array

  You are given a sorted array consisting of only integers where every element appears exactly twice, except for one element which appears exactly once.Return the single element that appears only once. Your solution must run in O(log n) time and O(1) space.

  

class Solution {
public:
    int singleNonDuplicate(vector<int>& nums) {
        // 解法一 对所有数字进行xoring 处理 从而提取出出现一次的数组 但这样没有用到sorted 的性质
        // 同时时间复杂度为o(n) 空间复杂度为o(1) 可以oc
        int res=0;
        for(auto nn:nums){
            res=res^nn;
        }
        return res;
        
    }
};

  首先这个nums是排序过后的数组,同时要求时间复杂度为o(log n),那必然解题方法需要往二分法去靠,如何检索得到出现一次的元素呢?这个nums还有一个规律就是,其他元素都出现两次,找到切分点,则唯一的元素一定在数字个数为奇数的区间。同时需要确定当前索引为mid的元素 归属于哪一边,从而只在元素个数为奇数的的子数组中找唯一的元素。 

  下面为采用二分法的方式,很明显不如直接位运算来的美观qaq。。。

class Solution {
public:
    int singleNonDuplicate(vector<int>& nums) {
        // 解法一 对所有数字进行xoring 处理 从而提取出出现一次的数组 但这样没有用到sorted 的性质
        // 同时时间复杂度为o(n) 空间复杂度为o(1) 可以oc
        int left=0,right=nums.size()-1;
        int mid,mid_left,mid_right;
        
        while(left<right){
            int mid=(left+right)/2;
            if(nums[mid]!=nums[mid-1] && nums[mid]!=nums[mid+1]) return nums[mid]; //找到了唯一的数字
            else if (nums[mid]==nums[mid-1]){
                mid_left=mid;
                mid_right=mid+1;  
            }
            else{
                mid_left=mid-1;
                mid_right=mid;
            }
            //哪边是奇数 则目标数字就在哪边
            if((mid_left-left+1)&1==1){ //位运算判断是奇数
                right=mid_left;
            }
            else{
                left=mid_right;
            }   
        }
        return nums[left];
        
    }
};

 

 

  

posted @ 2021-11-20 15:49  aalanwyr  阅读(20)  评论(0编辑  收藏  举报