数据结构刷题记录

 

1.斐波那契数列

要求输入一个整书n,请你输出斐波那契数列的第n项(从0开始,第0项为0)。

class Solution:
    def Fibonacci(self, n):
        # write code here
        res = [0,1]
        while(len(res)<=n):
            res.append(res[-1]+res[-2])
        return res[n]

2.用两个栈实现队列

用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。

# -*- coding:utf-8 -*-
class Solution:
    def __init__(self):
        self.stack1 = []
        self.stack2 = []
         
    def push(self, node):
        # write code here
        self.stack1.append(node)
         
    def pop(self):
        # return xx
        if not len(self.stack2) == 0:
            return self.stack2.pop()
        else:
            while len(self.stack1) > 0:
                self.stack2.append(self.stack1.pop())
            return self.stack2.pop()

3.串的模式匹配算法

'''
在主串s的pos后寻找子串t并返回索引,时间复杂度O[(n-m+1)*m]
'''
def Index(s, t, pos):
    i = pos
    j = 0
    while i<len(s) and j<len(t):
        if s[i]==t[j]:
            i += 1
            j += 1
        else:
            i = i-j+1
            j = 0
    if j == len(t):
        return i-j
    else:
        return False

4.重建二叉树

输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。

# -*- coding:utf-8 -*-
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution:
    # 返回构造的TreeNode根节点
    def reConstructBinaryTree(self, pre, tin):
        # write code here
        if not pre or not tin:
            return None
        root = TreeNode(pre.pop(0))
        index = tin.index(root.val)
        root.left = self.reConstructBinaryTree(pre,tin[:index])
        root.right = self.reConstructBinaryTree(pre,tin[index+1:])
        return root

5.二叉树的生成(python)

class Node(object):
    
    def __init__(self, number):
        self.val = number
        self.lchild = None
        self.rchild = None
        
class Tree(object):
    
    lis = []   ##用来保存没有左右孩子的节点,
    def __init__(self):
        self.root = None
    def add(self, number):
        node = Node(number)
        if self.root == None:
            self.root = node
            Tree.lis.append(self.root)
        else:
            while True:
                point = Tree.lis[0]
                
                if point.lchild==None:
                    point.lchild = node
                    Tree.lis.append(point.lchild)
                    return
                elif point.rchild==None:
                    point.rchild = node
                    Tree.lis.append(point.rchild)
                    Tree.lis.pop(0)  ###如果该节点的左右孩子都有则pop
                    return
    def traverse(self):   ##层次遍历
        if self.root == None:
            return None
        q = [self.root]
        res = [self.root.val]
        while q!=[]:
            pop_node = q.pop(0)
            if pop_node.lchild is not None:
                q.append(pop_node.lchild)
                res.append(pop_node.lchild.val)
            if pop_node.rchild is not None:
                q.append(pop_node.rchild)
                res.append(pop_node.rchild.val)
        return res
    
    def preorder(self, root):  ###前序遍历
        if root == None:
            return []
        res = [root.val]
        left_val = self.preorder(root.lchild)
        right_val = self.preorder(root.rchild)
        return res+left_val+right_val
    def preorder1(self, root): ##前序遍历迭代
        if root == None:
            return []
        p = root
        res = []
        stack = []
        while p or stack:
            if p:
                res.append(p.val)
                stack.append(p)
                p = p.lchild
            else:
                temp = stack.pop()
                p = temp.rchild
        return res
    
    def inorder(self, root): ###中序遍历
        if root == None:
            return []
        res = [root.val]
        left_val = self.inorder(root.lchild)
        right_val = self.inorder(root.rchild)
        return left_val+res+right_val
    
    def inorder2(self, root):
        if root == None:
            return []
        p = root
        stack = []
        res = []
        while p or stack:
            if p:
                stack.append(p)
                p = p.lchild
            else:
                temp = stack.pop()
                res.append(temp.val)
                p=temp.rchild
        return res
    
    def postorder(self, root):
        if root == None:
            return []
        res = [root.val]
        left_val = self.postorder(root.lchild)
        right_val = self.postorder(root.rchild)
        return left_val+right_val+res
    def postorder1(self, root):
        if root == None:
            return []
        p = root
        stack = []
        res = []
        while p or stack:
            if p:
                res.append(p.val)
                stack.append(p)
                p = p.rchild
            else:
                temp = stack.pop()
                p = temp.lchild
        return res[::-1]
