面试题41:和为s的两个数字VS和为s的连续正整数序列
题目一:输入一个递增排序的数组和一个数字s,在数组中查找两个数,使得它们的和正好是s,如果有多对数字的和等于s,输出任意一对即可。
分析:对于这个问题,最容易想到的就是现在数组中固定一个数字,再依次判断数组中其余的n-1个数字与它的和是不是等于s。这种做法的复杂度为O(n2)O(n2)。进一步优化算法:现在数组中选择两个数字,如果他们的和等于输入的s,就直接输出这两个数字,如果小于s,这个时候就希望两个数字的和大一点,我们知道数组是已经排好序的,所以可以考虑选择较小的数字后面的数字,因为排在后面的数字要大一些,那么两个数字的和也要大一些,就有可能等于输入的数字s了。同样的,当连个数字的和大于输入的数字的时候,我们可以选择较大数字前面的数字,因为排在数组前面的数字要小一些。
具体设计:
定义两个指针,第一个指向数组的第一个元素,另外一个指向数组的最后一个元素,然后把两个元素的和与s进行比较,如果相等则直接输出,如果两个元素的和比s小,则吧第一个指针向后移动一位,继续进行比较;相同的,如果两个元素的和比s大,则把第二个指针向前移动一位;直到找到第一个相等的便输出
代码实现(python)
class Solution:
def findnumberWithSum(self,nums,s):
if len(nums)<2:
return
ahead = 0
behind = len(nums)-1
while ahead < behind:
if nums[ahead] + nums[behind] >s:
behind -=1
elif nums[ahead] +nums[behind] <s:
ahead +=1
else:
print(nums[ahead],nums[behind])
break
if __name__ == "__main__":
S = Solution()
nums = [1,2,4,7,11,16]
S.findnumberWithSum(nums,10)
题目二:输入一个正数s,打印出所有和为s的连续整数序列(至少含有两个数),例如输入15,由于1+2+3+4+5=4+5+6=7+8=15,所以结果打印出3个连续序列1~5、4~6和7~8
分析:和上面题目的想法一样,我们用两个数small 和big 分别表示序列的最小值和最大值。首先把small初始化为1,big初始化为2.如果从small到big的序列的和大于s,我们可以从序列中去掉较小的值,也就是增大small的值。如果从small到big的序列的和小于s,我们可以增大big,让这个序列包含更多的数字。因为这个序列至少要有两个数字,我们一直增大small到(1+s)/2为止。
代码实现(python):
# -*- coding:utf-8 -*-
class Solution:
def FindContinuousSequence(self, tsum):
# write code here
nums = []
if tsum < 3:
return []
small = 1
big = 2
middle = (1+tsum)//2
curSum = small +big
while small < middle:
if curSum == tsum:
self.printSequence(nums,small,big)
while curSum >tsum and small <middle:
curSum -= small
small +=1
if curSum == tsum:
self.printSequence(nums,small,big)
big +=1
curSum +=big
return nums
def printSequence(self,nums,small,big):
num = []
for i in range(small,big+1):
num.append(i)
nums.append(num)
if __name__ == "__main__":
S = Solution()
S.FindContinuousSequence(3)