Given a sorted array consisting of only integers where every element appears twice except for one element which appears once. Find this single element that appears only once.
Example 1:
Input: [1,1,2,3,3,4,4,8,8] Output: 2
Example 2:
Input: [3,3,7,7,10,11,11] Output: 10
Note: Your solution should run in O(log n) time and O(1) space.
给定一个排好序的数组,其中每个元素出现两次,只有一个元素出现一次,找出这个出现一次的元素。
题目要求run in O(log n) time and O(1) space
如果不按照题目要求,这是一个很简明的算法题。给出3个算法如下:
1、顺序遍历,O(n) time
class Solution { public: int singleNonDuplicate(vector<int>& nums) { for (int i = 0; i < nums.size(); i = i + 2) { if (nums[i + 1] - nums[i] != 0) return nums[i]; } } }; // 7 ms
2、使用一个map存储元素出现的次数,返回出现1次的元素 O(n) time and O(n) space
class Solution { public: int singleNonDuplicate(vector<int>& nums) { unordered_map<int, int> m; for (auto num : nums) m[num]++; for (auto it = m.begin(); it != m.end(); it++) if (it->second == 1) return it->first; } }; // 10 ms
3、使用异或来找出出现一次的元素。 O(n) time and O(1) space
class Solution { public: int singleNonDuplicate(vector<int>& nums) { int res = 0; for (auto& num : nums) res ^= num; return res; } }; // 7 ms
以上三种算法虽然不满足复杂度要求,但是完全可以AC。
4、使用二分搜索来查找元素。符合题意 O(log n) time and O(1) space
那个单独出现的元素所在的索引一定是偶数。利用这个性质来二分搜索
如果mid是偶数,并且mid与mid+1的元素值相同,说明单独的元素在mid的后面。
如果mid是奇数,并且mid和mid-1的元素值相同,说明单独的元素在mid的后面。
举个例子一看便知。
2 2 3 3 5 5 7
1 2 2 3 3 5 5
class Solution { public: int singleNonDuplicate(vector<int>& nums) { int lo = 0, hi = nums.size() - 1; while (lo < hi) { int mid = lo + (hi - lo) / 2; if (mid % 2 == 0) { if (nums[mid] == nums[mid + 1]) lo = mid + 2; else hi = mid; } else { if (nums[mid] == nums[mid - 1]) lo = mid + 1; else hi = mid - 1; } } return nums[lo]; } }; // 7 ms