2.求一个数组有最大和的子串和上升子序列问题,只写好这些经典问题才有用

2.求一个数组有最大和的子串
'''问题是一个数组比如[3,-2,6,8],求他的一个子串,st这个子串的sum最大'''
'''经典动态规划问题,也就是一直保持更新,核心就是这个更新函数的写法'''
'''思路就是:先上来把3作为最好的sum,然后对他进行更新,更新的原则是,如果当前sum大于0,那么他对于
后面的加项的提升还是有作用的,所以继续扩充子串,否则就扔掉这个子串,直接把他后面的当成子串第一个,继续更新
显然算法O(N)的复杂度.'''
a=[0,-2032432432,1243432,68689,645,-45,-343545,-999999992,399999,-9999,9898]
import random
a=list(range(-11,10,3))
random.shuffle(a)
print (a)
#下面开始动态规划
daan=he=a[0]
left=0
right=0#left,right标示从index left 加到index right包含index right
for i in range(1,len(a)):
      if he+a[i]<0:
            if i+1<len(a):
              left=i
              right=i
            he=a[i] #这步重要,从a[i]从新开始
      else:
            
            he=he+a[i]
            if right+1<len(a):
              right+=1            
            if he>daan:
                  daan=he
                  want_left=left
                  want_right=right

print (daan,want_left,want_right,sum(a[want_left:want_right+1]))

      
View Code

 3.该写最大子序列的和了

'''首先复习,子序列和子串的区别.
子序列就是一个按照原顺序 排列的子集合,每个元素的原地址可以不连续
而子串每个元素的原地址必须连续'''

a=[1,23,45,6,8,78,89,89,999,-342,-34,-67]
#首先是拥有最大子序列的和的子序列:这个答案,显然是提取所有的正数组成的序列即可
#然后问题改成:
'''需要求最长的上升子序列的长度和坐标位置'''
'''比如a=[1,2,5,3,4]  分析,开始从1,2,5取到了没问题,下面的3该如何选取?因为3比5小比2大,所以把原来
子序列里面的5换成3是一种根据贪心来说更好的选择.那么如果a=[1,2,5,1.5,1.6,1.7]
or a=[1,2,5,1.5],那么如何选择?这里面选2还是选1.5就很麻烦了.'''
'''这里面北大的一个算法课程讲过,需要考虑这样一个数组b,b[i]标示以a[i]为结尾的最长上升子序列的长度.
好反向的思考方式.继续分析前面的比如a=[1,2,5,1.5,1.6,1.7],那么b=[1,2,3,2,3,4],所以答案是4,
问题是如何获得这个b数组,继续动态规划.b[0]显然,b[1]也显然,假设b[0]到b[i]都知道了,那么b[i+1]该
如何得到?动态规划思想好像数学归纳法.当然类似数学里面的方法从低角标开始尝试就知道了'''
'''b[0],b[1]已知,那么b[2]是多少,考虑问题转化成应该把5接到b[0]为结尾的子序列,还是b[1]为结尾的子序列
,或者他自己成为一个子序列,来似的得到的子序列最长.1.首先判断是否能接,把5跟1比跟2比都大,所以他
都能接到a[0]结尾的子序列,和a[1]结尾的子序列里面,所以b[2]=max(b[0]+1,b[1]+1,1)即可.
思路get下面直接写代码即可'''
import random
a=list(range(1,10))
random.shuffle(a)  #注意shuffle是一个工厂函数,不需要再赋值了.ps:突然想到的学算法的体会:
#尽量不要看别人的代码,只学习别人的大体思路,然后自己写code,学的才扎实,类似数学做题,老看别人的解答没啥大用,
#看看别人的思路,然后自己从头到尾写一次就能学到不少.
print (a)
#首先建立数组b,也是这个问题的本质.
b=[1]*len(a)
for i in range(len(a)):
      k=[]#k用来储存a[i]能拼接的index
      for j in range(i):#这个for来找k
            if a[j]<a[i]:
                  k.append(j)
      #开始动态规划,也就是递推函数
      
      if k!=[]:
       b[i]=max(b[j] for j in k)+1
      #当然下面的if不写也行
      if k==[]:
       b[i]=1

#上面已经成功输出长度,那么就应该继续写如何输出index的代码.
#我的想法是生成b的同时再生成一个数组c,来储存每一个以a[i]为结尾的子序列的开始index.#这个细想写起来有点复杂.
#不对,不应该直属处开始index,因为是子序列所以应该输出所有的index,因为可以跳着走.貌似需要一个二维数组;来储存.
print('下面开始的代码是输出最大的长度和这个序列的index的')

b=[1]*len(a)
c=[]
import numpy as np
for i in range(len(a)):
      c.append([])           #c=[[]]*len(a) !!!!!!千万不能这么创立二维数组!!!!!!!!!理由:list内存共享.会导致c中元素全一样.!!!!!
