leetcode python实现

博客围绕LeetCode多道题目展开,包括最大子序和、打家劫舍、等差数列划分等。针对不同题目给出了解题思路,如最大子序和考虑正负对和的影响,打家劫舍确定状态转移方程,部分题目还提及复杂度分析及不同解法的优劣。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

53 最大子序和

给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

示例:

输入: [-2,1,-3,4,-1,2,1,-5,4],
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。

解:


    class Solution:
        def maxSubArray(self, nums):
            """
            :type nums: List[int]
            :rtype: int
            """        
            count = -100000000000000000000
            maxlen = [0]*len(nums)
            for i in range(len(nums)):
                for j in range(i,len(nums)):
                    maxlen[i] += nums[j]
                    if maxlen[i]>count:
                        count = maxlen[i]
                    if maxlen[i] <0:
                        break
            return count     

简写为:

    class Solution:
        def maxSubArray(self, nums):
            """
            :type nums: List[int]
            :rtype: int
            """        
            count = nums[0]
            for i in range(len(nums)):
                maxlen = 0
                for j in range(i,len(nums)):
                    maxlen += nums[j]
                    if maxlen>count:
                        count = maxlen[i]
                    if maxlen <0:
                        break
            return count   

但这样其实没有简单 复杂度高。

当我们加上一个正数时,和会增加;当我们加上一个负数时,和会减少。如果当前得到的和是个负数,那么这个和在接下来的累加中应该抛弃并重新清零,不然的话这个负数将会减少接下来的和。

    class Solution:
        def maxSubArray(self, num):
            dp = num[0]
            max_s = dp
            for i in range(1, len(num)):
                if dp <= 0:
                    dp = num[i]
                else:
                    dp += num[i]
                if dp > max_s:
                    max_s = dp
            return max_s

198 打家劫舍

假设当前已经肆虐过了前i个房子(0…i-1),且rob[i]是抢劫了下标为i的房子时的最大收益,pass[i]是不抢劫下标为i的房子时的最大收益,那么可以得到状态转移方程:

参考 http://mzorro.me/2016/03/15/leetcode-house-robber/

状态方程:

    rob[i] = nums[i] + pass[i-1]
    pass[i] = max(rob[i-1], pass[i-1])

最重要的是先确定状态方程

    class Solution:
        def rob(self, nums):
            """
            :type nums: List[int]
            :rtype: int
            """
            if len(nums)<=0:
                return 0
            rob,passc = [0]*len(nums),[0]*len(nums)
            rob[0]=nums[0]
            for i in range(1,len(nums)):
                rob[i] = nums[i]+passc[i-1]
                passc[i] = max(rob[i-1],passc[i-1])
            return max(max(passc),max(rob))

也可以写为:

    class Solution(object):
        def rob(self, nums):
            """
            :type nums: List[int]
            :rtype: int
            """
            if nums == []:
                return 0
            dp=[0]*(len(nums)+1)
            dp[1] = nums[0]
            for i in range(2,len(nums)+1):
                dp[i] = max(dp[i-1],nums[i-1]+dp[i-2])  #因为有涉及i-2,所以这里dp向量维度多1
            return dp[len(nums)]

413. 等差数列划分

如果一个数列至少有三个元素,并且任意两个相邻元素之差相同,则称该数列为等差数列。
例如,以下数列为等差数列:
1, 3, 5, 7, 9
7, 7, 7, 7
3, -1, -5, -9
以下数列不是等差数列。
1, 1, 2, 5, 7
数组 A 包含 N 个数,且索引从0开始。数组 A 的一个子数组划分为数组 (P, Q),P 与 Q 是整数且满足 0<=P<Q<N 。
如果满足以下条件,则称子数组(P, Q)为等差数组:
元素 A[P], A[p + 1], ..., A[Q - 1], A[Q] 是等差的。并且 P + 1 < Q 。
函数要返回数组 A 中所有为等差数组的子数组个数。
示例:
A = [1, 2, 3, 4]
返回: 3, A 中有三个子等差数组: [1, 2, 3], [2, 3, 4] 以及自身 [1, 2, 3, 4]。

