題目地址:
https://leetcode.com/problems/single-element-in-a-sorted-array/
給定一個從小到大排好序的數組,除了其中一個數字只出現了一次外,每個數字都出現了兩次,要求找到那個只出現了一次的數字。
法1:位運算。一路異或一遍即可。代碼如下:
class Solution {
public int singleNonDuplicate(int[] nums) {
int res = 0;
for (int n : nums) {
res ^= n;
}
return res;
}
}
時間複雜度,空間。
法2:二分。考慮將區間二分後如何判斷那個唯一的數應該在哪個半邊。設二分中點爲,區間左右端點分別爲和,那麼區間中比大的數的個數可以這樣計算:如果,那麼個數是;否則個數是。而由於除了那個落單的數以外,其他數都是兩兩配對的,所以如果比大的數的個數是偶數個,那麼那個唯一的數一定在左半邊,否則在右半邊。這樣就可以縮小範圍了。代碼如下:
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];
}
}
時間複雜度,空間。