本题目摘自《Python程序员面试算法宝典》,我会每天做一道这本书上的题目,并分享出来,统一放在我博客内,收集在一个分类中。

【百度面试题】

难度系数:⭐⭐⭐

考察频率:⭐⭐⭐⭐

题目描述:数字1 ~ 1000放在含有1001个元素的数组中,其中只有唯一的一个元素重复,其他数字均只出现一次。设计一个算法,将重复元素找出来,要求每个数组元素只能访问一次。

进阶:在上面题目描述中,如果不使用辅助空间,能否设计一个算法实现?

方法一:空间换时间

首先分析题目所要达到的目标以及其中的限定条件。从题目中可以发现,本题的目标是在一个有且仅有一个元素重复的数组中找到这个唯一的重复元素,限定条件是每个数组元素只能访问一次。

在不考虑进阶条件的情况下,我们可以通过字典的key来进行去重,我们可以把数字当作key,出现的次数记作value

from collections import defaultdict

def find_elem(array):
dic = defaultdict(lambda : 0) # 构造一个缺省字典,当出现KeyError的时候压制,并创建键值对为key - 0
for elem in array:
if dic[elem] == 1: # 这一步如果dic中没有elem不会报错因为dic是defaultdict
return elem
dic[elem] += 1
return "can't find it" print(find_elem([1, 3, 4, 2, 5, 3])) # 3 # 如果defaultdict看不懂可以看下面使用get方法的版本 def find_elem(array):
dic = {} # 使用普通字典
for elem in array:
dic[elem] = dic.get(elem, 0) + 1 # get不到elem会返回0, 然后再+1,再创建 k - v 对
if dic[elem] == 2: # 重复的元素
return elem
return "can't find it"

这种方法很容易想到,时间复杂度为O(n),空间复杂度也是O(n),这种思想在工作中可以使用,比如一个项目急着上线,没有什么时间给你雕琢程序,那么我们可以考虑使用空间来换取程序运行的时间。

方法二:累加求和法

计算机技术与数学本身是一家,抛开计算机专业知识不提,这个问题可以回归成一个数学问题。数学问题的目标是在一个数字序列中寻找重复的那个数。题目描述是1 ~ 1000个数,有一个重复,那么我们把这1001个数加起来再减去 (1 + 2 + … + 1000)得到的就是重复的那个数了。

def find_it(array):
sum = 0
one_to_thousand = -1001
for i, v in enumerate(array, 1):
sum += v
one_to_thousand += i
return sum - one_to_thousand print(find_it([i for i in range(1, 1001)] + [56]))

分析:时间复杂度O(n), 空间复杂度O(1),但是计算也挺费时间的。 其实这里可以使用python的第三方库,科学计算库numpy进行并行计算,numpy.array.sum()

方法三:异或法

根据异或运算的性质可以直到,当相同元素异或时,运算结果为0,当相异元素异或时,运算结果非0,任何数字与数字0进行异或运算,其运算结果为该数。因为1001个数字是1 ~ 1000再加上一个大于0小于等于1000的数字,所以我们把这1001个数字和1到1000异或,最后会转变成0和重复的那个数字进行异或,得到的就是重复的数字。

例如数组(1, 3, 4, 2, 5, 3),进行运算:(1, 3, 4, 2, 5, 3)^ (1, 2, 3, 4, 5) = 1 ^ 1 ^ 2 ^ 2 ^ 3 ^ 3 ^ 4 ^ 4 ^ 5 ^ 5 ^ 3 = 0 ^ 3 = 3。

def find_it(array):
elem = 0
for i, v in enumerate(array):
elem ^= i ^ v
return elem print(find_it([1, 3, 4, 2, 5, 3]))

这种方法的时间复杂度是O(n), 没有申请额外的存储空间,进行位运算速度还算快。

方法四:数据映射法

数据的取值操作可以看作是一个特殊的函数f:D —> R, 定义域D为下标值 0 ~ 1000,值域为1 ~ 1000, 如果对任意一个数 i, 把f(i)叫做它的后继, i叫做f(i)的前驱。重复的那个数字有两个前驱,所以我们可以把每个数的前驱置为负数,当第二次遇到重复的数字时,它的前驱已经被置为负数了,这个就是重复的数值,返回即可。

# 数据影射法
def find_it(array):
p = 0
while array[p] >= 0:
p = array[p]
array[p] *= -1
return abs(array[p]) print(find_it([1, 2, 4, 2, 5, 3])) # 2
print(find_it([1, 3, 4, 2, 5, 3])) # 3

这个算法的时间复杂度是O(n),没有申请辅助的空间。但是这种方法修改了原本列表中的元素。



欢迎小伙伴们加入我创建的python交流群:625988679