t = Tree()
for i in range(10):
    t.add(i)
print('层序遍历:',t.traverse())
print('前序遍历:',t.preorder(t.root))
print('前序遍历:',t.preorder1(t.root))
print('中序遍历:',t.inorder(t.root))
print('中序遍历:',t.inorder2(t.root))
print('后序遍历:',t.postorder(t.root))
print('后序遍历:',t.postorder1(t.root))

6.跳台阶

一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果)。

对于本题,前提只有 一次 1阶或者2阶的跳法。

a.如果两种跳法,1阶或者2阶,那么假定第一次跳的是一阶,那么剩下的是n-1个台阶,跳法是f(n-1);

b.假定第一次跳的是2阶,那么剩下的是n-2个台阶,跳法是f(n-2)

c.由a\b假设可以得出总跳法为: f(n) = f(n-1) + f(n-2) 

d.然后通过实际的情况可以得出:只有一阶的时候 f(1) = 1 ,只有两阶的时候可以有 f(2) = 2

e.可以发现最终得出的是一个斐波那契数列:

        

              | 1, (n=1)

f(n) =     | 2, (n=2)

              | f(n-1)+f(n-2) ,(n>2,n为整数)

def jumpFloor(number):
    ###递归解法,空间复杂度太大,在牛客网上提交将显示,运行超时:您的程序未能在规定时间内运行结束,请检查是否循环有错或算法复杂度过大。因此采用斐波那契迭代方法。
    # write code here
    if number <= 0:
        return -1
    if number == 1:
        return 1
    elif number == 2:
        return 2
    else:
        return jumpFloor(number-1)+jumpFloor(number-2)
def jumpfloor(number):
    ###迭代解法
    f1 = 1
    f2 = 2
    if number <= 0:
        return -1
    elif number == 1 or number == 2:
        return number
    else:
        n = 2
        while(n<number):
            f2 += f1
            f1 = f2 - f1
            n += 1
        return f2

6.变态跳台阶

一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。

链接:https://www.nowcoder.com/questionTerminal/22243d016f6b47f2a6928b4313c85387
来源:牛客网
 

f(1) = 1

f(2) = f(2-1) + f(2-2)         //f(2-2) 表示2阶一次跳2阶的次数。

f(3) = f(3-1) + f(3-2) + f(3-3) 

...

f(n) = f(n-1) + f(n-2) + f(n-3) + ... + f(n-(n-1)) + f(n-n) 

 

说明: 

1)这里的f(n) 代表的是n个台阶有一次1,2,...n阶的 跳法数。

2)n = 1时,只有1种跳法,f(1) = 1

3) n = 2时,会有两个跳得方式,一次1阶或者2阶,这回归到了问题(1) ,f(2) = f(2-1) + f(2-2) 

4) n = 3时,会有三种跳得方式,1阶、2阶、3阶,

    那么就是第一次跳出1阶后面剩下:f(3-1);第一次跳出2阶,剩下f(3-2);第一次3阶,那么剩下f(3-3)

    因此结论是f(3) = f(3-1)+f(3-2)+f(3-3)

5) n = n时,会有n中跳的方式,1阶、2阶...n阶,得出结论:

    f(n) = f(n-1)+f(n-2)+...+f(n-(n-1)) + f(n-n) => f(0) + f(1) + f(2) + f(3) + ... + f(n-1)

    

