[LeetCode]singleNumber
题目:singleNumber
Given an array of integers, every element appears twice except for one. Find that single one.
	Note:
	Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory?
给一个数组里面除了唯一的一个数只出现一次,其他每个数都重复了一次。
要求:线性的时间复杂度,和O(1)的空间复杂度
思路:
如果不要求线性的时间复杂度,则可以考虑用排序的方法,成熟稳定,又有很好的通用性。
但是,如果要保证线性的时间复杂度,则可以考虑使用hash_map来找单个出现的数字。
通常思路里面效率的瓶颈在于如何确定当前元素是前面已经出现过的元素,此时可以通过hash_map来确保在O(1)的时间复杂度里确定当前元素是否出现过。
我用删除的方法来降低冲突率,同时,方便最后找到最终的singleNumber。
/**
*Given an array of integers, every element appears twice except for one. Find that single one.
*Note:
*Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory?
**/
/**空间复杂度O(n),时间复杂度O(n)但是依赖map的性能**/
int LeetCode::singleNumberMap(vector<int>& nums){
hash_map<int,int> hmp;
auto it = nums.cbegin();
while (it != nums.cend()){
auto temp = hmp.find(*it);
if (temp != hmp.cend()){//找得到当前元素,说明它在前面出现过
//(*temp).second = 2;
hmp.erase(temp);//删除重复元素
}
else{
hmp.insert(make_pair(*it,));//插入首次出现的元素
}
++it;
}
if (hmp.size() == ){//如果最终存在singleNumber
auto ret = hmp.begin();
return (*ret).first;
}
return -;//不存在,则返回-1
}
思路:
使用异或的方法;
因为元素是数字,且数组保证只重复两次;可以考虑使用异或的方法,来直接求出单一数字。
这个方法比上面的更高效,且空间复杂度O(1),而上面的空间复杂度O(n)。
/**
空间复杂度O(1),时间复杂度O(n)
使用异或来求单个数字
**/
int LeetCode::singleNumberXOR(vector<int>& nums){
int sum = ;
auto it = nums.cbegin();
while (it != nums.cend()){
sum = sum ^ (*it);//异或
++it;
}
return sum;
}
题目:singleNumberII
Given an array of integers, every element appears three times except for one, which appears exactly once. Find that single one.
	Note:
	Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory?
给一个数组里面除了唯一的一个数只出现一次,其他每个数都重复了两次(即出现3次)。
要求:线性的时间复杂度,和O(1)的空间复杂度
思路:
使用hash_map同样可以求出来,思路跟第一个是一样的。
但是,如何用异或更高效的找到singleNumber呢?
首先还是对每个元素异或,保留奇数次出现的元素(once);
同时,增加一个变量accumulate |= (*it) & once;
上面的算式能够保留出现2次以上的元素;(it表示当前元素)
例如:once中出现过奇数次则表示保留了该数字,则必然出现2次以上,于是上面表达式的结果确实是保留了当前元素;
once出现了偶数次,表示未保留该数字,则取决于accumulate中是否保留该数字,没有则是0。
因此,上面表达式确实能够保留出现2次以上的元素。
然后出现3次则表示,上面两个值都是保留当前元素的状态,于是在异或一次就消除了出现3次的元素。
int LeetCode::singleNumber(vector<int>& nums){
    //once标记出现奇数次的数字,accumulate标记出现2次以上的数字
    int once = ,accumulate = ;
    auto it = nums.cbegin();
    while (it != nums.cend()){
        //once中出现过奇数次则表示保留了该数字,则必然出现2次以上;
        //once出现了偶数次,表示未保留该数字,则取决于accumulate中是否保留该数字,没有则是0
        accumulate |= (*it) & once;// 只要第二次或者以上出现,就为1
        once ^= (*it);// 出现奇数次保留,偶数次抛弃
        int t = once & accumulate;// 第三次的时候one和accumulation都保留了该位的值
        once &= ~t;  // 清零出现三次的该位的值
        accumulate &= ~t;
        //once = (once ^ (*it)) & ~accumulate;
        //accumulate = (accumulate ^ (*it)) & ~once;
        ++it;
    }
    return once;
}
上面一连串的求解,还可以缩减成下面两个表达式:
once = (once ^ (*it)) & ~accumulate;
accumulate = (accumulate ^ (*it)) & ~once;
题目:Single Number III
Given an array of numbers nums, in which exactly two elements appear only once and all the other elements appear exactly twice. Find the two elements that appear only once.
For example:
Given nums = [1, 2, 1, 3, 2, 5], return [3, 5].
Note:
- The order of the result is not important. So in the above example, [5, 3]is also correct.
- Your algorithm should run in linear runtime complexity. Could you implement it using only constant space complexity?
给一个数组里面除了两个数只出现一次,其他每个数都出现了两次。
要求:线性的时间复杂度,和O(1)的空间复杂度。
思路:
设数组为A[],其中两个只出现一次的数字是A,B
根据第一个问题的思路,如果只有一个数字可以直接将所有数字异或得到。因此,该问题如果异或所有数字得到的值是A^B。
那么,如果能将A,B区分开就可以了;异或表示两个数字中不相同的位是1,即如果A^B的某一位是1,表示A和B中对应的该为分别为0和1,或1和0。
反之,只要将该位为1的所有数从新异或一遍,就能的到A或B中的一个数字,于是就区分开了。
vector<int> LeetCode::singleNumber3(vector<int>& nums){
    int xorall = , first1 = ;//第一个1
    vector<int>result(, );
    for (auto i : nums){//求A^B
        xorall ^= i;
    }
    first1 = xorall & (~(xorall - ));//求A^B中第一个1的值,例如A = 4,B = 8,A^B = 12,first1 = (0100 ^ 1000) & (0100) = 4
    for (auto i : nums){
        if (first1 & i)result[] ^= i;//所有A^B第一个1相同位置为1的元素异或
        else result[] ^= i;;
    }
    return result;
}
[LeetCode]singleNumber的更多相关文章
- LeetCode——single-number系列
		LeetCode--single-number系列 Question 1 Given an array of integers, every element appears twice except ... 
