[LeetCode] Single Element in a Sorted Array 有序数组中的单独元素
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.
这道题给我们了一个有序数组,说是所有的元素都出现了两次,除了一个元素,让我们找到这个元素。如果没有时间复杂度的限制,我们可以用多种方法来做,最straightforward的解法就是用个双指针,每次检验两个,就能找出落单的。也可以像Single Number里的方法那样,将所有数字亦或起来,相同的数字都会亦或成0,剩下就是那个落单的数字。那么由于有了时间复杂度的限制,需要为O(logn),而数组又是有序的,不难想到要用二分搜索法来做。二分搜索法的难点在于折半了以后,如何判断将要去哪个分支继续搜索,而这道题确实判断条件不明显,比如下面两个例子:
1 1 2 2 3
1 2 2 3 3
这两个例子初始化的时候left=0, right=4一样,mid算出来也一样为2,但是他们要去的方向不同,如何区分出来呢?仔细观察我们可以发现,如果当前数字出现两次的话,我们可以通过数组的长度跟当前位置的关系,计算出右边和当前数字不同的数字的总个数,如果是偶数个,说明落单数左半边,反之则在右半边。有了这个规律就可以写代码了,为啥我们直接就能跟mid+1比呢,不怕越界吗?当然不会,因为left如何跟right相等,就不会进入循环,所以mid一定会比right小,一定会有mid+1存在。当然mid是有可能为0的,所以此时当mid和mid+1的数字不等时,我们直接返回mid的数字就可以了,参见代码如下:
解法一:
class Solution {
public:
int singleNonDuplicate(vector<int>& nums) {
int left = , right = nums.size() - , n = nums.size();
while (left < right) {
int mid = left + (right - left) / ;
if (nums[mid] == nums[mid + ]) {
if ((n - - mid) % == ) right = mid;
else left = mid + ;
} else {
if (mid == || nums[mid] != nums[mid - ]) return nums[mid];
if ((n - - mid) % == ) right = mid;
else left = mid + ;
}
}
return nums[left];
}
};
下面这种解法是对上面的分支进行合并,使得代码非常的简洁。使用到了亦或1这个小技巧,为什么要亦或1呢,原来我们可以将坐标两两归为一对,比如0和1,2和3,4和5等等。而亦或1可以直接找到你的小伙伴,比如对于2,亦或1就是3,对于3,亦或1就是2。如果你和你的小伙伴相等了,说明落单数在右边,如果不等,说明在左边,这方法,太叼了有木有,参见代码如下:
解法二:
class Solution {
public:
int singleNonDuplicate(vector<int>& nums) {
int left = , right = nums.size() - ;
while (left < right) {
int mid = left + (right - left) / ;
if (nums[mid] == nums[mid ^ ]) left = mid + ;
else right = mid;
}
return nums[left];
}
};
下面这种解法其实跟上面的方法其实有些类似,虽然没有亦或1,但是将right缩小了一倍,但是在比较的时候,是比较mid*2和mid*2+1的关系的,这样还是能正确的比较原本应该相等的两个小伙伴的值的,其实核心思路和上面一样,参见代码如下:
解法三:
class Solution {
public:
int singleNonDuplicate(vector<int>& nums) {
int left = , right = nums.size() / ;
while (left < right) {
int mid = left + (right - left) / ;
if (nums[mid * ] == nums[mid * + ]) left = mid + ;
else right = mid;
}
return nums[left * ];
}
};
下面这种方法其实跟解法二很像,没有用亦或1,但是对mid进行了处理,强制使其成为小伙伴对儿中的第一个位置,然后跟另一个小伙伴比较大小,参见代码如下:
解法四:
class Solution {
public:
int singleNonDuplicate(vector<int>& nums) {
int left = , right = nums.size() - ;
while (left < right) {
int mid = left + (right - left) / ;
if (mid % == ) --mid;
if (nums[mid] == nums[mid + ]) left = mid + ;
else right = mid;
}
return nums[left];
}
};
参考资料:
https://discuss.leetcode.com/topic/83310/short-compare-nums-i-with-nums-i-1
https://discuss.leetcode.com/topic/82235/java-code-by-using-binary-search-o-log-n
https://discuss.leetcode.com/topic/82332/java-binary-search-o-log-n-shorter-than-others
https://discuss.leetcode.com/topic/87424/java-binary-search-short-7l-o-log-n-w-explanations
[LeetCode] Single Element in a Sorted Array 有序数组中的单独元素的更多相关文章
- 540 Single Element in a Sorted Array 有序数组中的单一元素
给定一个只包含整数的有序数组,每个元素都会出现两次,唯有一个数只会出现一次,找出这个数.示例 1:输入: [1,1,2,3,3,4,4,8,8]输出: 2 示例 2:输入: [3,3,7,7,10,1 ...
- [LeetCode] 26. Remove Duplicates from Sorted Array 有序数组中去除重复项
Given a sorted array nums, remove the duplicates in-place such that each element appear only once an ...
- [LeetCode] Remove Duplicates from Sorted Array 有序数组中去除重复项
Given a sorted array, remove the duplicates in place such that each element appear only once and ret ...
- LeetCode——Single Element in a Sorted Array
Question Given a sorted array consisting of only integers where every element appears twice except f ...
- [leetcode]26. Remove Duplicates from Sorted Array有序数组去重(单个元素只出现一次)
Given a sorted array nums, remove the duplicates in-place such that each element appear only once an ...
- LeetCode 977. Squares of a Sorted Array (有序数组的平方)
题目标签:Array 题目给了我们一组 从小到大的 integers,让我们平方数字 并且 也排序成 从小到达. 因为有负数在里面,平方后,负数在array的位置会变动. 可以设left 和 righ ...
- LeetCode 540. 有序数组中的单一元素(Single Element in a Sorted Array) 42
540. 有序数组中的单一元素 540. Single Element in a Sorted Array 题目描述 每日一算法2019/6/14Day 42LeetCode540. Single E ...
- Leetcode 540.有序数组中的单一元素
有序数组中的单一元素 给定一个只包含整数的有序数组,每个元素都会出现两次,唯有一个数只会出现一次,找出这个数. 示例 1: 输入: [1,1,2,3,3,4,4,8,8] 输出: 2 示例 2: 输入 ...
- Java实现 LeetCode 540 有序数组中的单一元素(位运算入门)
540. 有序数组中的单一元素 给定一个只包含整数的有序数组,每个元素都会出现两次,唯有一个数只会出现一次,找出这个数. 示例 1: 输入: [1,1,2,3,3,4,4,8,8] 输出: 2 示例 ...
随机推荐
- 【ASP.NET Core】如何隐藏响应头中的 “Kestrel”
全宇宙人民都知道,ASP.NET Core 应用是不依赖服务器组件的,因此它可以独立运行,一般是使用支持跨平台的 Kestrel 服务器(当然,在 Windows 上还可以考虑用 HttpSys,但要 ...
- centos-6.7 内核升级(转)
本文转自http://www.linuser.com/thread-1622-1-1.html 默认centos-6.7 自带的内核版本: [root@testserver ~ ::]#uname - ...
- (转)SQLite内置函数
一.聚合函数: SQLite中支持的聚合函数在很多其他的关系型数据库中也同样支持,因此我们这里将只是给出每个聚集函数的简要说明,而不在给出更多的示例了.这里还需要进一步说明的是,对于所有聚合函数而言, ...
- 实现Windows程序的更新
实现Windows程序的更新 一.使用枚举避免不合理的赋值 1.使用枚举的好处: 使用常量类中Student类中加入一个特别属性,StudentGender,而且这个属性只能接受两个有效值," ...
- css3图片模糊过滤特效
体验效果:点击这里查看效果 代码如下:<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" " ...
- web api 安全设计(1)
环境:后台 ASP.NET Web API ,前端为 html,js(跨域访问) 场景1: 客户端自保管RSA 公钥和密钥,签名为客户端私钥签名,服务端用客户端公钥进行签名验证 场景2: 客户端使用S ...
- 在linux环境下安装JDK并配置环境变量
操作步骤如下 1.根据linux服务器的系统版本在官网下载相应linux版本JDK(32位下载x86,64位下载x64) 2.通过远程连接工具(filezilla)将下载好的JDK上传至linux服务 ...
- C语言博客作业—函数
一.PTA实验作业 题目1:使用函数输出水仙花数 1. 本题PTA提交列表 2. 设计思路 (1)首先定义函数narcissistic(number)判断number是否为水仙花数: (2)narc用 ...
- 团队作业7——第二次项目冲刺(Beta版本12.08)
项目每个成员的进展.存在问题.接下来两天的安排. 已完成的内容:完成了排行榜的测试.上传头像功能的原型设计.界面优化 计划完成的内容:上传头像功能开发.测试.头像裁剪原型设计 每个人的工作 (有wor ...
- 学大伟业 国庆Day2
期望得分:30+100+0=130 实际得分:30+100+20=150 忍者钩爪 (ninja.pas/c/cpp) [问题描述] 小Q是一名酷爱钩爪的忍者,最喜欢飞檐走壁的感觉,有一天小Q发现一个 ...