6) 由以上已经是一种结论,但是为了简单,我们可以继续简化:

    f(n-1) = f(0) + f(1)+f(2)+f(3) + ... + f((n-1)-1) = f(0) + f(1) + f(2) + f(3) + ... + f(n-2)

    f(n) = f(0) + f(1) + f(2) + f(3) + ... + f(n-2) + f(n-1) = f(n-1) + f(n-1)

    可以得出:

    f(n) = 2*f(n-1)

    

7) 得出最终结论,在n阶台阶,一次有1、2、...n阶的跳的方式时,总得跳法为:

              | 1       ,(n=0 ) 

f(n) =     | 1       ,(n=1 )

              | 2*f(n-1),(n>=2)

# -*- coding:utf-8 -*-
class Solution:
    def jumpFloorII(self, number):
        # write code here
        return 2**(number-1)

7.二进制中一的个数

输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。

def NumberOf1(self, n):
    # write code here
    count = 0
    if n<0:
        n = n & 0xffffffff   ###n为负数时得到它的补码,因为python中负数的二进制表示是原码前面加-
    while n:
        count += 1
        n = (n - 1) & n
    return count

链接:https://www.nowcoder.com/questionTerminal/8ee967e43c2c4ec193b040ea7fbb10b8?f=discussion
来源:牛客网
 

分析一下代码: 这段小小的代码,很是巧妙。

如果一个整数不为0,那么这个整数至少有一位是1。如果我们把这个整数减1,那么原来处在整数最右边的1就会变为0,原来在1后面的所有的0都会变成1(如果最右边的1后面还有0的话)。其余所有位将不会受到影响。

举个例子:一个二进制数1100,从右边数起第三位是处于最右边的一个1。减去1后,第三位变成0,它后面的两位0变成了1,而前面的1保持不变,因此得到的结果是1011.我们发现减1的结果是把最右边的一个1开始的所有位都取反了。这个时候如果我们再把原来的整数和减去1之后的结果做与运算,从原来整数最右边一个1那一位开始所有位都会变成0。如1100&1011=1000.也就是说,把一个整数减去1,再和原整数做与运算,会把该整数最右边一个1变成0.那么一个整数的二进制有多少个1,就可以进行多少次这样的操作。

需要注意python中负数的二进制表示是原码前面加负号(比如bin(100)就是-0b1100100),和c/java直接就是补码不同,因此需要将负号表示转换为补码,对于负数,最高位为1,而负数在计算机是以补码存在的,往右移,符号位不变,符号位1往右移,最终可能会出现全1的情况,导致死循环。与0xffffffff相与,就可以消除负数的影响,得到负数的补码表示

8.数值的整数次方

给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。

# -*- coding:utf-8 -*-
class Solution:
    def Power(self, base, exponent):
        # write code here
        '''
        一般解法考虑base是否为0,以及exponent是否为0
        '''
        current = base
        if base == 0 and exponent>0:
            return 0
        elif base == 0 and exponent<=0:
            raise ZeroDivisionError()
        else:
            if exponent == 0:
                return 1
            elif exponent >= 0:
                while(exponent-1):
                    current *= base
                    exponent -= 1
                return current
            else:
                exponent = -exponent
                while(exponent-1):
                    current *= base
                    exponent -= 1
                return 1/current
        #return base**exponent  ###一行解法
'''
快速求幂算法  参考https://blog.csdn.net/hkdgjqr/article/details/5381028
''' 
    def fast_power(self, base, exponent):
        if base == 0:
            return 0
        if exponent == 0:
            return 1
        e = abs(exponent)
        tmp = base
        res = 1
        while(e > 0):
            #如果最后一位为1,那么给res乘上这一位的结果
            if (e & 1 == 1):
                res =res * tmp
            e = e >> 1
            tmp = tmp * tmp
        return res if exponent > 0 else 1/res

9.链表中倒数第k个结点

输入一个链表,输出该链表中倒数第k个结点。