解析:

参考 http://www.cnblogs.com/grandyang/p/5968340.html

要点在于 子数组个数怎么解。

我的第一种解法,三重循环,复杂度太高:

    class Solution(object):
        def numberOfArithmeticSlices(self, A):
            """
            :type A: List[int]
            :rtype: int
            """
            n = len(A)
            count=0
            for i in range(2, n):
                for j in range(n - i):  # 考虑所有连续的长度为i+1的子串,s[j....j+i]
                    temp = 1
                    for k in range(j,j+i-1):
                        if A[k+2] - A[k+1] != A[k+1] - A[k]:
                            temp = 0
                            break
                    count += temp
            return count

用动态规划的解法:这里有规律,如果知道了是等差数列,比如1,2,3 再加入下一个,比如2,3,4,也是等差,在已知前一个是等差的基础上,这里是加1了。

    class Solution:
        def numberOfArithmeticSlices(self, A):
            """
            :type A: List[int]
            :rtype: int
            """  
            dp = [0]*len(A)
            res=0
            for i in range(2,len(A)):
                if A[i]-A[i-1] == A[i-1]-A[i-2]:
                    dp[i] = dp[i-1]+1
                res+=dp[i]
            return res

152. 乘积最大子序列

给定一个整数数组 nums ,找出一个序列中乘积最大的连续子序列(该序列至少包含一个数)。

示例 1:

输入: [2,3,-2,4]
输出: 6
解释: 子数组 [2,3] 有最大乘积 6。
示例 2:

输入: [-2,0,-1]
输出: 0
解释: 结果不能为 2, 因为 [-2,-1] 不是子数组。

这题初看,以为是413等差数列划分的解法,但不太一样,因为有正负,没有一个衡量标准。
看了解答后,发现要设置最大最小两个参数,因为带负号的最小,只要遇到新的一个负号,就可能会变成最大。

    class Solution(object):
        def maxProduct(self, A):
            mmax,mmin = [0]*len(A),[0]*len(A)
            mmax[0],mmin[0],res = A[0],A[0],A[0]
            for i in range(1,len(A)):
                mmax[i] = max(mmax[i - 1] * A[i], mmin[i - 1] * A[i], A[i])
                mmin[i] = min(mmax[i - 1] * A[i], mmin[i - 1] * A[i], A[i])
                res = max(res,mmax[i])
            return res

695. 岛屿的最大面积

给定一个包含了一些 0 和 1的非空二维数组 grid , 一个 岛屿 是由四个方向 (水平或垂直) 的 1 (代表土地) 构成的组合。你可以假设二维矩阵的四个边缘都被水包围着。找到给定的二维数组中最大的岛屿面积。(如果没有岛屿,则返回面积为0。)
示例 1:
[[0,0,1,0,0,0,0,1,0,0,0,0,0],
 [0,0,0,0,0,0,0,1,1,1,0,0,0],
 [0,1,1,0,1,0,0,0,0,0,0,0,0],
 [0,1,0,0,1,1,0,0,1,0,1,0,0],
 [0,1,0,0,1,1,0,0,1,1,1,0,0],
 [0,0,0,0,0,0,0,0,0,0,1,0,0],
 [0,0,0,0,0,0,0,1,1,1,0,0,0],
 [0,0,0,0,0,0,0,1,1,0,0,0,0]]
对于上面这个给定矩阵应返回 6。注意答案不应该是11,因为岛屿只能包含水平或垂直的四个方向的‘1’。
示例 2:
[[0,0,0,0,0,0,0,0]]
对于上面这个给定的矩阵, 返回 0。

