【Leetcode】540. Single Element in a Sorted Array

題目地址:

https://leetcode.com/problems/single-element-in-a-sorted-array/

給定一個從小到大排好序的數組AA,除了其中一個數字只出現了一次外,每個數字都出現了兩次,要求找到那個只出現了一次的數字。

法1:位運算。一路異或一遍即可。代碼如下:

class Solution {
    public int singleNonDuplicate(int[] nums) {
        int res = 0;
        for (int n : nums) {
            res ^= n;
        }
        
        return res;
    }
}

時間複雜度O(n)O(n),空間O(1)O(1)

法2:二分。考慮將區間二分後如何判斷那個唯一的數應該在哪個半邊。設二分中點爲mm,區間左右端點分別爲llrr,那麼區間中比A[m]A[m]大的數的個數可以這樣計算:如果A[m]=A[m+1]A[m]=A[m+1],那麼個數是rm1r-m-1;否則個數是rmr-m。而由於除了那個落單的數以外,其他數都是兩兩配對的,所以如果比A[m]A[m]大的數的個數是偶數個,那麼那個唯一的數一定在左半邊,否則在右半邊。這樣就可以縮小範圍了。代碼如下:

public class Solution {
    public int singleNonDuplicate(int[] nums) {
        int l = 0, r = nums.length - 1;
        while (l < r) {
            int m = l + (r - l >> 1);
            if (nums[m] == nums[m + 1]) {
                int larger = r - m - 1;
                // 如果比A[m]大的數是偶數個,則答案在左邊,且不能是A[m],所以令r = m - 1;
                // 如果比A[m]大的數是奇數個,則答案在右邊,且不能是A[m],所以令l = m + 2;
                if (larger % 2 == 0) {
                    r = m - 1;
                } else {
                    l = m + 2;
                }
            } else {
            	// 此時nums[m] != nums[m + 1],則nums[m + 1] > nums[m]。
                int larger = r - m;
                // 如果比A[m]大的數是偶數個,則答案在左邊,且可能是A[m],所以令r = m;
                // 如果比A[m]大的數是奇數個,則答案在右邊,且不可能是A[m](因爲題目保證答案是唯一的),所以令r = m - 1;
                if (larger % 2 == 0) {
                    r = m;
                } else {
                    l = m + 1;
                }
            }
        }
        
        return nums[l];
    }
}

時間複雜度O(logn)O(\log n),空間O(1)O(1)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章