Leetcode专题[数组]-540-有序数组中的单一元素

力扣链接:https://leetcode-cn.com/probl...
解题思路:

  1. 首先,算法应该培养思维,看到有序数组以及题干要求的logn的解法,那么首先就应该想到的是二分查找,这算是解法的第一步
  2. 找到算法的思路后,开始找规律,或者可以叫找公式。如数组:[1,1,2,3,3,4,4,8,8],如果数组中没有单个数字,那么该数组就应该是[1,1,2,2,3,3,4,4,8,8];可以找出的一个规律是:下标从0开始,到len(nums) - 1 结束,下标为偶数的和下标为相邻奇数的数字相等。即:nums[0] == nums[1]; nums[2] == nums[3] ....
  3. 找到第二点所示的规律后,因为我们需要使用奇偶数下标来判断,那么mid := (high - low) >> 1 + low,mid可能是奇数,也可能是偶数,但是不论mid是奇数还是偶数,遵循的规律都是nums[偶数] == nums[相邻的奇数],基于这一点,当mid是奇数时,那么判断nums[mid - 1] == nums[mid];如果相等,那么说明只出现一个的数字在右半部分,那么low = mid + 1,如果不相等,则证明只出现一个的数字在左半部分,那么high = mid,当mid是偶数时,比较的是nums[mid] 是否等于 nums[mid + 1];如果相等,说明单个数字在右半部分,如果不相等,说明在左半部分
  4. 通过上面的判断,可以知道有两个分支:mid是奇数和mid是偶数,每个分支下各自有是否跟相邻数字相等的判断,这里有另外一个优化的技巧,即异或,在查找单个数字的时候见识过异或的威力,实际上异或还有一个定律:奇数和1异或等于减一,偶数异或1等于加一;那么可以优化if-else分支,不用去分奇数偶数,只要相邻想等的,那么单个数在右半部分,不想等则在左半部分
func SingleNonDuplicate(nums []int) int {
    low, high := 0, len(nums) - 1
    for low < high {
        mid := (high - low) >> 1 + low
        if nums[mid] == nums[mid^1] {
            low = mid + 1
        } else {
            high = mid
        }
    }
    return nums[low]
}

你可能感兴趣的:(golang)