本文属于算法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) operation popis 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:

  1. The order of the result is not important. So in the above example, [5, 3]is also correct.
  2. 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相关推荐

  1. 数据结构算法入门--链表

    2019 年第 76 篇文章,总第 100 篇文章 本文大约 3200 字,阅读大约需要 10 分钟 数据结构算法系列: 数据结构算法入门系列第三篇--链表,链表也是非常常见的数据结构,面试过程中也会 ...

  2. 遗传、退火算法入门(转载)

    优化算法入门系列文章目录(更新中): http://www.cnblogs.com/heaad/archive/2010/12/23/1914725.html 1. 模拟退火算法 2. 遗传算法 遗传 ...

  3. BP算法双向传_链式求导最缠绵(深度学习入门系列之八)

    摘要: 说到BP(Back Propagation)算法,人们通常强调的是反向传播,其实它是一个双向算法:正向传播输入信号,反向传播误差信息.接下来,你将看到的,可能是史上最为通俗易懂的BP图文讲解, ...

  4. (视频+图文)机器学习入门系列-第7章 KNN算法

    机器学习入门系列,黄海广老师主讲.本站将持续更新,ppt.代码.课后习题见文末. 本系列的目录 01.引言 02.回归 03.逻辑回归 04.朴素贝叶斯 05.机器学习实践 06.机器学习库Sciki ...

  5. BP算法双向传,链式求导最缠绵(深度学习入门系列之八)

    摘要: 说到BP(Back Propagation)算法,人们通常强调的是反向传播,其实它是一个双向算法:正向传播输入信号,反向传播误差信息.接下来,你将看到的,可能是史上最为通俗易懂的BP图文讲解, ...

  6. 区块链入门系列之共识算法

    区块链入门系列文章 区块链基本概念和名词解释 P2P 共识算法 梅克尔-帕特里夏树 从零开始搭建区块链 这里写自定义目录标题 区块链入门系列文章 前言 POW POS PBFT Raft 其他共识算法 ...

  7. CapsNet入门系列之三:囊间动态路由算法

    编者按:深度学习开创者之一.反向传播等神经网络经典算法的发明人Geoffrey Hinton思考了胶囊网络数十年之久,然而直到上一个月才发表论文正式提出胶囊网络.主要原因就是一直没找到训练胶囊网络的合 ...

  8. Spark入门系列(二)| 1小时学会RDD编程

    作者 | 梁云1991 转载自Python与算法之美(ID:Python_Ai_Road) 导读:本文为 Spark入门系列的第二篇文章,主要介绍 RDD 编程,实操性较强,感兴趣的同学可以动手实现一 ...

  9. xgboost 正则项_XGBoost入门系列第一讲

    Boosted Trees 介绍 XGBoost 是 "Extreme Gradient Boosting"的简称,其中"Gradient Boosting"来 ...

最新文章

  1. 基于 Ubuntu 系统安装 CUDA 和 cuDNN
  2. python 调用 C语言函数
  3. 排除网络故障课后习题参考答案
  4. 熊猫烧香是天才作品吗?
  5. CF1200D-White Lines【二维前缀和】
  6. 平台系统云服务器配置,01-云平台连接配置
  7. linux充电时熄屏时间,充电时玩手机会损害电池吗
  8. 费尔德曼的百吉饼实验:人类的诚实程度其实超出你的想象!
  9. 心大于物 ----论意识心灵与物理大脑的关系
  10. OpenStack_Swift源代码分析——Ring基本原理及一致性Hash算法
  11. ORACLE错误6650
  12. 【Python读csv文件】'gbk' codec can't decode byte 0xb3 in position 73: illegal multibyte sequence
  13. 收藏几个漂亮的login页面验证
  14. C语言——数据结构(线性,树形,图形结构等)
  15. 实验九 TCP 协议分析实验
  16. Radon变换实现对图像倾斜校正 matlab
  17. Mac更换JDK版本
  18. React 引用 ant 组件 使用 react-custom-scrollbars美化(隐藏)滚动条
  19. WARNING: The scripts f2py, f2py3 and f2py3.6 are installed in ‘/home/nano/.local/bin‘ which is not o
  20. Untiy AVpro

热门文章

  1. PDF如何添加墨绿背景
  2. gps与服务器协议,gps云服务器地址
  3. 甲骨文的历史之收购太阳公司
  4. Modbus扫描工具
  5. 《中国社会科学院公布2007年全国主要城市白领工资标准》
  6. 150512610_2_创伤后成长与人格特质问卷_229_229
  7. 搞定老外,这些英语句型一定要熟记!
  8. 第三章:数据解析---聚焦爬虫
  9. UI好看的王者荣耀战力查询助手微信小程序源码下载支持流量主
  10. 论文笔记:Dynamic Scene Deblurring Using Spatially Variant Recurrent Neural Networks