LeetCode136:只出现一次的数字与LeetCode137:只出现一次的数字ii
Leetcode136:
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
说明:
你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?
时间O(n),空间O(1)的算法实在没想到,满脑子里都是排序或者引入map。
看了下答案巧妙的运用了异或的性质,相同的数字异或为0,不同的数字异或异或为1的特点。
顺便纠正了下基础,异或运算在位上的,比如1异或3,答案不是1,而是2.因为异或是在001与011间的每一位进行,异或的结果是010,也就是2。
这样,对[a,a,c,b,c]这样的数组的每个数都进行^
a^a^c^b^c,配合结合律变为:
a^a^c^c^b
其中a^a^c^c=0
0^b=b
Leetcode137:
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现了三次。找出那个只出现了一次的元素。
说明:
你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | class Solution { public : int singleNumber(vector< int >& nums) { int result=0; int cnt=0; for ( int i=0;i<32;i++) { int tmp=0; //[-2,-2,1,1,-3,1,-3,-3,-4,-2] for ( int j=0;j<nums.size();j++) { tmp+=nums[j]&1; nums[j]=nums[j]>>1; } tmp=tmp%3; result=result|(tmp<<i); } return result; } }; |
从位的角度上来看,136题中,每一位的异或操作只是对进行二进制相加但不产生进位。
现在有三个相同的数,只要在每一位上,令三个相同的数进行某种运算后归0,即可将不同的数的那一位凸显出来。
因此考虑在每一位上进行三进制的相加,满了归0且不产生进位。
在32位上,所有数的某一位全部相加后对3取余,所得结果即是不同的数的对应位。
最后将每一位“或”起来即可。
另外关于负数的二进制位表示与右移:
负数的二进制表示并不是简单的将首尾改为1,比如-1的二进制表示实际上是1111....1(共32个)而不是1 000....1,不要想当然。
另外对负数进行右移时,符号位被丢弃后又会补一个1,比如-1,右移后并不会在首尾补0而是补1,因此无论右移多少次,一直为111....1,也即一直为-1。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 智能桌面机器人:用.NET IoT库控制舵机并多方法播放表情
· Linux glibc自带哈希表的用例及性能测试
· 深入理解 Mybatis 分库分表执行原理
· 如何打造一个高并发系统?
· .NET Core GC压缩(compact_phase)底层原理浅谈
· DeepSeek火爆全网,官网宕机?本地部署一个随便玩「LLM探索」
· 开发者新选择:用DeepSeek实现Cursor级智能编程的免费方案
· 【译】.NET 升级助手现在支持升级到集中式包管理
· 独立开发经验谈:如何通过 Docker 让潜在客户快速体验你的系统
· 并发编程 - 线程同步(二)