1、数组中只出现一次的两个数字
题目描述:
一个整型数组里除了两个数字只出现一次,其他的数字都出现了至少两次。请写程序找出这两个只出现一次的数字。
示例:
输入:[1,4,1,6] 返回值:[4,6]
输入:[1, 2, 3, 3, 3, 2, 9] 返回值:[1, 9]
解题思路:
既然有两个数字只出现了一次,我们就统计每个数字的出现次数。
step 1:遍历数组,用哈希表统计每个数字出现的频率。
step 2:然后再遍历一次数组,对比哈希表,找到出现频率为1的两个数字。
step 3:最后整理次序输出。
Python的字典能够很好的解决这件事情, 用键值对来记录元素以及其出现的次数
def find_nums_appear_once(array):
dic = dict()
lst = list()
for i in array:
if i not in dic:
dic[i] = 1
else:
# 不能删,这里记录频次
dic[i] += 1
for key, value in dic.items():
if value == 1:
lst.append(key)
print(dic, lst)
return sorted(lst)
2、两数之和
题目描述:
给出一个整型数组 numbers 和一个目标值 target,请在数组中找出两个加起来等于目标值的数的下标,返回的下标按升序排列。 (注:返回的数组下标从1开始算起,保证target一定可以由数组里面2个数字相加得到)
示例:
输入:[3, 2, 4], 6
返回值:[2, 3]
说明:因为2+4=6 ,而 2的下标为2 ,4的下标为3 ,又因为 下标2 < 下标3 ,所以返回[2,3]输入:[20, 70, 110, 150], 90
返回值:[1, 2]
说明:20 + 70=90
解题思路:
step 1:构建一个哈希表,其中key值为遍历数组过程中出现过的值,value值为其相应的下标,因为我们最终要返回的是下标。
step 2:遍历数组每个元素,如果目标值减去该元素的结果在哈希表中存在,说明我们先前遍历的时候它出现过,根据记录的下标,就可以得到结果。
step 3:如果相减后的结果没有在哈希表中,说明先前遍历的元素中没有它对应的另一个值,那我们将它加入哈希表,等待后续它匹配的那个值出现即可。
# 每次插入一个新的数进入hash_map,在插入之前,就看看他的补数remind是不是已经在数组里了?
# 如果在的话,直接返回结果。
# 如果不在的话,就正常插入,毕竟,咱们不能排除这个数可能是,后来还没插入数的补数的可能性。
def get_two_sum(array, target):
hash_map = dict()
for i in range(len(array)):
remind = target - array[i]
if remind in hash_map:
# +1是因为返回的index要求从1开始
return [hash_map[remind] + 1, i + 1]
else:
hash_map[array[i]] = i
return []
3、三数之和
题目描述:
给出一个有n个元素的数组S,S中是否有元素a,b,c满足a+b+c=0?找出数组S中所有满足条件的三元组。
注意:
三元组(a、b、c)中的元素可以按任意顺序排列。
解集中不能包含重复的三元组。
示例:
输入:[-10,0,10,20,-10,-40]
返回值:[[-10,-10,20],[-10,0,10]]输入:[-2,0,1,1,2]
返回值:[[-2,0,2],[-2,1,1]]输入:[0,0]
返回值:[]
解题思路:
step 1:先得把这个无序的数组搞有序了,使用sort函数优先对其排序。
step 2:得到有序数组后,遍历该数组,对于每个遍历到的元素假设它是三元组中最小的一个,那么另外两个一定在后面。
step 3:需要三个数相加为0,则另外两个数相加应该为上述第一个数的相反数,我们可以利用双指针在剩余的子数组中找有没有这样的数对。双指针指向剩余子数组的首尾,如果二者相加为目标值,那么可以记录,而且二者中间的数字相加可能还会有。
step 4:如果二者相加大于目标值,说明右指针太大了,那就将其左移缩小,相反如果二者相加小于目标值,说明左指针太小了,将其右移扩大,直到两指针相遇,剩余子数组找完了。
注:对于三个数字都要判断是否相邻有重复的情况,要去重。
def three_sum(num_list):
"""
利用双指针解决,将原来数组进行排序,在从小到大取出,设置两个哨兵left,right
根据num_list[left] + num_list[right] + target进行指针移动判断。
:param num_list:
:return:
"""
length = len(num_list)
if length <= 2 or (length == 3 and sum(num_list) != 0):
return []
result = list()
num_list.sort()
for i in range(length-2):
if i > 0 and num_list[i] == num_list[i - 1]:
# 挨着的数字是相同只计算一次,可以达到去重和节约时间的效果,
# 也可以不要这里,后面append的时候判断去重,这样就多循环一次。
continue
target = num_list[i]
left, right = i+1, length-1
while left < right:
if num_list[left] + num_list[right] + target == 0:
result.append([num_list[i], num_list[left], num_list[right]])
# 找到一组后继续找,可能有多组
left += 1
# right -= 1 可要可不要
elif num_list[left] + num_list[right] + target < 0:
# 三数相加小于0,需要增大,左指针右移
left += 1
elif num_list[left] + num_list[right] + target > 0:
# 三数相加大于0,需要减小,右指针左移
right -= 1
return result