for i in range(len(a)):
      k=[]#k用来储存a[i]能拼接的index

 
      for j in range(i):#这个for来找k
            if a[j]<a[i]:
                  k.append(j)
      #开始动态规划,也就是递推函数
     
      if len(k)!=0:
       
       b[i]=max(b[j] for j in k)+1
       t=[]
       for j in k:
        t.append(b[j] )
       q=t.index(b[i]-1)
       attachto=k[q]
       #找到应该贴在谁的后面:i可以贴到k里面的元素的后面,那么贴到哪个元素的后面最大?
      
       
       c[i]=(c[attachto]+[i])

      #当然下面的if不写也行
      if len(k)==0:
       c[i].append(i)
print (b)
##print (max(b))
print (c)

print ('下面打印的是最长的长度和路径')
print(max(b))
index=b.index(max(b))

print (c[index])
print('最长路径上面的数字')
qq=''
for i in c[index]:
      qq+=','+str(a[i])
qq=qq[1:]
print (qq)
#当然上面还只是给一个首index最小的解,而不是全解.
View Code

 4.上升子串

'''最长不严格上升子串问题'''
'''a=[2,4,-1,6,7,8],显然长度是4,感觉好废话,直接扫描即可'''
'''直接代码'''
import random
a=list(range(10))
random.shuffle(a)
print (a)
require_left=left=0
require_right=right=0
he=1
for i in range(len(a)):
      if i==0:
            continue
      else:
            if a[i]>=a[i-1]:
                  right+=1
                  
                  tmp=len(a[left:right+1])
               
                  if (tmp>he):
                        he=tmp
                        require_left=left
                        require_right=right
            else:
                  left=i
                  right=i
               
print (he,end=''),print ('是长度')
print (require_left,end=''),print('是开始index')
print (require_right,end=''),print('是结尾index')
print('具体的数是',end=''),print (a[require_left:require_right+1])
print('下面是其他东西')
#如何python 打印不回车,加一个end参数就行了.
print('3432423', end=""),print (3432423)
View Code

 5.用单链表实现栈和队列

'''算法导论中文本p134'''
'''1.用一个单链表来实现一个栈,要求操作push和pop的运行时间仍为O(1)'''

'''发现了一个很吊的东西叫windows api,利用里面函数可以控制windows.实现非常多的操作'''
class node():
      def __init__(self,a):#另外python也可以在类里面定义类.类里面的属性可
                            #以定义成类的属性或者实例的属性.
            
           self.data=a
           self.next=None
class link():
      
      def __init__(self):
            self.head=node(None)  #需要逆着做链表.比如8本书摞起来放,最上面的书是head,倒数第二上面
                                        #的是head.next....这样做链表才行.
            
      def push(self,a):         #保证head一直指向栈顶元素.
            
                  e=node(a)
                  e.next=self.head
                  self.head=e
                  
      def pop(self):
            
            if self.head.next==None:
                  print ('error')
                  return 
            else:
                  re=self.head.data  #保证head一直指向栈顶元素.
                  self.head=self.head.next
                  print (re)
                  return re
b=link();    b.push(3)  #用分号可以把两句化拼成一句话,节省代码长度.

b.push(4)
b.push(5)
b.push(6)
b.pop()
b.pop()
b.pop()
b.pop()
b.pop()
b.pop()  #还是成功了哈.


class node():
      def __init__(self,a):#另外python也可以在类里面定义类.类里面的属性可
                            #以定义成类的属性或者实例的属性.
            
           self.data=a
           self.next=None

'''用一个单链表来实现一个队列,要求操作enqueue和dequeue的运行时间是O(1)'''
class queue():
      def __init__(self):
            self.head=node(None)        #注意这里面开始时候head和tail都不是真正的元素,都是哨兵.
            self.tail=node(None)
            self.head.next=self.tail
      def push(self,a):         #保证head一直指向栈顶元素.            
                  e=node(a)
                  if self.head.next.data==None:
                      self.head.next=e
                  self.tail.next=e
                  self.tail=e    #现在tail指向最后一个
      def pop(self):
            if self.head==None:
                print ('error')
                return
            if self.head.data==None and self.head.next==None:
                print ('error')
                return
            if self.head.data==None and self.head.next.data!=None:
                  self.head=self.head.next
            
            re=self.head.data
            print (re)
            self.head=self.head.next
a=queue()

a.push(3)
a.push(4)
a.push(5)
a.push(5)
a.pop()
a.pop()
a.pop()
a.pop()
a.pop()
a.pop()
a.pop()















      
View Code

 

posted on 2018-02-28 00:57  张博的博客  阅读(149)  评论(0编辑  收藏  举报

导航