# -*- coding:utf-8 -*-
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def FindKthToTail(self, head, k):
        # write code here
        if head == None or k<=0:
            return None
        p1 = head
        p2 = head
        while(k > 1):
            if p2.next == None:
                return None
            else:
                p2 = p2.next
            k -= 1
        while(p2.next != None):
            p1 = p1.next
            p2 = p2.next
        return p1

设置两个指针,p1,p2,先让p2走k-1步,然后再一起走,直到p2为最后一个 时,p1即为倒数第k个节点 

10.反转链表

输入一个链表,反转链表后,输出新链表的表头。

# -*- coding:utf-8 -*-
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None
class Solution:
    # 返回ListNode
    def ReverseList(self, pHead):
        # write code here
        if pHead == None or pHead.next == None:
            return pHead
        else:
            pre = None
            cur = pHead
            while(cur):
                tmp = cur.next
                cur.next = pre
                pre = cur
                cur = tmp
            return pre

11.合并两个排序的链表

输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。

'''
非递归方法
'''
# -*- coding:utf-8 -*-
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None
class Solution:
    # 返回合并后列表
    def Merge(self, pHead1, pHead2):
        # write code here
        if pHead1 == None:
            return pHead2
        elif pHead2 == None:
            return pHead1
        else:
            MergedHead = current = None
            while pHead1 and pHead2:
                if pHead1.val <= pHead2.val:
                    if MergedHead == None:
                        MergedHead = current = pHead1
                    else:
                        current.next = pHead1
                        current = current.next
                    pHead1 = pHead1.next
                else:
                    if MergedHead == None:
                        MergedHead = current = pHead2
                    else:
                        current.next = pHead2
                        current = current.next
                    pHead2 = pHead2.next
            if pHead1 == None:
                current.next = pHead2
            elif pHead2 == None:
                current.next = pHead1
            return MergedHead
                    

'''
递归方法
'''
# -*- coding:utf-8 -*-
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None
class Solution:
    # 返回合并后列表
    def Merge(self, pHead1, pHead2):
        # write code here
        if pHead1 == None:
            return pHead2
        elif pHead2 == None:
            return pHead1
        if pHead1.val <= pHead2.val:
            MergedHead = pHead1
            MergedHead.next = self.Merge(pHead1.next, pHead2)
        else:
            MergedHead = pHead2
            MergedHead.next = self.Merge(pHead1, pHead2.next)
        return MergedHead

12.树的子结构

输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)

# -*- coding:utf-8 -*-
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution:
    def HasSubtree(self, pRoot1, pRoot2):
        # write code here
        result = False
        if pRoot1 != None and pRoot2 != None:
            if pRoot1.val == pRoot2.val:
                    result = self.DoesTree1hasTree2(pRoot1, pRoot2)
            if not result:
                    result = self.HasSubtree(pRoot1.left, pRoot2)
            if not result:
                    result = self.HasSubtree(pRoot1.right, pRoot2)
        return result
    def DoesTree1hasTree2(self, pRoot1, pRoot2):
        if pRoot2 == None:
            return True
        if pRoot1 == None:
            return False
        if pRoot1.val != pRoot2.val:
            return False
        return self.DoesTree1hasTree2(pRoot1.left, pRoot2.left) and self.DoesTree1hasTree2(pRoot1.right, pRoot2.right)

1、首先设置标志位result = false,因为一旦匹配成功result就设为true,

剩下的代码不会执行,如果匹配不成功,默认返回false

2、递归思想,如果根节点相同则递归调用DoesTree1HaveTree2(),

如果根节点不相同,则判断tree1的左子树和tree2是否相同,

再判断右子树和tree2是否相同

3、注意null的条件,HasSubTree中,如果两棵树都不为空才进行判断,

DoesTree1HasTree2中,如果Tree2为空,则说明第二棵树遍历完了,即匹配成功,

tree1为空有两种情况(1)如果tree1为空&&tree2不为空说明不匹配,

(2)如果tree1为空,tree2为空,说明匹配。

13.二叉树的镜像

