原题是:
Given an array of integers where 1 ≤ a[i] ≤ n (n = size of array), some elements appear twice and others appear once.
Find all the elements of [1, n] inclusive that do not appear in this array.
Could you do it without extra space and in O(n) runtime? You may assume the returned list does not count as extra space.
Example:
Input:
[4,3,2,7,8,2,3,1]
Output:
[5,6]
思路1:
是把输入数组排序,遍历输入数组,如果这个数和前一个不一样,就去[1,2,,...n]数组总删除这个数。
方法可行,但是因为要排序,所以超时。
思路2:
利用Python list与set的互相转换
代码是:
class Solution(object):
def findDisappearedNumbers(self, nums):
"""
:type nums: List[int]
:rtype: List[int]
"""
x = list(range(1,len(nums)+1))
return list(set(x).difference(set(nums)))
别人的代码:
将输入数组中出现的数,去[1....n]数组中删掉,删掉的数用0占位,以保证序号。
删完后,把所有的0去掉,剩下的就是输入数组所缺的数。
学到的知识点:
1.python 中list 与set的互相转换
在python中,数组可以用list来表示。如果有两个数组,分别要求交集,并集与差集,怎么实现比较方便呢?
def diff(listA,listB):
#求交集的两种方式
retA = [i for i in listA if i in listB]
retB = list(set(listA).intersection(set(listB)))
print "retA is: ",retA
print "retB is: ",retB
#求并集
retC = list(set(listA).union(set(listB)))
print "retC1 is: ",retC
#求差集,在B中但不在A中
retD = list(set(listB).difference(set(listA)))
print "retD is: ",retD
retE = [i for i in listB if i not in listA]
print "retE is: ",retE
def main():
listA = [1,2,3,4,5]
listB = [3,4,5,6,7]
diff(listA,listB)
if __name__ == '__main__':
main()
运行结果是:
retA is: [3, 4, 5]
retB is: [3, 4, 5]
retC1 is: [1, 2, 3, 4, 5, 6, 7]
retD is: [6, 7]
retE is: [6, 7]
结合代码来看,大体上是两种思路:
1.使用列表解析式。列表解析式一般来说比循环更快,而且更pythonic显得更牛逼。
2.将list转成set以后,使用set的各种方法去处理。
2.去掉list里的重复元素
二维的list不能转换为set
3.list列表增删改查合并排序
# Auther: Aaron Fan
names = ["aaron", "alex", "james", "meihengfan"]
names2 = [1,2,3,4,5]
print(names)
#查
#print(names) #列出列表的内容
print(names[3]) #访问列表中第4个值
print(names[1:3]) #访问列表中从第2个到第3个的值
print(names[-1]) #访问列表中的最后一个值
print(names[:-2]) #访问列表中的所有值,但是把倒数第二个及后面的所有值都去掉
print(names[-3:]) #访问列表中倒数第一个到倒数第三个的值
print(names[0],names[3]) #注意取多个值的时候,不能直接把下标写到一起,需要按照这种方式写
print(names[::2]) #打印列表,但是以2为步长,就是跳着切,也可以根据需求把这个步长给改了
print(names.index("james")) #查找列表中james这个元素的下标
print(len(names)) #确定列表的长度
#增
names.append("jack") #在列表末尾插入一个元素
names.insert(1,"fanheng") #把fanheng插入到第二个位置那里
#改
names[2] = "liming" #把第三个位置的元素改成liming
#删
names.remove("liming") #把元素liming从列表中删除
del names[2] #把第三个元素删除,必须知道元素的索引
#del names #直接删除列表
names.pop() #默认删除列表末尾的元素,当然也可以直接指定元素的下标去弹出一个指定的元素,并让你等够接着使用它
#每当你使用pop时,被弹出的元素就不再在列表中了。
#pop把一个元素从列表中弹出来了,被弹出来的值,可以直接赋给其它变量使用,比如:
popend_name = names.pop()
print(popend_name)
#names.clear() #清空列表,危险操作,请慎用
#其它操作
#names.reverse() #把列表反转,就是把原有顺序完全反过来了
#排序
#names.sort() #把列表永久性的排序
print(sorted(names)) #对列表进行临时性的排序
#合并列表
names.extend(names2) #把names2的东西合并到names里面
print(names)
4.切片操作
对这种经常取指定索引范围的操作,用循环十分繁琐,因此,Python提供了切片(Slice)操作符,能大大简化这种操作。
L = ['Michael', 'Sarah', 'Tracy', 'Bob', 'Jack']
对应上面的问题,取前3个元素,用一行代码就可以完成切片:
L[0:3]
['Michael', 'Sarah', 'Tracy']
L[0:3]表示,从索引0开始取,直到索引3为止,但不包括索引3。即索引0,1,2,正好是3个元素。
如果第一个索引是0,还可以省略:
L[:3]
['Michael', 'Sarah', 'Tracy']
也可以从索引1开始,取出2个元素出来:
L[1:3]
['Sarah', 'Tracy']
类似的,既然Python支持L[-1]取倒数第一个元素,那么它同样支持倒数切片,试试:
L[-2:]
['Bob', 'Jack']
L[-2:-1]
['Bob']
记住倒数第一个元素的索引是-1。
切片操作十分有用。我们先创建一个0-99的数列:
L = range(100)
L
[0, 1, 2, 3, ..., 99]
可以通过切片轻松取出某一段数列。比如前10个数:
L[:10]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
后10个数:
L[-10:]
[90, 91, 92, 93, 94, 95, 96, 97, 98, 99]
前11-20个数:
L[10:20]
[10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
前10个数,每两个取一个:
L[:10:2]
[0, 2, 4, 6, 8]
所有数,每5个取一个:
L[::5]
[0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95]
甚至什么都不写,只写[:]就可以原样复制一个list:
L[:]
[0, 1, 2, 3, ..., 99]
tuple也是一种list,唯一区别是tuple不可变。因此,tuple也可以用切片操作,只是操作的结果仍是tuple:
(0, 1, 2, 3, 4, 5)[:3]
(0, 1, 2)
字符串'xxx'或Unicode字符串u'xxx'也可以看成是一种list,每个元素就是一个字符。因此,字符串也可以用切片操作,只是操作结果仍是字符串:
'ABCDEFG'[:3]
'ABC'
'ABCDEFG'[::2]
'ACEG'
在很多编程语言中,针对字符串提供了很多各种截取函数,其实目的就是对字符串切片。Python没有针对字符串的截取函数,只需要切片一个操作就可以完成,非常简单。