用广度优先搜索dfs解:
注意:这里不需要一个flag,直接把grid设置为0即可,因为grid是连通域,扫描过一次,之后不会再第二次用到,所以可以设成0.

    def maxAreaOfIsland(grid):
        count=0
        def dfs(grid,i,j):
            if i<0 or i>=len(grid) or j<0 or j>=len(grid[0]) or grid[i][j]==0:
                return 0
            grid[i][j]=0
            return dfs(grid,i-1,j) + dfs(grid,i+1,j) + dfs(grid,i,j+1) + dfs(grid,i,j-1) +1
    
        for i in range(len(grid)):
            for j in range(len(grid[0])):
                if grid[i][j]==1:
                    count = max(dfs(grid,i,j),count)
        return count
    
    A = [[0,0,1],[1,0,1],[1,1,0]]
    
    print(maxAreaOfIsland(A))

874. 模拟行走机器人

这题看了答案,没想出来。
自己重写了一遍,值得注意的是,如果用数组[],不用tuple()的话,会超出时间限制,不知为何。

    class Solution:
        def robotSim(self, commands, obstacles):
            i = j = mx = d = 0
            move, obstacles = [(0, 1), (-1, 0), (0, -1), (1, 0) ], set(map(tuple, obstacles))
            for command in commands:
                if command == -2: d = (d + 1) % 4
                elif command == -1: d = (d - 1) % 4
                else:
                    x, y = move[d]
                    while command and (i + x, j + y) not in obstacles:
                        i += x
                        j += y
                        command -= 1
                mx = max(mx, i ** 2 + j ** 2)
            return mx

以下用[]会超出时间限制:

    class Solution(object):
        def robotSim(self, commands, obstacles):
            """
            :type commands: List[int]
            :type obstacles: List[List[int]]
            :rtype: int
            """
            i = j = d = res= 0
            move = [[0,1],[-1,0],[0,-1],[1,0]]
    
            for com in commands:
                if com == -2:
                    d = (d+1)%4
                elif com == -1:
                    d = (d-1)%4
                else:
                    x,y = move[d] 
                    while com and [i+x,j+y] not in obstacles:
                        i += x
                        j += y
                        com -= 1
                res = max(res, i**2 + j**2) 
            return res

104. 二叉树的最大深度

给定一个二叉树,找出其最大深度。

二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。

说明: 叶子节点是指没有子节点的节点。

示例:
给定二叉树 [3,9,20,null,null,15,7],

    3
   / \
  9  20
    /  \
   15   7
返回它的最大深度 3 。

这题要好好看看,最大深度就是深度优先搜索dfs,用递归!;还可以层次遍历,用bfs的方法也可以得到层数。

dfs递归:

    # Definition for a binary tree node.
    # class TreeNode(object):
    #     def __init__(self, x):
    #         self.val = x
    #         self.left = None
    #         self.right = None
    
    class Solution(object):
        def maxDepth(self, root):
            """
            :type root: TreeNode
            :rtype: int
            """
            if root==None:
                return 0
            return 1 + max(self.maxDepth(root.left),self.maxDepth(root.right))

复杂度分析:

时间复杂度:我们每个结点只访问一次,因此时间复杂度为O(N),其中N是结点的数量。

空间复杂度:在最糟糕的情况下,树是完全不平衡的,例如每个结点只剩下左子结点,递归将会被调用N次(树的高度),因此保持调用栈的存储将是O(N)。
但在最好的情况下(树是完全平衡的),树的高度将是log(N)。因此,在这种情况下的空间复杂度将是O(log(N))

麻烦一点的bfs:

    # Definition for a binary tree node.
    # class TreeNode(object):
    #     def __init__(self, x):
    #         self.val = x
    #         self.left = None
    #         self.right = None
    
    class Solution(object):
        def maxDepth(self, root):
            """
            :type root: TreeNode
            :rtype: int
            """
            if root == None:
                return 0
            res = 0
            q = [root]
            while q:
                res+=1
                for i in range(len(q),0,-1):
                    t = q[0]
                    q.pop(0)
                    if t.left:
                        q.append(t.left)
                    if t.right:
                        q.append(t.right)
            return res