- leetcode — single-number
		/** * Source : https://oj.leetcode.com/problems/single-number/ * * * Given an array of integers, eve ... 
- Leetcode SingleNumber I & II & III 136/137/260
		SingleNumber I: 题目链接:https://leetcode-cn.com/problems/single-number/ 题意: 给定一个非空整数数组,除了某个元素只出现一次以外,其余 ... 
- Leetcode 136 137 260 SingleNumber I II III
		Leetccode 136 SingleNumber I Given an array of integers, every element appears twice except for one. ... 
- LeetCode 2: single-number II
		Given an array of integers, every element appears three times except for one. Find that single one. ... 
- LeetCode 1: single-number
		Given an array of integers, every element appears twice except for one. Find that single one. soluti ... 
- single-number leetcode C++
		Given an array of integers, every element appears twice except for one. Find that single one. Note: ... 
- [LeetCode] Single Number III 单独的数字之三
		Given an array of numbers nums, in which exactly two elements appear only once and all the other ele ... 
- [LeetCode] Single Number II 单独的数字之二
		Given an array of integers, every element appears three times except for one. Find that single one. ... 
随机推荐
- HBase 系列(四)—— HBase 集群环境配置
			一.集群规划 这里搭建一个 3 节点的 HBase 集群,其中三台主机上均为 Regin Server.同时为了保证高可用,除了在 hadoop001 上部署主 Master 服务外,还在 hadoo ... 
- 微服务架构 - 网关 Spring Cloud Gateway
			Spring Cloud Gateway 工作原理 客户端向 Spring Cloud Gateway 发出请求,如果请求与网关程序定义的路由匹配,则将其发送到网关 Web 处理程序,此处理程序运行特 ... 
- Okhttp3源码解析(4)-拦截器与设计模式
			### 前言 回顾: [Okhttp的基本用法](https://www.jianshu.com/p/8e404d9c160f) [Okhttp3源码解析(1)-OkHttpClient分析](htt ... 
- 梳理commons-lang工具包
			目录 概述 builder包 NumberUtils 转换 String 类型为原始类型 截取小数位数 创建包装类型 最大值 | 最小值 关于数字的检查 mutable包 relect包 Constr ... 
- 开发APP必须知道的API集合,来源http://www.cnblogs.com/wikiki/p/7232388.html
			笔记 OneNote - OneNote支持获取,复制,创建,更新,导入与导出笔记,支持为笔记添加多媒体内容,管理权限等.提供SDK和Demo. 为知笔记 - 为知笔记Windows客户端开放了大量的 ... 
- Leetcode之二分法专题-240. 搜索二维矩阵 II(Search a 2D Matrix II)
			Leetcode之二分法专题-240. 搜索二维矩阵 II(Search a 2D Matrix II) 编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target.该矩阵 ... 
- MySQL8版本密码重置(老版本skip-grant-tables不起作用,MySQL服务开启之后立马关闭)
			原文:https://blog.csdn.net/gupao123456/article/details/80766154 MySQL密码重置思路MySQL的密码是存放在user表里面的,修改密码其 ... 
- 小白专场-多项式乘法与加法运算-c语言实现
			目录 一.题意理解 二.求解思路 三.多项式的表示 3.1 数组 3.2 链表 四.程序框架搭建 五.如何读入多项式 六.如何将两个多项式相加 七.如何将两个多项式相乘 八.如何将多项式输出 一.题意 ... 
- gym/102021/J GCPC18 模拟拼图
			模拟拼图 题意: 给定n块拼图,每个拼图为四方形,对应四条边有四个数字,如果为0,表示这个边是在边界的,其他数字表示和另一个拼图的一条边相接.保证每个非零数只出现两次. 思路: 模拟,但是要注意几个情 ... 
- CodeForces 780 E Underground Lab
			Underground Lab 题解: 如果遍历一棵树,我们可以发现最多需要走的步数也不会超过2 * n步. 所以我们选出一棵树,然后遍历一边这颗树. 然后把序列分成k块就好了. 代码: #inclu ... 
