第2章 面试需要的基础知识
第3章 高质量的代码
第4章 解决面试题的思路
第5章 优化时间和空间效率
面试题39 : 数组中出现次数超过一半的数字
面试题40 : 最小的k个数
面试题42 : 连续子数组的最大和
面试题43 : 从1到n整数中1出现的次数
面试题45 : 把数组排成最小的数
面试题49 : 丑数
面试题50 : 第一个只出现一次的字符
面试题51 : 数组中的逆序对
面试题52 : 两个链表的第一个公共结点
面试题53 : 在排序数组中查找数字
面试题55 : 二叉树的深度、平衡二叉树
面试题56 : 数组中数字出现的次数
面试题57 : 和为s的连续正数序列、和为s的数字
第6章 面试中的各项能力
第7章 两个面试案例
题目描述
牛客网
输入一个递增排序的数组和一个数字s,在数组中查找两个数,使得它们的和正好是s。如果有多对数字的和等于s,输出任意一对即可。
解题思路
使用双指针前后夹逼,以数组[1, 2, 4, 7, 11, 15]为例,s=15。
第一个指针指向1,第二个指针指向15。发现两数之和为16,大于15,因此第二个指针后退一步,指向11;
此时两数之和为12,小于15,因此第一个指针前进一步,指向2;
此时两数之和为13,小于15,因此第一个指针前进一步,指向4;
此时两数之和为15,返回指针指向的数字,结束。
实战
def sequenceSum(lst, tsum):
if not lst or tsum <= lst[0]:
return -1
start, end = 0, len(lst) - 1
while start < end:
sums = lst[start] + lst[end]
if sums < tsum:
start += 1
elif sums > tsum:
end -= 1
else:
return [lst[start], lst[end]]
return -1
题目描述
牛客网
小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100。但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数)。没多久,他就得到另一组连续正数和为100的序列:18,19,20,21,22。现在把问题交给你,你能不能也很快的找出所有和为S的连续正数序列? Good Luck!
解题思路
使用一个窗口遍历数字,窗口大小是动态的。当窗口内数字和大于S时,从窗口尾部删除小的数字,当窗口内数字和小于S时,加入一个数字到窗口中,每次删除和加入数字后都需要判断窗口内数字之和是否等于S,若等于则保留此时窗口作为一个序列。
实战
代码中lst就是一个窗口,从1开始遍历数字直到 S // 2 + 1。
需要特别注意的是results.append(lst[:])这一行,如果改成results.append(lst)会出错,因为lst始终在变化,例如lst=[2, 3, 4]时执行这一句results.append(lst),那么results中就是[[2, 3, 4]],但是之后lst.pop(0)后,lst变为[3, 4],此时results中也会跟着变为[3, 4]]。
class Solution:
def FindContinuousSequence(self, tsum):
# write code here
if tsum <= 1:
return []
results, lst = [], []
step = 0
sums = 0
while step < tsum // 2 + 1:
if sums < tsum:
step += 1
sums += step
lst.append(step)
while sums >= tsum:
if sums == tsum:
results.append(lst[:])
sums -= lst.pop(0)
sums -= lst.pop(0)
return results