[OJ] Single Number II
LintCode 83. Single Number II (Medium)
LeetCode 137. Single Number II (Medium)
以下算法的复杂度都是:
时间复杂度: O(n)
空间复杂度: O(1)
解法1. 32个计数器
最简单的思路是用32个计数器, 满3复位0.
class Solution {
public:
int singleNumberII(vector<int> &A) {
int cnt[32] = {0};
int res = 0;
for (int i = 0; i < 32; ++i) {
for (int n : A) {
cnt[i] += (n >> i) & 1;
cnt[i] %= 3;
}
res |= cnt[i] << i;
}
return res;
}
};
解法2. 找规律
我的思路是, 解法1中的计数其实只需要两个bit就够了. 所有的首个bit记做res, 所有的第二个bit记做carry, 找规律:
如果A[i]的第k位是0, 则res和carry的第k位保持原样.
如果A[i]的第k位是1, 则:
| res | carry | res' | carry' |
|---|---|---|---|
| 0 | 0 | 1 | 0 |
| 1 | 0 | 0 | 1 |
| 0 | 1 | 0 | 0 |
此时(A[i][k]=1时)的规律就是:
res'[k]=~res[k] & ~carry[k]
carry'[k]=res[k] & ~carry[k]
class Solution {
public:
int singleNumberII(vector<int> &A) {
int res = 0, carry = 0;
for (int n : A) {
for (int i = 0; i < 32; ++i) {
int mask = (1 << i);
int bit = n & mask;
if (bit) {
int newRes = (~mask & res) + ((~res & mask) & (~carry & mask));
carry = (~mask & carry) + ((res & mask) & (~carry & mask));
res = newRes;
}
}
}
return res;
}
};
解法2.1. 解法2的简化
解法2中, 将A[i][k]=0和=1的情况合并, 可以得到:
res'[k]=(A[i][k] & ~res[k] & ~carry[k]) | (~A[i][k] & res[k])
carry'[k]=(A[i][k] & res[k] & ~carry[k]) | (~A[i][k] & carry[k])
这样的好处是可以32位一起算, 而不用一位一位地算:
res'=(A[i] & ~res & ~carry) | (~A[i][k] & res)
carry'=(A[i] & res & ~carry) | (~A[i][k] & carry)
class Solution {
public:
int singleNumberII(vector<int> &A) {
int res = 0, carry = 0;
for (int n : A) {
int newRes = (n & (~res & ~carry)) | (~n & res);
carry = (n & (res & ~carry)) | (~n & carry);
res = newRes;
}
return res;
}
};
解法3. one, two, three
Discuss中看到的解法, 自己实在想不出来. 用one, two和three三个int值作为bit flags.
循环对A[0]到A[n]进行考察, 当考察A[i]时:
记S[i]={A[0],...,A[i]},
若S[i]中所有数字的第k位bit的数目%3==1, 则one的第k位为1, 否则为0.
若S[i]中所有数字的第k位bit的数目%3==2, 则two的第k位为1, 否则为0.
而three是一个临时变量, 用于记录这一轮中, 哪些bit的数目恰巧是3的倍数.
two |= one & n;: 给two加上那些从1到2的数字.
one ^= n;: 这句比较巧妙, 既删掉了会变成2的那些1, 又加上了新的1.
three = one & two;: 1+2=3...
one&= ~three: 从1中刨去那些成为3的1.
two&= ~three: 从2中跑去那些成为3的2.
...如果你能解释得更清晰易懂, 欢迎留言!
class Solution {
public:
int singleNumberII(vector<int> &A) {
int one = 0, two = 0, three = 0;
for (int n : A) {
two |= one & n;
one ^= n;
three = one & two;
one &= ~three;
two &= ~three;
}
return one;
}
};
解法3.1. 解法3的变形
自己没想出解法4, 但是参照它的思路, 写了一个对自己比较直观的算法.
three = two & n;: 算出从2变成3的那些2.
two = (two & ~three) | (one & n);: (two & ~three)是从2中刨去那些变为3的2, (one & n)是加上那些从1变成2的1.
one = (one & ~n) | (n & ~three & ~two);: (one & ~n)是从1中刨去那些变成2的1, (n & ~three & ~two)是加上那些没给"2变3"或"1变2"用过的1.
class Solution {
public:
int singleNumberII(vector<int> &A) {
int one = 0, two = 0;
for (int n : A) {
int three = two & n;
two = (two & ~three) | (one & n);
one = (one & ~n) | (n & ~three & ~two);
}
return one;
}
};
[OJ] Single Number II的更多相关文章
- 【leetcode】Single Number && Single Number II(ORZ 位运算)
题目描述: Single Number Given an array of integers, every element appears twice except for one. Find tha ...
- 【题解】【位操作】【Leetcode】Single Number II
Given an array of integers, every element appears three times except for one. Find that single one. ...
- Single Number,Single Number II
Single Number Total Accepted: 103745 Total Submissions: 218647 Difficulty: Medium Given an array of ...
- leetcode 之 Single Number II
问题来源:Single Number II 问题描述:给定一个整数数组,除了一个整数出现一次之外,其余的每一个整数均出现三次,请找出这个出现一次的整数. 大家可能很熟悉另一个题目(Single Num ...
- 【leetcode78】Single Number II
题目描述: 给定一个数组,里面除了一个数字,其他的都出现三次.求出这个数字 原文描述: Given an array of integers, every element appears three ...
- leetcode 136. Single Number 、 137. Single Number II 、 260. Single Number III(剑指offer40 数组中只出现一次的数字)
136. Single Number 除了一个数字,其他数字都出现了两遍. 用亦或解决,亦或的特点:1.相同的数结果为0,不同的数结果为1 2.与自己亦或为0,与0亦或为原来的数 class Solu ...
- Leetcode 137 Single Number II 仅出现一次的数字
原题地址https://leetcode.com/problems/single-number-ii/ 题目描述Given an array of integers, every element ap ...
- 【LeetCode】137. Single Number II (3 solutions)
Single Number II Given an array of integers, every element appears threetimes except for one. Find t ...
- LeetCode 137. Single Number II(只出现一次的数字 II)
LeetCode 137. Single Number II(只出现一次的数字 II)
随机推荐
- web app开发中 iPhone、iPad默认按钮样式问题
webapp开发过程中,用html5+css3很方便,而且可以很方便的编译到Android ios等不同平台,但是ios需要单独处理一下,不然会出现一些想象不到的问题.下面就介绍一下各种问题的解决方法 ...
- 三【相关度 相似度查询与计算】相似度到大数据查找之Mysql 文章匹配的一些思路与提高查询速度
记录下,在上2回的数据基础之上,附带一个互信息(MI,Mutual Information)可以计算词之间的相关度 标准互信息 MI(X,Y)=log2p(x,y)/p(x)p(y) 值越大于0 则趋 ...
- C# 数据类型映射 (SQLite,MySQL,MSSQL,Oracle)
一.C# vs SQLite: C# SQLite 字段名 类型 库类型 GetFieldType(#) 转换 备注 F_BOOL bool BIT NOT NULL Boolean F_BOOL_N ...
- Ajax的概述与实现过程
一.ajax概述 1.Ajax是Asynchronous([ə'sɪŋkrənəs) JavaScript XML的简写,不是一门新技术,而是对现有技术的综合利用.这一技术能够向服务器请求额外数据而无 ...
- QT/C++ 智能指针
什么是智能指针? 为什么用智能指针? 还有哪些关于内存管理方面的知识点,需要注意的?
- From MSI to WiX, Part 1 - Required properties, by Alex Shevchuk
Following content is directly reprinted from From MSI to WiX, Part 1 - Required properties Author: A ...
- 在Linux系统下安装大于mysql5.5版本的数据库
linux下mysql 5.5的安装方法: 1.安装所需要系统库相关库文件 gcc等开发包,在安装linux系统的时候安装. 2.创建mysql安装目录 # mkdir -p /usr/lo ...
- angular中的orderBy过滤器使用
一 orderBy过滤器 AngularJS中orderBy进行排序,第一个参数可以有三种类型,分别为:function,string,array: 第一种:function,如果是func ...
- C语言中的程序终止函数
在C语言的标准库<stdlib.h>中提供了一些与正常或者不正常的程序终止有关的函数,下面分别对其进行简单介绍. 参考文献: [1] C和指针,P298,342 [2] C程序设计语言现代 ...
- ios中XPath的语法
在XML的读写中,我们知道有Xpath的语法 1.定位节点:(/)代表绝对的路径,代表起始地位置.(//)表示文件中所有符合模式的元素都会被选出来,即使是处于树中不同的层级也会被选出来 2.KissX ...