LeetCode 137. 只出现一次的数字 II

题目链接

原始博客地址(从CSDN迁来的,有对问题评论进行回答)

这题起初根本想不到.直到翻了leetcode.com的discuss.....然后我整个人都"awesome!!!!"地瞎叫了.

下面讲讲我学来的思路.


概述

这题本质上来讲,就是让我们做一个有限状态机(finite state machine)(瞎翻的).

首先

  • 一般看到这种题,我们第一反应是做状态记录,比如数字x出现了y次.然后从记录里查询出现了一次的数字.

  • 但是 现在我们的空间复杂度被限制成了O(1),不可能对所有的64位二进制表示的整数进行统计次数.

于是

  • 我们只能着眼于二进制上了.我们先将状态记录缩小到记录目标数字的每一个二进制上.

  • 那么这题就会变成: 遍历所有数,一个二进制位出现1的次数对3取余是否为1,若为1,那么我们目标数字的这一位也就是1. (具体见下例)

比如

  • [1,1,1,2] 他们转换成二进制就是[01,01,01,10],我们可以知道第一位(从右往左)的二进制总共出现了三次1,那么我们的目标结果在第一位就绝对不会是1,相对的第二位出现了一次1,那么我们的目标值在这一位就是1

实际上

  • 这题我们也可以写64个变量(不知道数据量范围多大或者32位也可以?)记录每位的二进制1出现的次数,然后每一个对三取余最后得出的64个1与0再组成一个整数...不过思路本质离不开这里.

  • 而且到这一步空间复杂度已经是O(1)了,毕竟一个定长数组.但是大佬就是不一样,非要用几个变量解决....

最后

  • 我们要运用逻辑门的想法设计一个计数器.计数到3就回归0.对于每一个二进制位,出现了多少次1我们可以用两个二进制表示(因为这题只需要记录%3),00表示出现0次,01表示出现1此,10表示出现2次.这样就记录了三个状态,(题目中是出现三次,其实对于x次,我们也可以同理描述).如下

补充

  • 建议此题可以补充一下逻辑代数相关知识,暂时不知道有什么好的文章,这里贴个百度百科.学习成本不高

介绍

a为高位,b为低位.两个一起表示一个两位二进制表示的数字(一个计数器)

计数器代表值 a b 目标出现次数
0 0 0 0
1 0 1 1
2 1 0 2
0 0 0 3
1 0 1 4
2 1 0 5
... ... ... ...

上面是我们计数器需要达成的目标,一个计数循环.学过数字电路的同学看到这里应该就知道怎么做了.

我们再进一步. 我们遍历数据,每来一个数据c(这里一个二进制)我们的a与b就要开始为c计数,那么有以下情况

a b c 结果a 结果b
0 0 0 0 0
0 1 0 0 1
1 0 0 1 0

上面比较容易明白,来的是0,那么我们不统计,原来a,b的统计结果不变

a b c 结果a 结果b
0 0 1 0 1
0 1 1 1 0
1 0 1 0 0

这里也比较容易明白,当来的是1,那么只要为其计数增加1就好.

接下来就是我们的重头戏了.开始设计逻辑门能让我们的计数器保持3个状态记录循环.

我们观察结果a,可以看到会使结果a=1的状态仅有 ( a为1 && b为0 && c为0 ) || (a为0 && b为1 && c为1),同理可以推出b的表达式.

故可得出公式结果a结果b的表达式:

: 结果a = (a & ~b & ~c) + (~a & b & c)

: 结果b = (~a & ~b & c) + (~a & b & ~c)

另外根据逻辑代数分配率公式也可以变成:

: 结果b = ~a & (~b & c + b & ~c) = ~a & (b^c) //二进制进位逻辑

再然后根据上图a,c,结果b 三者的关系写出结果a的逻辑

结果a = a & ~c & (~结果b) + ~a & c & (~结果b) = (~结果b) & (a^c)

然后对实际int型数据做以上处理,就可完成我们的目标.(实际上可以把int看成是在维护一个二进制组成的数组a[i],b[i],c[i],i表示第i位.我们每次位运算操相当于对每一个i所在的三个元素进行操作,也就变成了上述单独描述一个二进制位时的情况.))


/**

* 给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现了三次。找出那个只出现了一次的元素。

* 题目要求:你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?

*

* 思路有点像是数字电路设计一个计数器.此题的情况就是为每一位二进制进行计数,计数三次归零,那么最后没有归零的数就是出现一次的那个数.设计思路与逻辑门电路设计一样.

*

* @author jxwww

* @date 2018/8/30

*/

public class No137 {

    /**

    *  如上所推

    */

    public static int singleNumber(int[] nums) {

        int a = 0, b = 0;

        for (int c : nums) {

            int tempA = (~a & b & c) + (a & ~b & ~c);

            b = (~a & ~b & c) + (~a & b & ~c);

            a = tempA;

        }

        return b;

    }

/**

*  如上所推,你也可以写成这样

*/

public int singleNumber(int[] nums) {

        int a=0,b=0;

        for (int c : nums) {

            b = b ^ c & ~ a;

            a = a ^ c & ~ b;

        }

        return b;

    }

    public static void main(String[] args) {

        int[] nums = new int[]{0, 1, 0, 1, 0, 1, 99};

        System.out.println(singleNumber(nums));

    }

}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,992评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,212评论 3 388
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,535评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,197评论 1 287
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,310评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,383评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,409评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,191评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,621评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,910评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,084评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,763评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,403评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,083评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,318评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,946评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,967评论 2 351