代码随想录算法训练营第四十三天|1049. 最后一块石头的重量 II, 494. 目标和,474.一和零

1049. 最后一块石头的重量 II 

https://leetcode.com/problems/last-stone-weight-ii/description/

思路:两块石头可以互相湮灭, 可以认为其是就是把所有的石头分成正负两组的符号。 例如石头是 [2, 4, 5], 可以认为最后最小的重量是 -(5-4) + 2 = +4 +2 -5 的组合。 那么要求这个问题, 可以回到01背包问题上了,设容量为 sum(stones) // 2 的背包, 看最大可以装多少重量的石头 设为x, 结果就是  sum(stones) - 2x。

难点: 思路上的转化

class Solution:
    def lastStoneWeightII(self, stones: List[int]) -> int:
        half = sum(stones) / 2
        print(half)
        dp = [[0] * (int(half) + 1) for _ in range(len(stones) + 1)]
        for i in range(1, len(dp)):
            for j in range(1, len(dp[0])):
                if stones[i-1] > j:
                    dp[i][j] = dp[i-1][j]
                else:
                    dp[i][j] = max(dp[i-1][j], dp[i-1][j-stones[i-1]] + stones[i-1])
        return int(2 * (half - dp[-1][-1]))

494. 目标和

https://leetcode.com/problems/target-sum/description/

思路:给定一个数组 nums 和 一个目标值 target。给数组的元素添加正负号, 问有多少种组合方式可以让数组的元素组合出目标值。 我们假设把数组的 的元素氛围pos 和 neg 组, sum(pos) + sum(neg) = sum(nums), sum(pos) - sum(neg) = target. 那么我们要找的其实就是sum(pos) = (sum(nums) + target) / 2 的组合方式。 然后问题转化成填满一个 (sum(nums) + target) / 2 的背包有多少方法。 注意这里是找组合方法, 所以明确dp数组的值表示的组合方法, 那么可以找到递推关系 dp[i][j] = dp[i-1][j] + dp[i-1][j-nums[i-1]]. 其中 dp[i-1][j]表示不放入i个元素可以填满j个背包的方法, dp[i-1][j-nums[i-1]]表示放入j 可以填满的方法。一维的关系就是 dp[i] += dp[i-nums[i-1]]. 然后数组的[0] 位置放入1, 表示[0] 有一种方法填满0容量的背包。

难点: 这个题怎么转变成背包问题我一开始是没想明白的, 看了卡哥的文档思路才恍然大悟。

class Solution:
    def findTargetSumWays(self, nums: List[int], target: int) -> int:
        '''
        total_pos - total_neg = target
        total_pos + total_neg = total_nums
        the question equivlant to how many ways to pack a package of capacity total_pos with nums. 
        '''
        if (sum(nums) + target) % 2 !=0 or abs(target) > sum(nums):
            return 0
        total_pos = int((sum(nums) + target) / 2)
        dp = [0] * (total_pos + 1)
        dp[0] = 1
        for num in nums:
            for i in range(total_pos, num-1, -1):
                dp[i] += dp[i-num] 
        return dp[-1]

474.一和零  

https://leetcode.com/problems/ones-and-zeroes/submissions/1201733711/

思路: 这个问题是一个更多维度的01背包问题, 首先明确问题要找的是满足条件的最大subset。 然后明确dp 数组中的值应该是最大subset 里面元素的个数。 然后回到01背包的问题中来, 当我们看到某个元素, 如果放进背包中, 那么它的最大元素个数就等于背包容量减去它分别占的 0, 1 的容量的最大元素个数加一, 或者不放入元素,等于前一个同位置的dp。 它和传统的01背包问题不同的是么传统的背包只有重量或者体积 这一个维度的容量, 但是这个问题有两维度。

难点: 要把一维的拓展到两维去考虑问题。

class Solution:
    def findMaxForm(self, strs: List[str], m: int, n: int) -> int:
        dp = [[0] * (m + 1) for _ in range(n+1)]
        for s in strs:
            c = Counter(s)
            for i in range(n, c['1']-1, -1):
                for j in range(m, c['0']-1, -1):
                    dp[i][j] = max(dp[i-c['1']][j-c['0']]+1, dp[i][j])
        return dp[-1][-1]
第二十二天的算法训练营主要涵盖了Leetcode题目中的三道题目,分别是Leetcode 28 "Find the Index of the First Occurrence in a String",Leetcode 977 "有序数组的平方",和Leetcode 209 "长度最小的子数组"。 首先是Leetcode 28题,题目要求在给定的字符串中找到第一个出现的字符的索引。思路是使用双指针来遍历字符串,一个指向字符串的开头,另一个指向字符串的结尾。通过比较两个指针所指向的字符是否相等来判断是否找到了第一个出现的字符。具体实现的代码如下: ```python def findIndex(self, s: str) -> int: left = 0 right = len(s) - 1 while left <= right: if s[left == s[right]: return left left += 1 right -= 1 return -1 ``` 接下来是Leetcode 977题,题目要求对给定的有序数组中的元素进行平方,并按照非递减的顺序返回结果。这里由于数组已经是有序的,所以可以使用双指针的方法来解决问题。一个指针指向数组的开头,另一个指针指向数组的末尾。通过比较两个指针所指向的元素的绝对值的大小来确定哪个元素的平方应该放在结果数组的末尾。具体实现的代码如下: ```python def sortedSquares(self, nums: List[int]) -> List[int]: left = 0 right = len(nums) - 1 ans = [] while left <= right: if abs(nums[left]) >= abs(nums[right]): ans.append(nums[left ** 2) left += 1 else: ans.append(nums[right ** 2) right -= 1 return ans[::-1] ``` 最后是Leetcode 209题,题目要求在给定的数组中找到长度最小的子数组,
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值