Leetcode SingleNumber I & II & III 136/137/260
SingleNumber I:
题目链接:https://leetcode-cn.com/problems/single-number/
题意:
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
说明:
你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?
示例 1:
输入: [2,2,1]
输出: 1
示例 2:
输入: [4,1,2,1,2]
输出: 4
分析:
利用异或(xor)运算,两个相同的数异或为0
代码如下:
class Solution {
public:
int singleNumber(int A[], int n) {
int ans = ;
for(int i = ; i < n; ++i) {
ans ^= A[i];
}
return ans;
}
};
SingleNumber II:
题目链接:https://leetcode-cn.com/problems/single-number-ii/
借鉴:https://www.cnblogs.com/grandyang/p/4263927.html
题意:
给定一个非空整数数组,除了某个元素,其余每个元素均出现了三次。找出那个没出现过三次的元素。
说明:
你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?
示例 1:
输入: [2,2,3,2]
输出: 3
示例 2:
输入: [0,1,0,1,0,1,99]
输出: 99
分析1:
与第一题的不同是这里相同的数出现了3次,如果能定义一种3进制异或运算,就可以以第一题的方式解出这道题了。
代码如下:
class Solution {
public:
int singleNumber(vector<int>& nums) {
int res = ;
for (int i = ; i < ; ++i) {
int sum = ;
for (int j = ; j < nums.size(); ++j) {
// 取nums[j]的第i位值,然后加起来
sum += (nums[j] >> i) & ;
}
// sum目前的有进位相加的结果,模3以后就是无进位相加的结果
res |= (sum % ) << i;
}
return res;
}
};
分析2:
还有一种解法,思路很相似,用3个整数来表示INT的各位的出现次数情况,one表示出现了1次,two表示出现了2次。当出现3次的时候该位清零。最后答案就是one的值。
ones代表第ith 位只出现一次的掩码变量twos代表第ith 位只出现两次次的掩码变量threes代表第ith 位只出现三次的掩码变量
代码如下:
class Solution {
public:
int singleNumber(vector<int>& nums) {
int one = , two = , three = ;
for (int i = ; i < nums.size(); ++i) {
// one & nums[i]的结果某一位上为1意味着这一位在上一轮出现过一次,在这一轮又出现过一次,那么也就意味着出现了两次
// two此时包含所有出现过2次和3次的
two |= one & nums[i];
// one的某一位为1,表示之前出现过1次。如果nums[i]对应位为0,one的某一位没有变化;如果nums[i]对应位为1,one的某一位变为0,表示这一位出现2次了。
// one的某一位为0,表示之前出现过0次或2次。如果nums[i]对应位为0,one的某一位没有变化;如果nums[i]对应位为1,one的某一位变为1,表示这一位出现过1次或3次。
// one此时包含所有出现过1次和3次的
one ^= nums[i];
three = one & two;
// 消掉3次的
one &= ~three;
two &= ~three;
}
return one;
}
};
分析3:
和分析2一样,不过这次只需要2个变量。
ones代表第ith 位只出现一次的掩码变量twos代表第ith 位只出现两次次的掩码变量
ones[i]原:ones第i位二进制位原来的值
twos[i]原:twos第i位二进制位原来的值
x[i]:所要异或的数的第i位二进制位的值
ones[i]:ones第i位二进制位异或后的值
ones[i]:ones第i位二进制位异或后的值
| ones[i]原 | twos[i]原 | x[i] | ones[i] | twos[i] |
| 0 | 0 | 0 | 0 | 0 |
| 0 | 1 | 0 | 0 | 1 |
| 1 | 0 | 0 | 1 | 0 |
| 1 | 1 | 0 | x | x |
| 0 | 0 | 1 | 1 | 0 |
| 0 | 1 | 1 | 0 | 0 |
| 1 | 0 | 1 | 0 | 1 |
| 1 | 1 | 1 | x | x |
| x\ones原twos原 | 00 | 01 | 10 | 11 |
| 0 | 0 | 0 | 1 | x |
| 1 | 1 | 0 | 0 | x |
| x\onestwos原 | 00 | 01 | 10 | 11 |
| 0 | 0 | 1 | 0 | x |
| 1 | 1 | 0 | 0 | x |
得到公式为:
ones = (ones ^ x) & ~twos;
twos = (twos ^ x) & ~ones;
代码如下:
class Solution {
public:
int singleNumber(vector<int>& nums) {
int twos = , ones = ;
for (int i = ; i < nums.size(); ++i) {
// ones ^ nums[i]后ones的某一位1可能表示原来出现过0次,也可能表示原来出现过2次
// & ~twos表示把原来出现过2次的部分删掉
ones = (ones ^ nums[i]) & ~twos;
// twos ^ nums[i]后twos的某一位1可能表示目前出现过2次,也可能表示目前出现过1次
// & ~ones表示把目前出现过1次的部分删掉
twos = (twos ^ nums[i]) & ~ones;
}
return ones | twos;
}
};
SingleNumber III:
题目链接:https://leetcode-cn.com/problems/single-number-iii/
题意:
给定一个整数数组 nums,其中恰好有两个元素只出现一次,其余所有元素均出现两次。 找出只出现一次的那两个元素。
示例 :
输入:[1,2,1,3,2,5]
输出:[3,5]
注意:
- 结果输出的顺序并不重要,对于上面的例子,
[5, 3]也是正确答案。 - 你的算法应该具有线性时间复杂度。你能否仅使用常数空间复杂度来实现?
- 结果输出的顺序并不重要,对于上面的例子,
分析:
将所有数异或一遍,那个异或完后一定有某一位是1,这意味着两个数在这一位上不同,因此只要把这一位上为0的数和为1的数分别全部异或一遍就能得到只出现一次的2个元素了。
代码如下:
class Solution {
public:
vector<int> singleNumber(vector<int>& nums) {
vector<int> ans;
int a = , b = , lowbit = ;
for(int i = ; i < (int)nums.size(); ++i) {
lowbit ^= nums[i];
}
lowbit = lowbit & (-lowbit);
for(int i = ; i < (int)nums.size(); ++i) {
if(nums[i] & lowbit) a ^= nums[i];
else b ^= nums[i];
}
ans.push_back(a);
ans.push_back(b);
return ans;
}
};
Leetcode SingleNumber I & II & III 136/137/260的更多相关文章
- Leetcode 136 137 260 SingleNumber I II III
Leetccode 136 SingleNumber I Given an array of integers, every element appears twice except for one. ...
- 136.137.260. Single Number && 位运算
136. Single Number 意思就是给你一堆数,每个数都出现了两次,只有一个数只出现了一次,找出这个数 位运算(和c艹一样) &:按位与 |:按位或 ^:异或(一样为0,不一样为1) ...
- [LeetCode] Contains Duplicate(II,III)
Contains Duplicate Given an array of integers, find if the array contains any duplicates. Your funct ...
- Leetcode 137. Single Number I/II/III
Given an array of integers, every element appears twice except for one. Find that single one. 本题利用XO ...
- 买卖股票的最佳时机I II III IV
I 假设有一个数组,它的第i个元素是一支给定的股票在第i天的价格.如果你最多只允许完成一次交易(例如,一次买卖股票),设计一个算法来找出最大利润. II 假设有一个数组,它的第i个元素是一个给定的股票 ...
- [LeetCode]singleNumber
题目:singleNumber Given an array of integers, every element appears twice except for one. Find that si ...
- [LeetCode] 216. Combination Sum III 组合之和 III
Find all possible combinations of k numbers that add up to a number n, given that only numbers from ...
- [LeetCode] Palindrome Partitioning II 解题笔记
Given a string s, partition s such that every substring of the partition is a palindrome. Return the ...
- [leetcode]Word Ladder II @ Python
[leetcode]Word Ladder II @ Python 原题地址:http://oj.leetcode.com/problems/word-ladder-ii/ 参考文献:http://b ...
随机推荐
- UVA1646-Edge Case(递推+斐波那契数列)
Problem UVA1646-Edge Case Time Limit: 3000 mSec Problem Description Input For each test case, you ge ...
- C++ 星号* 与 引用&
星号 * 1. 声明的时候有*, 表示指针变量 int *p=&a;// '&'的作用就是把a变量在内存中的地址给提取出来 2. * +地址, 表示地址操作符 3. 数字*数字, 表示 ...
- 基于Spring Boot和Shiro的后台管理系统FEBS
FEBS是一个简单高效的后台权限管理系统.项目基础框架采用全新的Java Web开发框架 —— Spring Boot 2.0.3,消除了繁杂的XML配置,使得二次开发更为简单:数据访问层采用Myba ...
- Jenkins以root用户运行的方法
以centOS系统为例,记录下修改Jenkins以root用户运行的方法. 修改Jenkins配置文件 # 打开配置文件 vim /etc/sysconfig/jenkins # 修改$JENKINS ...
- 禁止 gVim 在 Linux 下自动生成 undo 文件 *.un~
在配置文件 .vimrc 中加入配置项, set noundofile 完.
- java操作Redis缓存设置过期时间
关于Redis的概念和应用本文就不再详解了,说一下怎么在java应用中设置过期时间. 在应用中我们会需要使用redis设置过期时间,比如单点登录中我们需要随机生成一个token作为key,将用户的信息 ...
- P2251 质量检测--洛谷luogu
传送门 题目描述 为了检测生产流水线上总共N件产品的质量,我们首先给每一件产品打一个分数A表示其品质,然后统计前M件产品中质量最差的产品的分值Q[m] = min{A1, A2, ... Am},以及 ...
- mac sourcetree push分支选中所有tag的时候报错
错误信息: ....... ! [rejected] 573_0811_stable -> 573_0811_stable (already exists)updating local trac ...
- object detection[YOLO]
这部分,我们来聊聊YOLO. YOLO:You Only Look Once,顾名思义,就是希望网络在训练过程中,一张图片只要看一次就行,不需要去多次观察,比如滑框啥的,从而从底层原理上就减少了很多的 ...
- 测试工具使用-Qunit单元测试使用过程
031302620 应课程要求写一篇单元测试工具的博客,但是暂时没用到java,所以不想使用junit(对各种类都不熟悉的也不好谈什么测试),原计划是要用phpunit,但是安装经历了三个小时,查阅各 ...