二叉树的镜像定义:
         源二叉树 
    	    8
    	   /  \
    	  6   10
    	 / \  / \
    	5  7 9 11
    	镜像二叉树
    	    8
    	   /  \
    	  10   6
    	 / \  / \
    	11 9 7  5
# -*- coding:utf-8 -*-
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution:
    # 返回镜像树的根节点
    def Mirror(self, root):
        # write code here
        if root == None:
            return root
        tmp = root.left
        root.left = root.right
        root.right = tmp
        self.Mirror(root.left)
        self.Mirror(root.right)
        return root

14.顺时针打印矩阵

输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下4 X 4矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 则依次打印出数字1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10.

'''
解法一
'''
# -*- coding:utf-8 -*-
class Solution:
    # matrix类型为二维列表,需要返回列表
    def printMatrix(self, matrix):
        # write code here
        if matrix == None:
            return []
        res = []
        while matrix:
            res += matrix.pop(0)
            if matrix and matrix[0]:
                for row in matrix:
                    res.append(row.pop())
            if matrix:
                res += matrix.pop()[::-1]
            if matrix and matrix[0]:
                for row in matrix[::-1]:
                    res.append(row.pop(0))
        return res
'''
解法二:
可以模拟魔方逆时针旋转的方法,一直做取出第一行的操作
例如 
1 2 3
4 5 6
7 8 9
输出并删除第一行后,再进行一次逆时针旋转,就变成:
6 9
5 8
4 7
继续重复上述操作即可。
'''
链接:https://www.nowcoder.com/questionTerminal/9b4c81a02cd34f76be2659fa0d54342a?f=discussion
来源:牛客网

class Solution:
    # matrix类型为二维列表,需要返回列表
    def printMatrix(self, matrix):
        # write code here
        result = []
        while(matrix):
            result+=matrix.pop(0)
            if not matrix or not matrix[0]:
                break
            matrix = self.turn(matrix)
        return result
    def turn(self,matrix):
        num_r = len(matrix)
        num_c = len(matrix[0])
        newmat = []
        for i in range(num_c):
            newmat2 = []
            for j in range(num_r):
                newmat2.append(matrix[j][i])
            newmat.append(newmat2)
        newmat.reverse()
        return newmat
'''
解法三
'''
# -*- coding:utf-8 -*-
class Solution:
    # matrix类型为二维列表,需要返回列表
    def printMatrix(self, matrix):
        # write code here
        if matrix == None:
            return None
        width = len(matrix)
        hight = len(matrix[0])
        res = []
        if width == 1:
            for i in range(hight):
                res.append(matrix[0][i])
            return res
        elif hight == 1:
            for i in range(width):
                res.append(matrix[i][0])
            return res
        elif width == 2:
            res += matrix[0]
            for i in range(hight-1,-1,-1):
                res.append(matrix[1][i])
        elif hight == 2:
            res += matrix[0]
            for i in range(1,width):
                res.append(matrix[i][1])
            for i in range(width-1,0,-1):
                res.append(matrix[i][0])
        else:
            res += matrix[0]
            for i in range(1,width):
                res.append(matrix[i][-1])
            for i in range(hight-2,-1,-1):
                res.append(matrix[-1][i])
            for i in range(width-2,0,-1):
                res.append(matrix[i][0])
            if width > 2 and hight > 2:
                matrixleft = []
                for i in range(1,width-1):
                    matrixleft.append(matrix[i][1:-1])
                resleft = self.printMatrix(matrixleft)
                res += resleft
        return res

15.字符串最长回文子串(LeetCode5)

给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。

解法一:暴力搜索(Leetcode通过101/103)

class Solution:
    def longestPalindrome(self, s: str) -> str:
        n = length = len(s)
        if length == 0:
            return s
        while(length>0):
            for i in range(n-length+1):
                subs = s[i:i+length]
                if self.isPalindrome(subs):
                    return subs
            length -= 1
    def isPalindrome(self, string):
        n = len(string)
        length = n//2 if n%2 == 0 else n//2+1
        for i in range(length):
            if string[i] != string[-i-1]:
                return False
        return True
        

