版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Laox1ao/article/details/78036216
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) #对A进行快排
for i in range(len(b)):
if binarysearch(a,b[i]): #在A中进行二分查找
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)