牛客网在线编程专题《剑指offer

阅读: 评论:0

牛客网在线编程专题《剑指offer

牛客网在线编程专题《剑指offer

我的个人微信公众号:Microstrong

微信公众号ID:MicrostrongAI

微信公众号介绍:Microstrong(小强)同学主要研究机器学习、深度学习、计算机视觉、智能对话系统相关内容,分享在学习过程中的读书笔记!期待您的关注,欢迎一起学习交流进步!

知乎主页:

Github:

个人博客:

 题目链接:

=13&tqId=11193&tPage=2&rp=2&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking

题目描述:

 解题思路:

(1)以空间复杂度换时间复杂度

空间复杂度,时间复杂度。

已经AC的代码:

# -*- coding:utf-8 -*-
class Solution:# 返回[a,b] 其中ab是出现一次的两个数字def FindNumsAppearOnce(self, array):# write code herenum_dic = {}result_list = []for item in array:if item in num_dic.keys():num_dic[item] = num_dic[item] + 1else:num_dic[item] = 1for item, count in num_dic.items():if count == 1:result_list.append(item)return result_listif __name__ == "__main__":input_array = [2, 4, 3, 6, 3, 2, 5, 5]sol = Solution()print(sol.FindNumsAppearOnce(input_array))

(2)利用Python中unt()函数,时间复杂度为

# -*- coding:utf-8 -*-
class Solution:# 返回[a,b] 其中ab是出现一次的两个数字def FindNumsAppearOnce(self, array):# write code hereresult_list = []for item in array:count = unt(item)if count == 1:result_list.append(item)return result_list

(3)运用异或思想,时间复杂度为,空间复杂度为

异或概念:如果a、b两个值不相同,则异或结果为1。如果a、b两个值相同,异或结果为0。

        这是一个比较难的题目, 很少有人能在面试的时候不需要提示一下子想到最好的解决办法。一般当应聘者想了几分钟后还没有思路, 面试官会给出一些提示。面试官很有可能会说: 你可以先考虑这个数组中只有一个数字只出现一次, 其他的都出现了两次, 怎么找出这个数字?

        这两个题目都在强调一个(或两个〉数字只出现一次, 其他的出现两次。 这有什么意义呢?我们想到异或运算的一个性质:任何一个数字异或它自己都等于0。也就是说,如果我们从头到尾依次异或数组中的每一个数字, 那么最终的结果刚好是那个只出现一次的数字, 因为那些成对出现两次的数字全部在异或中抵消了。

        想明白怎么解决这个简单问题之后, 我们再回到原始的问题, 看看能不能运用相同的思路。 我们试着把原数组分成两个子数组, 使得每个子数组包含一个只出现一次的数字, 而其他数字都成对出现两次。 如果能够这样拆分成两个数组, 我们就可以按照前面的办法分别找出两个只出现一次的数字了。

         我们还是从头到尾依次异或数组中的每一个数字, 那么最终得到的结果就是两个只出现一次的数字的异或结果。 因为其他数字都出现了两次,在异或中全部抵消了。由于这两个数字肯定不一样, 那么异或的结果肯定不为0,也就是说在这个结果数字的二进制表示中至少就有一位为1。我们在结果数字中找到第一个为1 的位的位置, 记为第n位。 现在我们以第n位是不是1为标准把原数组中的数字分成两个子数组,第一个子数组中每个数字的第n位都是1,而第二个子数组中每个数字的第n位都是0。 由于我们分组的标准是数字中的某一位是 1 还是 0,那么出现了两次的数字肯定被分配到同一个子数组。 因为两个相同的数字的任意一 位都是相同的,我们不可能把两个相同的数字分配到两个子数组中去, 于是我们已经把原数组分成了两个子数组,每个子数组都包含一个只出现一次的数字,而其他数字都出现了两次。我们已经知道如何在数组中找出唯一一个只出现一次数字,因此到此为止所有的问题都已经解决了。

        举个例子,假设输入数组{ 2, 4, 3, 6, 3, 2, 5, 5}。 当我们依次对数组中的每一个数字做异或运算之后, 得到的结果用二进制表示是 0010。 异或得到结果中的倒数第二位是1,于是我们根据数字的倒数第二位是不是1分为两个数组。第一个子数组{2, 3, 6, 3, 2}中所有数字的倒数第二位都是1,而第二个子数组{4, 5, 5}中所有数字的倒数第二位都是0。接下来只要分别对这两个子数组求异或,就能找出第一个子数组中只出现一次的数字是 6,而第二个子数组中只出现一次的数字是4。

        想清楚整个过程之后再写代码就不难了。 下面是已经AC的代码:

# -*- coding:utf-8 -*-
class Solution:def FindNumsAppearOnce(self, array):# write code hereif array == None or len(array) < 2:return []# 对数据进行异或运算resultExclusiveOR = 0for i in array:resultExclusiveOR ^= i# 在异或结果中找出从右向左第一个为1的索引indexOf1 = self.FindFirstBitIs1(resultExclusiveOR)num1 = 0num2 = 0for j in array:if self.IsBit1(j, indexOf1):num1 ^= jelse:num2 ^= jreturn [num1, num2]def FindFirstBitIs1(self, num):indexBit = 0while num & 1 == 0:num = num >> 1indexBit += 1return indexBitdef IsBit1(self, num, indexBit):num = num >> indexBitreturn (num & 1)if __name__ == "__main__":input_array = [2, 4, 3, 6, 3, 2, 5, 5]sol = Solution()print(sol.FindNumsAppearOnce(input_array))

Reference:

【1】剑指Offer,何海涛著。

【2】剑指offer-数组中只出现过一次的数字-Java版,地址:=search&seid=17735582839041767037     

本文发布于:2024-01-27 18:08:35,感谢您对本站的认可!

本文链接:https://www.4u4v.net/it/17063501151816.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:在线   剑指   专题   牛客网   offer
留言与评论(共有 0 条评论)
   
验证码:

Copyright ©2019-2022 Comsenz Inc.Powered by ©

网站地图1 网站地图2 网站地图3 网站地图4 网站地图5 网站地图6 网站地图7 网站地图8 网站地图9 网站地图10 网站地图11 网站地图12 网站地图13 网站地图14 网站地图15 网站地图16 网站地图17 网站地图18 网站地图19 网站地图20 网站地图21 网站地图22/a> 网站地图23