方法二:动态规划 

class Solution:
    def longestPalindrome(self, s: str) -> str:
        n = len(s)
        if n < 2:
            return s
        
        dp = [[0 for i in range(n)] for i in range(n)]
        
        longest_slen = 1
        res = s[0]
        
        for j in range(1,n):
            for i in range(j):
                if s[i] == s[j] and (j-i <=2 or dp[i+1][j-1]):
                    dp[i][j] = 1
                    cur_len = j-i+1
                    if cur_len > longest_slen:
                        longest_slen = cur_len
                        res = s[i:j+1]
        return res
        

16.字符串的字典序排列

输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。

输入描述:

输入一个字符串,长度不超过9(可能有字符重复),字符只包括大小写字母。

参考:

https://blog.csdn.net/weixin_42018258/article/details/80683826

https://www.cnblogs.com/pmars/archive/2013/12/04/3458289.html


思路一:递归

 

# -*- coding:utf-8 -*-
class Solution:
    def Permutation(self, ss):
        # write code here
        if len(ss)<2:
            return ss.split()
        strs = list(ss)
        res = []
        self.PermutationHelper(strs, 0, len(strs), res)
        return sorted(res)
    
    def PermutationHelper(self, strs, begin, end, res):
        if begin == end-1:
            res.append(''.join(strs))
        for i in range(begin, end):
            if i != begin and strs[i]==strs[begin]:
                continue
            self.swap(strs, begin, i)
            self.PermutationHelper(strs, begin+1, end, res)
            self.swap(strs, begin, i)
    
    def swap(self,strs, a, b):
        tmp = strs[a]
        strs[a] = strs[b]
        strs[b] = tmp

思路二:非递归

【例】 如何得到346987521的下一个
    1,从尾部往前找第一个P(i-1) < P(i)的位置
            3 4 6 <- 9 <- 8 <- 7 <- 5 <- 2 <- 1
        最终找到6是第一个变小的数字,记录下6的位置i-1
    2,从i位置往后找到最后一个大于6的数
            3 4 6 -> 9 -> 8 -> 7 5 2 1
        最终找到7的位置,记录位置为m
    3,交换位置i-1和m的值
            3 4 7 9 8 6 5 2 1
    4,倒序i位置后的所有数据
            3 4 7 1 2 5 6 8 9
    则347125689为346987521的下一个排列


所以思路就是先排序得到字典序最小的,然后不断的找下一个字典序排列。

# -*- coding:utf-8 -*-
class Solution:
    def Permutation(self, ss):
        # write code here
        if len(ss) < 2:
            return ss.split()
        ss = sorted(ss)
        res = []
        next_pmt = ss
        while next_pmt != []:
            res.append(''.join(next_pmt))
            next_pmt = self.get_next_pmt(next_pmt)
        return res
    def get_next_pmt(self, ss):
        i = len(ss)-2
        while (i>=0 and ss[i] >= ss[i+1]):
            i -= 1
        if i < 0:
            return []
        j = len(ss)-1
        while ss[j]<=ss[i]:
            j -= 1
        self.swap(ss, i, j)
        self.reverse(ss, i+1, len(ss)-1)
        return ss
    def swap(self, ss, i, j):
        temp = ss[i]
        ss[i] = ss[j]
        ss[j] = temp
    def reverse(self, ss, i ,j):
        while i<j:
            self.swap(ss, i, j)
            i += 1
            j -= 1

17.连续子数组的最大和

HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学。今天测试组开完会后,他又发话了:在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向量全为正数的时候,问题很好解决。但是,如果向量中包含负数,是否应该包含某个负数,并期望旁边的正数会弥补它呢?例如:{6,-3,-2,7,-15,1,2,2},连续子向量的最大和为8(从第0个开始,到第3个为止)。给一个数组,返回它的最大连续子序列的和,你会不会被他忽悠住?(子向量的长度至少是1)

