leetcode题解

5、191. Number of 1 Bits

思路1:

class Solution(object):
    def hammingWeight(self, n):
        """
        :type n: int
        :rtype: int
        """
        count=0
        
        while n!=0:
            if n%2==1: 
                count+=1
            n=n>>1
        return(count)

 

思路2:每次去掉二进制中最右边的1

class Solution(object):
    def hammingWeight(self, n):
        """
        :type n: int
        :rtype: int
        """
        count=0
        
        while n!=0:
            count=count+1
            n=n&(n-1)#每次去掉最右边的1
        return(count)

6、Triangle(三角形的最小路径和)

1、动态规划

自底而上的,申请一维数组就可以

class Solution(object):
    def minimumTotal(self, triangle):
        
        res=triangle[-1]
        
        for i in range(len(triangle)-2,-1,-1):
            
            for j in range(len(triangle[i])):
                res[j]=triangle[i][j]+min(res[j],res[j+1])
        return res[0]

 

#使用二维矩阵
class Solution(object):
    def minimumTotal(self, triangle):
        
        res= [[0 for i in range(len(triangle[-1]))] for i in range(len(triangle))]
        res[-1]=triangle[-1]
        
        for i in range(len(triangle)-2,-1,-1):
            
            for j in range(len(triangle[i])):
                res[i][j]=triangle[i][j]+min(res[i+1][j],res[i+1][j+1])
                
        return res[0][0]

7、55. Jump Game

贪心

这个题的tag是贪心,贪心策略是我们每次都选取最优的策略,然后前面已经选好了的就不用管了。

这个贪心的方法是,我们使用一个变量reach 保存当前能达到的最后位置索引,那么在每个位置的时候判断这个位置能不能到达,即位置的索引大于这个reach,说明前面无论怎么走也走不到这个位置,返回False。如果这个位置可以到达,要维护一下这个reach,更新策略是:当前索引位置+这个数字表示能向右走多少步,这个代表了到达当前位置的时候向右边能到达 的最远距离,在这个最远距离以内的任何位置都能到,因为每次跳的步数可以变小的。进行了一次循环后,每个位置都能到达,结果可以返回True.

时间复杂度o(n) 空间复杂度o(1)

class Solution(object):
    def canJump(self, nums):
        """
        :type nums: List[int]
        :rtype: bool
        """
        reach = 0
        for i, num in enumerate(nums):
            if i > reach:
                return False
            reach = max(reach, i + num)
        return True

贪心和DP的比较:

贪心算法(又称贪婪算法)是指,在对问题求解时,总是做出在当前看来最好的选择。也就是说,不从整体最优上加以考虑,他所作出的是在某种意义上的局部最优解。贪心算法和动态规划算法都是由局部最优导出全局最优,这里不得不比较下二者的区别。

贪心算法:
1.贪心算法中,作出的每步贪心决策都无法改变,因为贪心策略是由上一步的最优解推导下一步的最优解,而上一步之前的最优解则不作保留;
2.由(1)中的介绍,可以知道贪心法正确的条件是:每一步的最优解一定包含上一步的最优解。

动态规划算法:
1.全局最优解中一定包含某个局部最优解,但不一定包含前一个局部最优解,因此需要记录之前的所有最优解
2.动态规划的关键是状态转移方程,即如何由以求出的局部最优解来推导全局最优解;
3.边界条件:即最简单的,可以直接得出的局部最优解。
参考:
原文:https://blog.csdn.net/fuxuemingzhu/article/details/83504437 
 

8、45 Jump Game2

贪心

我们每次贪心的找在自己当前能到达的几个位置里面,跳到哪个位置的时候,在下一步能跳的最远。然后,我们当前步就跳到这个位置上去,所以我们在这一步的跳跃时,给下一步留下了最好的结果。

