1、对于数组A,求出数组中连续子序列的最大和,如[1, 2, 3, 3, -4, 3, 0]的和最大连续子序列为[1, 2, 3, 3],最大和为9。
解法一:暴力遍历,两个for循环,加上求出所有子序列的和操作,算法复杂度为O(n3),若把之前的计算过的和存起来,则可减少为O(n2):
def maxsum1 (nums) :
maxsum = 0
for i in range(len(nums)):
sum = 0
for j in range(i,len(nums)):
sum += nums[j]
if sum>maxsum:
maxsum = sum
return maxsum
解法二:分治法,最大连续子序列和要么出现在数组左半部分,要么出现在数组右半部分,要么横跨左右两半部分。因此求出这三种情况下的最大值就可以得到最大连续子序列和,时间复杂度为O(nlogn)。
def maxsum2 (nums, l, r) :
if l>r: return 0
if l==r: return nums[l]
mid = (l+r)/2
lmax, rmax = 0 , 0
lsum, rsum = 0 , 0
for i in range(l,mid+1 )[::-1 ]:
lsum += nums[i]
if (lsum>lmax):
lmax = lsum
for i in range(mid+1 ,r+1 ):
rsum += nums[i]
if (rsum>rmax):
rmax = rsum
return max(lmax+rmax, maxsum2(nums,l,mid), maxsum2(nums,mid+1 ,r))
解法三:还有一种O(n)解法,一般最优解法都是需要深入分析具体问题的,本题的连续子序列,所有情况都是以0,n-1中某一元素为结尾,所以遍历到以第i个元素结尾的连续子序列时,判断当以第i-1个元素结尾的连续子序列,如果和为正数,那么就直接加上第i个元素,如果为负数或者为零,则以第i个元素结尾的连续子序列最大和即为第i个元素:
def maxsum3 (nums) :
maxsum, maxhere = nums[0 ], nums[0 ]
for i in range(1 ,len(nums)):
if maxhere<=0 :
maxhere = nums[i]
else :
maxhere += nums[i]
if maxhere>maxsum:
maxsum = maxhere
return maxsum
2、爬楼梯问题:一共有n级楼梯,从下往上,每次只能跨一级,两级,三级,共三种跨法,问一共有多少种爬法。再问:加上这样的规则,若这次跨了一次三级的台阶,则由于劳累而不能再跨一次三级,即不能连续跨三级楼梯,但是一、二级楼梯没有限制,问共有几种爬法。
无规则:典型的DP问题。d[i]为到达第i级楼梯的所有爬法:
def climbstep (n) :
d = [0 for _ in range(n+1 )]
d[0 ], d[1 ], d[2 ] = 1 , 1 , 2
for i in range(3 ,n+1 ):
d[i] = d[i-1 ] + d[i-2 ] + d[i-3 ]
return d[n]
Coding Here
3、有两个乱序且元素不重复的数组A,B,数组长度分别为m,n,求两个数组中所有相同的元素。
当场解法:1、暴力遍历,时间复杂度为O(mn)。2、对A排序(快排),遍历B,对于每个B中的元素在A中进行查找(二分查找),时间复杂度O(mlogm+nlogm):
def sameElement1 (a, b) :
res = []
quicksort(a)
for i in range(len(b)):
if binarysearch(a,b[i]):
res.append(b[i])
return res
def sameElements (a, b) :
temp, same = set(a), list()
for i in range(len(b)):
len0 = len(temp)
temp.add(b[i])
len1 = len(temp)
if len0 == len1:
same.append(b[i])
return same
def sameElements (a, b) :
a, b = set(a), set(b)
return list(a&b)