leetcode每日一道(13)神仙思路!找出只出现一次的数字!(其余数字都出现两次、三次)

news/2024/7/24 5:29:45 标签: LeetCode, 找出数字, 只出现一次, 出现两次

文章目录

  • 1. 其余数字出现两次——小试牛刀
  • 2. 其余数字出现三次——神仙解法
  • 3. 思路
  • 代码

1. 其余数字出现两次——小试牛刀

题目描述
现在有一个整数类型的数组,数组中素只有一个元素只出现一次,其余的元素都出现两次
注意:
你需要给出一个线性时间复杂度的算法,你能在不使用额外内存空间的情况下解决这个问题么?

Given an 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?

2. 其余数字出现三次——神仙解法

题目描述
现在有一个整数类型的数组,数组中只有一个元素只出现一次,其余元素都出现三次。
注意:
你需要给出一个线性时间复杂度的算法,你能在不使用额外内存空间的情况下解决这个问题么?

3. 思路

来自牛客的大神的思路,当然这道题为了速度是必须要用位运算的,这道题本质是什么呢?
对于题1来说,其实是不难的,假设所有的数据都是成对出现的,那么所有的数据进行异或之后,一定是归零的,那么既然有一个多余的数字,那么所有的数字进行异或之后,异或得到的结果就是那个落单的数字!
三个数字重复的就稍微麻烦了,在剑指offer上提供的思路是三个数字各个位上之和肯定是能够被3整除的,只需要检验每个位上的和能否被3整除,能的话,结果在这位上的数字就是0,而不能的话,结果在这位上的数字就是1。那这个思路不仅涉及到位运算,还涉及到四则运算,个人觉得比较混乱。
而在牛客上的大神提出的一个三进制思路令人拍案叫绝。
考虑如下,三进制情况下,我们用变量ones来存储所有数字加和之后,位为1的情况;twos用来存储哪些位数字是2,threes则表示哪些位上加起来已经是3了,这个变量有什么用呢?threes是由ones和twos得来, 当然是在目前更新的情况下,反向置零ones和twos相应的位,然后threes不用保存。
可能我说得不清楚,没有大佬理解透彻,我就引用一下大佬的原话:

链接:https://www.nowcoder.com/questionTerminal/1097ca585245418ea2efd0e8b4d9eb7a?f=discussion
来源:牛客网
Single Number的本质,就是用一个数记录每个bit出现的次数,如果一个bit出现两次就归0,这种运算采用二进制底下的位操作^是很自然的。Single Number II中,如果能定义三进制底下的某种位操作,也可以达到相同的效果,Single Number II中想要记录每个bit出现的次数,一个数搞不定就加两个数,用ones来记录只出现过一次的bits,用twos来记录只出现过两次的bits,ones&twos实际上就记录了出现过三次的bits,这时候我们来模拟进行出现3次就抵消为0的操作,抹去ones和twos中都为1的bits。

举个例子吧:
ones = 1 0 1 0
twos = 0 1 0 0
这时进来一个新数t=6,它的二进制是 0 1 1 0
想象一下,它进来之后,ones和twos是不是就会变了,这里要先更新twos,容易得twos第三位(从左到右)会因为ones和t 变成1,其他位保持,更新为0 1 1 0,然后ones会更新为 1 1 0 0 ,threes当然就是ones和twos位都位1的位置被置一,更新为0 1 0 0,既然threes被更新了,那么ones和twos对应位就应该被抹去了。ones:1 0 0 0 ,twos:0 0 1 0。然后继续等待下一个新数 t 。理解到了吗,这么清晰,还不懂的话,那你就来打死我。
下面上代码;

代码

class Solution {
public:
    int singleNumber(int A[], int n) {
        int ones = 0;
        int twos = 0;
        int threes;
        for (int i=0; i<n;i++){
            int t = A[i];
            twos |= ones&t;
            ones ^= t;
            threes = ones & twos; //默认threes是0;
            ones &= ~threes;
            twos &= ~threes;
        }
        return ones;
    }
};

就是这么简洁,举重若轻,至于其中的先用顺序,比如为什么要先更新twos,聪明的你,很容易想明白!!


http://www.niftyadmin.cn/n/880067.html

相关文章

leetcode每日一道(14)按评分给小朋友分糖果

题目描述 有N个小朋友站在一排&#xff0c;每个小朋友都有一个评分 你现在要按以下的规则给孩子们分糖果&#xff1a; 每个小朋友至少要分得一颗糖果 分数高的小朋友要他比旁边得分低的小朋友分得的糖果多 你最少要分发多少颗糖果&#xff1f; 思路 这样一道题有点意思&#x…

微软解析新Edge浏览器的多进程体系结构

微信搜索【前端全栈开发者】关注这个脱发、摆摊、卖货、持续学习的程序员&#xff0c;第一时间阅读最新文章&#xff0c;会优先两天发表新文章。关注即可大礼包&#xff0c;准能为你节省不少钱&#xff01; 今天的浏览器更像是操作系统&#xff0c;而不是文档查看器。用户在浏览…

如何在WebStorm中获得对数据库工具和SQL的支持

微信搜索【前端全栈开发者】关注这个脱发、摆摊、卖货、持续学习的程序员&#xff0c;第一时间阅读最新文章&#xff0c;会优先两天发表新文章。关注即可大礼包&#xff0c;准能为你节省不少钱&#xff01; 你可能已经知道&#xff0c;其他JetBrains IDE&#xff08;例如PhpSto…

在Vue Vite应用程序中实现暗/亮模式

在本文中&#xff0c;我将在不使用任何库的情况下将dark\Light模式功能实现到我们的Vue Vite应用程序中。 我们将首先创建一个简单的Vite应用程序&#xff0c;然后为我们的应用程序设置一个简单的用户界面。在创建我们的Vue应用程序之前&#xff0c;我想提到WrapPixel提供的一…

leetcode每日一道(15)环形路上加油站起点问题,绝妙思路

题目描述 环形路上有n个加油站&#xff0c;第i个加油站的汽油量是gas[i]. 你有一辆车&#xff0c;车的油箱可以无限装汽油。从加油站i走到下一个加油站&#xff08;i1&#xff09;花费的油量是cost[i]&#xff0c;你从一个加油站出发&#xff0c;刚开始的时候油箱里面没有汽油。…

cURL简介:高级程序员都在用的工具

微信搜索【前端全栈开发者】关注这个脱发、摆摊、卖货、持续学习的程序员&#xff0c;第一时间阅读最新文章&#xff0c;会优先两天发表新文章。关注即可大礼包&#xff0c;准能为你节省不少钱&#xff01; 在本教程中&#xff0c;我们介绍cURL的基本选项&#xff0c;并通过示例…

leetcode每日一道(16)复制一个无向图,每个节点都包含一个标签和它的邻居列表

题目描述 本题要求复制一个无向图&#xff0c;图中每个节点都包含一个标签和它的邻居列表 我们无向图用以下的方法序列化&#xff1a; 节点的标签是互不相同的&#xff0c; 我们使用“#”作为节点之间的分隔符&#xff0c;使用“,”作为节点标签和节点的节点邻居的分隔符。 例如…

Google搜索的10个小技巧,部分适用于百度

微信搜索【前端全栈开发者】关注这个脱发、摆摊、卖货、持续学习的程序员&#xff0c;第一时间阅读最新文章&#xff0c;会优先两天发表新文章。关注即可大礼包&#xff0c;准能为你节省不少钱&#xff01; 这些出色的提示和技巧可像专业人士一样使用Google。 我们通常会在需要…