算法入门系列:singleNumber
本文属于算法leetcode系列。
singleNumber1: easy 模式。
Given a non-empty 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?
Example 1:
Input: [2,2,1]
Output: 1
Example 2:
Input: [4,1,2,1,2]
Output: 4
60%的通过率。
有通常的双重for循环处理的。还可以用hashmap处理。
class Solution {public int singleNumber(int[] nums) {Map<Integer,Integer> map = new HashMap();for(int i=0;i<nums.length;i++){if(map.containsKey(nums[i])){map.remove(nums[i]);}else{map.put(nums[i], nums[i]);} }Integer tmp = map.values().iterator().next();return tmp;}
}
Runtime: 7 ms, faster than 34.35% of Java online submissions for Single Number.
Memory Usage: 39.7 MB, less than 96.60% of Java online submissions forSingle Number.
Complexity Analysis
Time complexity : O(n \cdot 1) = O(n)O(n⋅1)=O(n). Time complexity of
for
loop is O(n)O(n). Time complexity of hash table(dictionary in python) operationpop
is O(1)O(1).Space complexity : O(n)O(n). The space required by hash\_tablehash_table is equal to the number of elements in \text{nums}nums.
我想到就这样,看到有个复杂度类似的。
上面表了是方法3 math
用set保存数字,2∗(a+b+c)−(a+a+b+b+c)=c,
看看方法4 bit 操作吧。也就是最优解:
class Solution {public int singleNumber(int[] nums) {int num =0;for(int i=0;i<nums.length;i++){num ^= nums[i];}return num;}
}
Runtime: 0 ms, faster than 100.00% of Java online submissions for Single Number.
Memory Usage: 38.2 MB, less than 99.68% of Java online submissions forSingle Number.
用到了异或 XOR的原理:x^x =0,x^0=x.
用一个数记录每个bit出现的次数,如果一个bit出现两次就归0.跟前面的hashmap去删除原理一样。
这里就是使用^ 操作。
Complexity Analysis
Time complexity : O(n)O(n). We only iterate through \text{nums}nums, so the time complexity is the number of elements in \text{nums}nums.
Space complexity : O(1)O(1).
singleNumber II: Medium模式
Given a non-empty 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?
Example 1:
Input: [2,2,3,2]
Output: 3
Example 2:
Input: [0,1,0,1,0,1,99]
Output: 99
从2个重复,变成三个重复。本质上还是要计数。
先看下稍微改动的hahsmap版本。
class Solution {public int singleNumber(int[] nums) {Map<Integer,Integer> map = new HashMap();for(int i=0;i<nums.length;i++){if(map.containsKey(nums[i])){int tmp = map.get(nums[i]);if(tmp ==2){map.remove(nums[i]);}else{map.put(nums[i], 2);}}else{map.put(nums[i], 1);} }Integer res = map.keySet().iterator().next();return res;}
}
Runtime: 5 ms, faster than 28.01% of Java online submissions for Single Number II.
Memory Usage: 36.8 MB, less than 99.28% of Java online submissions forSingle Number II.
这种速度就是太慢了。
怎么用上原来的bit操作呢?上题 Single Number 用到了二进制中异或的运算特性,这题给出的元素数目为3*n + 1
,因此我们很自然地想到如果有种运算能满足3进制运算就好了。当然有大神用1位跟2位的分别记录来模拟3进制。
以下是原地址:https://www.nowcoder.com/questionTerminal/1097ca585245418ea2efd0e8b4d9eb7a
真看不懂。贴一下瞻仰下。
链接:https://www.nowcoder.com/questionTerminal/1097ca585245418ea2efd0e8b4d9eb7a
来源:牛客网public int singleNumber(int[] A) {int ones = 0;//记录只出现过1次的bitsint twos = 0;//记录只出现过2次的bitsint threes;for(int i = 0; i < A.length; i++){int t = A[i];twos |= ones&t;//要在更新ones前面更新twosones ^= t;threes = ones&twos;//ones和twos中都为1即出现了3次ones &= ~threes;//抹去出现了3次的bitstwos &= ~threes;}return ones; }
相比而言:找规律的更容易理解些:
- 对于三个相同的数来说,其相加的和必然是3的倍数。
- 相加结果二进制位上的每一位也能被3整除(二进制数每一位相加必为3或0,不考虑进位)
- 因此我们只需要一个和
int
类型相同大小的数组记录每一位累加的结果即可(若为3的倍数,所求数的该二进制位对3取余为0,否则为1。当结果为1的时候,也就是这个位上出现了只出现一次的数字)
再看代码:
public static int singleNumber(int[] nums) {int result=0;for(int i=0;i<32;++i){int bits=0;for(int j=0;j<nums.length;++j){System.out.println("j="+j+"nums[j]="+nums[j]+":binary:"+Integer.toBinaryString(nums[j]));int tmp = (nums[j]>>i)&1;System.out.println("num["+j+"]="+nums[j]+":i="+i+":tmp="+tmp);bits+= tmp;//依次获取元素的每一位,并将数组元素相同位相加 }//取余得到第i位上的数字,更新resultresult|=(bits%3)<<i;System.out.println("result="+result+":i="+i);}return result;}
核心代码就是相同位数求和,用到了右移及截取1位的操作。
bits+= (nums[j]>>i)&1;
后面每位的结果都按照之前分析的对3取余,判断是否本位有出现一次的数字,再吧这结果用或操作恢复成对应的数字。
result|=(bits%3)<<i;
为了方便理解,我打印了中间变量:这里以[2,2,3,2]举例
j=0nums[j]=2:binary:10
num[0]=2:i=0:tmp=0
j=1nums[j]=2:binary:10
num[1]=2:i=0:tmp=0
j=2nums[j]=3:binary:11
num[2]=3:i=0:tmp=1
j=3nums[j]=2:binary:10
num[3]=2:i=0:tmp=0
result=1:i=0
j=0nums[j]=2:binary:10
num[0]=2:i=1:tmp=1
j=1nums[j]=2:binary:10
num[1]=2:i=1:tmp=1
j=2nums[j]=3:binary:11
num[2]=3:i=1:tmp=1
j=3nums[j]=2:binary:10
num[3]=2:i=1:tmp=1
result=3:i=1
j=0nums[j]=2:binary:10
num[0]=2:i=2:tmp=0
j=1nums[j]=2:binary:10
num[1]=2:i=2:tmp=0
j=2nums[j]=3:binary:11
num[2]=3:i=2:tmp=0
j=3nums[j]=2:binary:10
num[3]=2:i=2:tmp=0
result=3:i=2
j=0nums[j]=2:binary:10
num[0]=2:i=3:tmp=0
j=1nums[j]=2:binary:10
num[1]=2:i=3:tmp=0
j=2nums[j]=3:binary:11
num[2]=3:i=3:tmp=0
j=3nums[j]=2:binary:10
num[3]=2:i=3:tmp=0
result=3:i=3
。。。
j=0nums[j]=2:binary:10
num[0]=2:i=31:tmp=0
j=1nums[j]=2:binary:10
num[1]=2:i=31:tmp=0
j=2nums[j]=3:binary:11
num[2]=3:i=31:tmp=0
j=3nums[j]=2:binary:10
num[3]=2:i=31:tmp=0
result=3:i=31
3
再看结果:
Runtime: 1 ms, faster than 72.94% of Java online submissions for Single Number II.
Memory Usage: 37.1 MB, less than 99.17% of Java online submissions forSingle Number II.
比原来快多了,当然还不是最优解。
真的,如果对于位操作不熟悉,看代码是很比较晦涩的,得自己先画出一串二进制先翻译下。对于第二种方式,虽然我在上一题的基础上想到位操作,还是写不出来。弱爆了。
3 SinglenumberIII Medium 模式
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.
Example:
Input:[1,2,1,3,2,5]
Output:[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?
Accepted 111,425 Submissions 193,252
之前那种hashmap模式不再重复了。
Runtime: 4 ms, faster than 31.92% of Java online submissions for Single Number III.
Memory Usage: 38.3 MB, less than 98.90% of Java online submissions forSingle Number III.
再看位操作。
这跟number1 不一样,异或完结果剩余两个数,假设是x1,x2,即 x1^x2.
可是咋区分啊?没招了。真实感受到能力有限。
看看大神的办法吧。具体方法则是利用了x1 ^
x2不为0的特性,如果 x1^x2不为0,那么 x1^x2的结果必然存在某一二进制位不为0(即为1),我们将最低位的1提取出来.因为是异或的结果为1,x1 与x2必然在此位不相等。我们以此分组,又因为其他的数据成对出现,必然会抵消掉。这样就分别剩下x1,x2.
class Solution {public int[] singleNumber(int[] nums) {int[] result=new int[2];int num =0;for(int i=0;i<nums.length;i++){num ^= nums[i];}int index =0;for(int i=0;i<32;i++){int tmp = (num>>i)&1;if(tmp==1){index =i;break;}}for(int j=0;j<nums.length;j++){ if((nums[j]&(1<<index))==0 ){result[0] ^= nums[j];}else{result[1] ^= nums[j];} }return result;}
}
Runtime: 1 ms, faster than 99.74% of Java online submissions for Single Number III.
Memory Usage: 38.2 MB, less than 98.90% of Java online submissions forSingle Number III.
两次遍历数组,时间复杂度 O(n)+O(n).
算法入门系列:singleNumber相关推荐
- 数据结构算法入门--链表
2019 年第 76 篇文章,总第 100 篇文章 本文大约 3200 字,阅读大约需要 10 分钟 数据结构算法系列: 数据结构算法入门系列第三篇--链表,链表也是非常常见的数据结构,面试过程中也会 ...
- 遗传、退火算法入门(转载)
优化算法入门系列文章目录(更新中): http://www.cnblogs.com/heaad/archive/2010/12/23/1914725.html 1. 模拟退火算法 2. 遗传算法 遗传 ...
- BP算法双向传_链式求导最缠绵(深度学习入门系列之八)
摘要: 说到BP(Back Propagation)算法,人们通常强调的是反向传播,其实它是一个双向算法:正向传播输入信号,反向传播误差信息.接下来,你将看到的,可能是史上最为通俗易懂的BP图文讲解, ...
- (视频+图文)机器学习入门系列-第7章 KNN算法
机器学习入门系列,黄海广老师主讲.本站将持续更新,ppt.代码.课后习题见文末. 本系列的目录 01.引言 02.回归 03.逻辑回归 04.朴素贝叶斯 05.机器学习实践 06.机器学习库Sciki ...
- BP算法双向传,链式求导最缠绵(深度学习入门系列之八)
摘要: 说到BP(Back Propagation)算法,人们通常强调的是反向传播,其实它是一个双向算法:正向传播输入信号,反向传播误差信息.接下来,你将看到的,可能是史上最为通俗易懂的BP图文讲解, ...
- 区块链入门系列之共识算法
区块链入门系列文章 区块链基本概念和名词解释 P2P 共识算法 梅克尔-帕特里夏树 从零开始搭建区块链 这里写自定义目录标题 区块链入门系列文章 前言 POW POS PBFT Raft 其他共识算法 ...
- CapsNet入门系列之三:囊间动态路由算法
编者按:深度学习开创者之一.反向传播等神经网络经典算法的发明人Geoffrey Hinton思考了胶囊网络数十年之久,然而直到上一个月才发表论文正式提出胶囊网络.主要原因就是一直没找到训练胶囊网络的合 ...
- Spark入门系列(二)| 1小时学会RDD编程
作者 | 梁云1991 转载自Python与算法之美(ID:Python_Ai_Road) 导读:本文为 Spark入门系列的第二篇文章,主要介绍 RDD 编程,实操性较强,感兴趣的同学可以动手实现一 ...
- xgboost 正则项_XGBoost入门系列第一讲
Boosted Trees 介绍 XGBoost 是 "Extreme Gradient Boosting"的简称,其中"Gradient Boosting"来 ...
最新文章
- 基于 Ubuntu 系统安装 CUDA 和 cuDNN
- python 调用 C语言函数
- 排除网络故障课后习题参考答案
- 熊猫烧香是天才作品吗?
- CF1200D-White Lines【二维前缀和】
- 平台系统云服务器配置,01-云平台连接配置
- linux充电时熄屏时间,充电时玩手机会损害电池吗
- 费尔德曼的百吉饼实验:人类的诚实程度其实超出你的想象!
- 心大于物 ----论意识心灵与物理大脑的关系
- OpenStack_Swift源代码分析——Ring基本原理及一致性Hash算法
- ORACLE错误6650
- 【Python读csv文件】'gbk' codec can't decode byte 0xb3 in position 73: illegal multibyte sequence
- 收藏几个漂亮的login页面验证
- C语言——数据结构(线性,树形,图形结构等)
- 实验九 TCP 协议分析实验
- Radon变换实现对图像倾斜校正 matlab
- Mac更换JDK版本
- React 引用 ant 组件 使用 react-custom-scrollbars美化(隐藏)滚动条
- WARNING: The scripts f2py, f2py3 and f2py3.6 are installed in ‘/home/nano/.local/bin‘ which is not o
- Untiy AVpro