# -*- coding:utf-8 -*-
'''动态规划'''
class Solution:
    def FindGreatestSumOfSubArray(self, array):
        # write code here
        if array is None:
            return 0
        dp = [0 for _ in range(len(array))]
        dp [0] = array[0]
        max_sum= dp[0]
        for i in range(1, len(array)):
            if dp[i-1] > 0:
                dp[i] = dp[i-1] + array[i]
            else:
                dp[i] = array[i]
            if dp[i] > max_sum:
                max_sum = dp[i]
        return max_sum

 进阶:最大子矩阵

链接:https://www.nowcoder.com/questionTerminal/a5a0b05f0505406ca837a3a76a5419b3
来源:牛客网

已知矩阵的大小定义为矩阵中所有元素的和。给定一个矩阵,你的任务是找到最大的非空(大小至少是1 * 1)子矩阵。 比如,如下4 * 4的矩阵 0 -2 -7 0 9 2 -6 2 -4 1 -4 1 -1 8 0 -2 的最大子矩阵是 9 2 -4 1 -1 8 这个子矩阵的大小是15。

思路:

//要求一个二维矩阵的最大子矩阵,首先要会求一维矩阵的最大子矩阵(即一维数组连续最大和)

//假设原二维矩阵的最大子矩阵所在的行为i到j

//  1 当i = j时,则最大子矩阵为第i行的连续最大和

//  2 当i != j时,现在我们已经直到最大子矩阵的行,要求的是其所在的列

//      我们把从第i行到第j行的所有行相加,得到一个只有一行的一维数组,则该一维数组

//      的连续最大和就是最大子矩阵。

 

//求一维数组的连续最大和

//动态规划问题,设DP[i]=以v[i]元素结尾的连续最大和

//则DP[i] = max(DP[i-1] + v[i], v[i])

//初始条件为DP[0] = v[0]

import sys
if __name__ == '__main__':
    n = int(input().strip())
    matrix = []
    for i in range(n):
        matrix.append(list(map(int, input().strip().split())))
    def func(array):
        dp = [0 for _ in range(len(array))]
        dp[0] = array[0]
        max_n = dp[0]
        for i in range(1, len(array)):
            if dp[i-1] > 0:
                dp[i] = dp[i-1] + array[i]
            else:
                dp[i] = array[i]
            if max_n < dp[i]:
                max_n = dp[i]
        return max_n
    max_sum = 0
    for i in range(n):
        array = [0]*n
        for j in range(i, n):
            for k in range(n):
                array[k] += matrix[j][k]
            ms = func(array)
            if max_sum < ms:
                max_sum = ms
    print(max_sum)

18.把数组排成最小的数

输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323。

思路:排序,排序的规则是比较两个字符串前后合并之后数字的大小对比,见cmp函数

# -*- coding:utf-8 -*-
class Solution:
    def PrintMinNumber(self, numbers):
        # write code here
        if len(numbers) == 0:
            return ''
        def cmp(a,b):
            if int(a+b)>int(b+a):
                return True
            else:
                return False
        numbers = list(map(str, numbers))
        flag = True
        for i in range(len(numbers)):
            if flag == False:
                break
            flag = False
            for j in range(len(numbers)-2, i-1, -1):
                if cmp(numbers[j], numbers[j+1]):
                    numbers[j], numbers[j+1] = numbers[j+1], numbers[j]
                    flag = True
        return int(''.join(numbers))

 

19.丑数

把只包含质因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含质因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。

# -*- coding:utf-8 -*-
class Solution:
    def GetUglyNumber_Solution(self, index):
        # write code here
        if index < 7:
            return index
        res = [1]
        t1 = t2 = t3 = 0
        for i in range(1, index):
            res.append(min(res[t1]*2, res[t2]*3, res[t3]*5))
            if res[i] == res[t1]*2:
                t1 += 1
            if res[i] == res[t2]*3:
                t2 += 1
            if res[i] == res[t3]*5:
                t3 += 1
        return res[-1]

 

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值