python经典面试算法题4.1:如何找出数组中唯一的重复元素的更多相关文章

  1. python经典面试算法题1.4:如何对链表进行重新排序

    本题目摘自<Python程序员面试算法宝典>,我会每天做一道这本书上的题目,并分享出来,统一放在我博客内,收集在一个分类中. 1.4 对链表按照如下要求重新排序 [微软笔试题] 难度系数: ...

  2. python经典面试算法题1.3:如何计算两个单链表所代表的数之和

    本题目摘自<Python程序员面试算法宝典>,我会每天做一道这本书上的题目,并分享出来,统一放在我博客内,收集在一个分类中. 1.2 如何实现链表的逆序 [华为笔试题] 难度系数:⭐⭐⭐ ...

  3. python经典面试算法题1.2:如何从无序链表中移除重复项

    本题目摘自<Python程序员面试算法宝典>,我会每天做一道这本书上的题目,并分享出来,统一放在我博客内,收集在一个分类中. 1.2 如何实现链表的逆序 [蚂蚁金服面试题] 难度系数:⭐⭐ ...

  4. python经典面试算法题1.1:如何实现链表的逆序

    本题目摘自<Python程序员面试算法宝典>,我会每天做一道这本书上的题目,并分享出来,统一放在我博客内,收集在一个分类中. 1.1 如何实现链表的逆序 [腾讯笔试题] 难度系数:⭐⭐⭐ ...

  5. 一起来刷《剑指Offer》-- 题目一:找出数组中重复的数字(Python多种方法实现)

    数组中重复的数字 最近在复习算法和数据结构(基于Python实现),然后看了Python的各种"序列"--比如列表List.元组Tuple和字符串String,后期会写一篇博客介绍 ...

  6. 找出数组中出现次数超过一半的数,现在有一个数组,已知一个数出现的次数超过了一半,请用O(n)的复杂度的算法找出这个数

    找出数组中出现次数超过一半的数,现在有一个数组,已知一个数出现的次数超过了一半,请用O(n)的复杂度的算法找出这个数 #include<iostream>using namespace s ...

  7. python找出数组中第二大的数

    #!usr/bin/env python #encoding:utf-8 ''''' __Author__:沂水寒城 功能:找出数组中第2大的数字 ''' def find_Second_large_ ...

  8. C++经典面试算法题

    转自:http://blog.csdn.net/f_r_e_e_x/article/details/50770907 //1.实现strcpy. char* MyStrCpy( char *pDest ...

  9. 算法面试题(python)——如何找出数组中出现一次的数

    题目描述: 一个数组里,除了三个数是唯一出现的,其余的数都出现了偶数次,找出这三个数中任意一个.比如数组序列为[1,2,4,5,6,4,2],只有1.5.6这三个数字是唯一出现的,数字2.4均出现了偶 ...

随机推荐

  1. vue-cli脚手架项目本地阅览和在线阅览

    一.需求 开发环境:当然啦,前提是你要完整检测整个项目无错误的运行:npm run dev 后项目在本地预览问题没有问题 二.服务器本地阅览 生产环境:项目制作完成后需执行npm run build操 ...

  2. vim 的初始配置

    我是一个vim爱好者,项目开发过程中,大量地使用vim作为编辑工具. 今天刚开箱了一台新的 CentOS7, 现将Vim安装后的一些基本配置作一下记录. 使用配置模板 vim安装完之后,大多数配置都是 ...

  3. ZGC深入学习

    ZGC简介 本次调研目标选取的是jdk11(long-term support)下首次亮相的zgc. zgc介绍简单翻译了zgc main page:ZGC简介 另外参考hotspot garbage ...

  4. 微信小程序前端页面书写

    微信小程序前端页面书写 WXML(WeiXin Markup Language)是框架设计的一套标签语言,结合基础组件.事件系统,可以构建出页面的结构. 一.数据绑定 1. 普通写法 <view ...

  5. Microsoft Word 2019 mac破解版下载

    Microsoft Word 2019 Mac版是大名鼎鼎的Office办公软件组件之一,能帮助你进行文字排版,可方便的进行创作项目.作业.信件.博客.剧本.笔记.评论文章或简历. Microsoft ...

  6. socat的介绍与使用

    Socat 是 Linux 下的一个多功能的网络工具,名字来由是 「Socket CAT」.其功能与有瑞士军刀之称的 Netcat 类似,可以看做是 Netcat 的加强版. Socat 的主要特点就 ...

  7. 运用第一性原理探寻AI本质

    摘要:使用第一性原理探讨理解AI本质. 文章来源:宜信技术学院|宜信支付结算团队技术分享第二期-支付结算机器学习技术团队负责人 刘创 分享<AI与第一性原理> 分享者:宜信支付结算机器学习 ...

  8. SpringBoot 2.0整合阿里云OSS,实现动静分离架构

    前言 相信大部分开发者对下面这张架构图并不陌生吧,现在很多网站/应用都采用了动静分离的架构进行部署.博主的博客也不例外,主机采用的是阿里云的 ECS,使用 CDN 做静态内容分发,不过静态文件还是存储 ...

  9. Nginx基本属性配置详解

    1. Nginx服务的基本配置 1.1 用于调试进程和定位问题的配置项 是否以守护进程的方式运行nginx # 默认on daemon on|off; 是否以master/worker方式工作 # 默 ...

  10. php在哪里写代码?

    php在哪里写代码? php可以在PhpStorm中写代码. PhpStorm 是 JetBrains 公司开发的一款商业的 PHP 集成开发工具,旨在提高用户效率,可深刻理解用户的编码,提供智能代码 ...