官方题解,迭代法:

    # Definition for a binary tree node.
    # class TreeNode(object):
    #     def __init__(self, x):
    #         self.val = x
    #         self.left = None
    #         self.right = None
    
    class Solution:
        def maxDepth(self, root):
            """
            :type root: TreeNode
            :rtype: int
            """ 
            stack = []
            if root is not None:
                stack.append((1, root))
            
            depth = 0
            while stack != []:
                current_depth, root = stack.pop()   #这里的current_depth很巧妙,不是每次让current_depth+=1,因为这样就错了,难点所在。
                if root is not None:
                    depth = max(depth, current_depth)
                    stack.append((current_depth + 1, root.left))
                    stack.append((current_depth + 1, root.right))
            
            return depth

谷歌一题

题目:

由输入字符串生成输出字符串数组, 实现linux指令echo的功能
1:输入:a{1,2,3}{4,3,2}          
输出:     [a14, a23, a32]
2:输入:{1,2,3}a{4,5,6}{7,8,9}
输出:[1a47, 2a58, 3a69]
3:输入:{a,d,s}{g,k,l}{j,k,l}f
输出:[agjf, dkkf, sllf]

思路:

{1,2,3}a{4,5,6}{7,8,9}
Step1: 按照{进行分割,会分为四组,确保最终输出的字符串长度正确
“”,  “1,2,3}a”,  “4,5,6}”,    “7,8,9}”
Step2: 当上述例子中a出现在中间或者最右时可能分割不正确,进行纠正:
1)     去掉右括号,如果右括号不是出现在最后一个字符,将这个字符串拆成两个,例如,1,2,3}a”按照“}”的位置拆分为”1,2,3”和”a”
2)     忽略拆分的空字符串
Step3:拆分得到:“1,2,3”,  “a”,  “4,5,6”,    “7,8,9”
将结果存储到一个二维数组。行为最后输出字符串要拼接的元素个数,列为{}中的元素个数,本例中分别为 4和3
Step4:将每行数组按照列的位置组合到一起,组成新的数组输出:
[1a47, 2a58, 3a69]

解答:

    def expand(expression):
        rawWord = expression.split('{')
        l = 1
        point = 0
        word = [[0 for col in range(len(rawWord))] for row in range(len(rawWord))]
        for i in range(len(rawWord)):
            if len(rawWord[i]) < 1:
                continue
            if rawWord[i][len(rawWord[i])-1] != '}':
                tmp = rawWord[i]
                if rawWord[i].index('}') == -1:
                    word[point] = [0]
                    word[point][0] = rawWord[i]
                    point += 1
                else:
                    rawWord[i] = rawWord[i][0:rawWord[i].index('}')].replace('}','')
                    word[point] = rawWord[i].split(',')
                    point += 1
                    word[point] = [0]
                    word[point][0] = tmp[tmp.index('}')+1:]
                    point += 1
            else:
                rawWord[i] = rawWord[i].replace('}','')
                word[point] = rawWord[i].split(',')
                point += 1
                if l==1 and l<len(word[point-1]):
                    l = len(word[point-1])
        answer = [0]*l
        for j in range(l):
            answer[j] = []
            for i in range(len(rawWord)):
                if word[i] == None:
                    continue
                elif len(word[i]) == 1:
                  answer[j] += word[i][0]
                else:
                    answer[j] += word[i][j]
        ans = [0]*l
        for j in range(l):
            ans[j] = ''.join(answer[j])
        return ans
    c = '{3,5,6}{7,8,9}{a,b,c}{3,4,5}a'
    a = '{3,5,6}{7,8,9}a{a,b,c}{3,4,5}'
    ans = expand(a)
    print(ans)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值