所以,使用一个cur表示当前步能到达的最远位置,使用pre表示上一次能到达的最远位置。所以,我们应该遍历在上一步的覆盖范围内,当前能跳的最远位置来更新cur。一个节省计算资源的方式是,保存以前已经检查了的位置为Pos,这样每次检查的范围是pos~pre。

class Solution(object):
    def jump(self, nums):
        cur = 0
        N = len(nums)
        count = 0
        pos = 0
        while cur < N - 1:
            count += 1
            pre = cur
            while pos <= pre:
                cur = max(cur, pos + nums[pos])
                pos += 1
        return count

9、 最长回文子串

参考:https://leetcode-cn.com/problems/longest-palindromic-substring/solution/zhong-xin-kuo-san-dong-tai-gui-hua-by-liweiwei1419/

dp[l][r] 表示子串 s[l, r](包括区间左右端点)是否构成回文串,是一个二维布尔型数组。即如果子串 s[l, r] 是回文串,那么 dp[l][r] = true。

class Solution:
    def longestPalindrome(self, s: str) -> str:
        size = len(s)
        if size <= 1:
            return s
        # 二维 dp 问题
        # 状态:dp[l,r]: s[l:r] 包括 l,r ,表示的字符串是不是回文串
        # 设置为 None 是为了方便调试,看清楚代码执行流程
        dp = [[False for _ in range(size)] for _ in range(size)]

        longest_l = 1#初始化
        res = s[0]

        # 因为只有 1 个字符的情况在最开始做了判断
        # 左边界一定要比右边界小,因此右边界从 1 开始
        for r in range(1, size):
            for l in range(r):
                # 状态转移方程:如果头尾字符相等并且中间也是回文
                # 在头尾字符相等的前提下,如果收缩以后不构成区间(最多只有 1 个元素),直接返回 True 即可
                # 否则要继续看收缩以后的区间的回文性
                # 重点理解 or 的短路性质在这里的作用
                if s[l] == s[r] and (l-r>=-2 or dp[l + 1][r - 1]):
                    dp[l][r] = True
                    cur_len = r - l + 1
                    if cur_len > longest_l:
                        longest_l = cur_len
                        res = s[l:r + 1]
            # 调试语句
            # for item in dp:
            #     print(item)
            # print('---')
        return res

10、892-三维形体的表面积

参考:https://unclegem.cn/2018/08/27/Leetcode%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0-892-%E4%B8%89%E7%BB%B4%E5%BD%A2%E4%BD%93%E7%9A%84%E8%A1%A8%E9%9D%A2%E7%A7%AF/

def surfaceArea(self, grid):
    """
    :type grid: List[List[int]]
    :rtype: int
    """
    area = 0
    for i in range(len(grid)):
        for j in range(len(grid[0])):
            if grid[i][j] > 0:
                area += 4 * grid[i][j] + 2
            if i > 0:
                area -= 2 * min(grid[i][j], grid[i - 1][j])
            if j > 0:
                area -= 2 * min(grid[i][j], grid[i][j - 1])
    return area

11、1042. 不邻接植花

本来以为是图着色?后来发现题中限制一个节点的度最多就为3,而颜色一共有4种,也就是一定可以染上色,这样我们先把图构造出来,然后遍历每个节点的邻节点,当前节点+邻节点最多四个,这样就用邻节点没有用过的一个颜色将当前节点染色即可。

class Solution:
    def gardenNoAdj(self, N: int, paths: List[List[int]]) -> List[int]:
        
        graph=[[] for _ in range(N)]
        
        for path in paths:
            graph[path[0]-1].append(path[1]-1)
            graph[path[1]-1].append(path[0]-1)
            
        res=[0 for i in range(N)]
        
        for i in range(N):
            res[i]=({1,2,3,4}-{res[j] for j in graph[i]}).pop()
        
        return res

12、困于环中的机器人

https://blog.csdn.net/qq_32424059/article/details/90140487

13、2. 两数相加 

https://blog.csdn.net/qq_32424059/article/details/90708493

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值