题目描述
思路一:哈希表
若在没有时空间复杂度的情况下,一个简单的思路是直接使用哈希表记录数组中不同数字出现的次数:
class Solution:
def singleNumber(self, nums: List[int]) -> int:
hashtable=dict()
for i in nums:
if i in hashtable.keys():
hashtable[i]+=1
else:
hashtable[i]=1
for k in hashtable.keys():
if hashtable[k]==1:
return k
这一算法虽然是极其简单有效,但在时空复杂度上是糟糕的。(面试备选方案)
思路二:排序+查找
一个同样简单的思路是将数组进行排序,在将数组从小到大进行排序后,由于相同的数字总会在排序后共同出现,因而会被十分简单地区分出来:
class Solution:
def singleNumber(self, nums: List[int]) -> int:
def QuickSort(nums:List[int],left:int,right:int)->List[int]:
if left>=right:
return
l,r,key=left,right,nums[left]
while l<r:
while l<r and nums[r]>=key:
r-=1
nums[l]=nums[r]
while l<r and nums[l]<key:
l+=1
nums[r]=nums[l]
nums[l]=key
QuickSort(nums,left,l-1)
QuickSort(nums,l+1,right)
return nums
nums=QuickSort(nums,0,len(nums)-1)
flag=1
for i in range(1,len(nums)-1):
if nums[i]==nums[i-1]:
flag=0
else:
if flag:
return nums[i-1]
else:
flag=1
return nums[-1]
思路三:位运算
可以联想到,当数组中如果其他数字只出现两次,而只有一个数字出现一次时,我们可以采用对数组中所有的数字异或轻松得到问题的结果,更深层次地,我们思考这样可行的原因,由于位运算异或操作在位值相同时为0,不同时则为1,这可以转换为对每一位上二进制位相加模2取余,相同的两个数在这一操作过程中不会影响最终的结果,因而能取得最终的仅出现一次的数字。
那么迁移到这个问题上来,我们是否可以对二进制数字按位相加后模3取余即可得到那个唯一仅出现一次的数字呢?答案显然是可以的:
class Solution:
def singleNumber(self, nums: List[int]) -> int:
def Tripe(x,y):
tripebit=1
ans=0
while x and y:
ans+=((x%3+y%3)%3)*tripebit
tripebit*=3
x=x//3
y=y//3
ans+=(x+y)*tripebit
return ans
return functools.reduce(Tripe,nums)
思路四:有限状态机
这一思路的解法是在充分明白思路三前提后的算法优化。回顾思路三的位运算操作,我们实际上只是将数组中所有的数字按位相加后取余,那么我们是否可以不用把比特位显示的写出每一位的操作,而是把他们整体进行考虑,把数字按位累加的过程分成所有当前位组成的数字和所有进位组成的数字。那么这一过程可以理解为一种有限状态机,在每一位上,会有位加法运算后的当前位与进位,由于运算是针对模三取余的,因而共有三种状态:
那么用one表示所有的当前位组成的数字,two表示所有进位表示的组成的数字,则根据图示的状态跳转过程,我们可以写出如下的状态跳转规则:
if two == 0:
if n == 0:
one = one
if n == 1:
one = ~one
if two == 1:
one = 0
作者:jyd
链接:https://leetcode-cn.com/problems/shu-zu-zhong-shu-zi-chu-xian-de-ci-shu-ii-lcof/solution/mian-shi-ti-56-ii-shu-zu-zhong-shu-zi-chu-xian-d-4/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
if two == 0:
one = one ^ n
if two == 1:
one = 0
把上述规则整合如下:
one = one ^ n & ~two
two = two ^ n & ~one
进而我们有形成如下的状态转移机:
class Solution:
def singleNumber(self, nums: List[int]) -> int:
ones, twos = 0, 0
for num in nums:
ones = ones ^ num & ~twos
twos = twos ^ num & ~ones
return ones
作者:jyd
链接:https://leetcode-cn.com/problems/shu-zu-zhong-shu-zi-chu-xian-de-ci-shu-ii-lcof/solution/mian-shi-ti-56-ii-shu-zu-zhong-shu-zi-chu-xian-d-4/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。