首页 > 其他分享 >day43| 1049+494+474

day43| 1049+494+474

时间:2023-05-17 17:24:38浏览次数:46  
标签:target nums neg 1049 range 494 day43 sum dp

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

 

题目简述:

有一堆石头,用整数数组 stones 表示。其中 stones[i] 表示第 i 块石头的重量。

每一回合,从中选出任意两块石头,然后将它们一起粉碎。假设石头的重量分别为 x 和 y,且 x <= y。那么粉碎的可能结果如下:

如果 x == y,那么两块石头都会被完全粉碎;
如果 x != y,那么重量为 x 的石头将会完全粉碎,而重量为 y 的石头新重量为 y-x。
最后,最多只会剩下一块 石头。返回此石头 最小的可能重量 。如果没有石头剩下,就返回 0。

 

思路:

1. 题目转化为背包问题,取数,使得和最接近sum//2,这个最接近的值为maxweight

2. 则最终结果为sum-2*maxweight

 

代码如下:

class Solution:
    def lastStoneWeightII(self, stones: List[int]) -> int:
        total = sum(stones)
        n, m = len(stones), total // 2
        dp = [[False] * (m + 1) for _ in range(n + 1)]
        dp[0][0] = True

        for i in range(n):
            for j in range(m + 1):
                if j < stones[i]:
                    dp[i + 1][j] = dp[i][j]
                else:
                    dp[i + 1][j] = dp[i][j] or dp[i][j - stones[i]]
        
        ans = None
        for maxweight in range(m, -1, -1):
            if dp[n][maxweight]:
                ans = total - 2 * maxweight
                break
        
        return ans

 

 

494. 目标和

 

题目简述:

给你一个整数数组 nums 和一个整数 target 。

向数组中的每个整数前添加 '+' 或 '-' ,然后串联起所有整数,可以构造一个 表达式 :

例如,nums = [2, 1] ,可以在 2 之前添加 '+' ,在 1 之前添加 '-' ,然后串联起来得到表达式 "+2-1" 。
返回可以通过上述方法构造的、运算结果等于 target 的不同 表达式 的数目。

 

思路:

1. 记数组和为sum,添加负号的元素之和为neg,则其余添加正号的元素之和为sum-neg

2. 得到的表达式结果为

        (sum−neg)−neg=sum−2⋅neg=target

3. 则neg=(sum-target)/2

4. 由于数组nums中的元素都是非负整数,neg也必须是非负整数,所以要求sum-target是非负偶数,若不符合条件直接返回0

5. 问题转化为在数组nums中选取若干元素,使得这些元素之和等于neg,计算选取元素的方案数

6. 利用动态规划方法求解

7. 定义二维数组dp,其中dp[i][j]表示在数组nums的前i个数中选取元素,使得这些元素之和等于j的方案数。

8. 假设数组nums的长度为n,则最终答案为dp[n][neg]

9. 没有任何元素可选取,元素和只能为0,对应方案数是1,即dp[0][0]=1,dp[0][j]=0(j>=1)

10. 当1<=i<=n时,对于数组nums中的第i个元素num,遍历0<=j<=neg,计算dp[i][j]的值

  1)如果j<num,则不能选num,又dp[i][j]=dp[i-1][j]

  2)  如果j>=num,为选num和不选num两种情况,总和是dp[i][j]=dp[i-1][j]+dp[i-1][j-num]

11. 最终答案为dp[n][neg]

 

代码如下:

class Solution:
    def findTargetSumWays(self, nums: List[int], target: int) -> int:
        ''' pos + neg = total  '''
        ''' pos - neg = target '''
        total = sum(nums)
        if abs(target) > total:         # target可能为负
            return 0
        if (total + target) % 2 == 1:   # 不能被2整除【对应于pos不是整数】
            return 0
        
        '''【0/1背包】:从nums中选出数字组成pos或neg'''
        pos = (total + target) // 2
        neg = (total - target) // 2
        capcity = min(pos, neg)         # 取pos和neg中的较小者,以使得dp空间最小
        n = len(nums)

        # 初始化
        dp = [[0] * (capcity+1) for _ in range(n+1)]
        # dp[i][j]: 从前i个元素中选出若干个其和为j的方案数
        dp[0][0] = 1        # 其他 dp[0][j]均为0

        # 状态更新
        for i in range(1, n+1):
            for j in range(capcity+1):
                if j < nums[i-1]:       # 容量有限,无法选择第i个数字nums[i-1]
                    dp[i][j] = dp[i-1][j]
                else:                   # 可选择第i个数字nums[i-1],也可不选【两种方式之和】
                    dp[i][j] = dp[i-1][j] + dp[i-1][j-nums[i-1]]
        
        return dp[n][capcity]

 

474. 一和零

 

题目简述:

给你一个二进制字符串数组 strs 和两个整数 m 和 n 。

请你找出并返回 strs 的最大子集的长度,该子集中 最多 有 m 个 0 和 n 个 1 。

如果 x 的所有元素也是 y 的元素,集合 x 是集合 y 的 子集 。

 

思路:

三维dp

1. 定义三维数组dp[i][j][k],表示取数组的前i个元素参加操作,使得0的数量小于等于j,1的数量小于等于k,在这种条件约束下的最长子集

2. 进行分类讨论

 

代码如下:

class Solution:
    def findMaxForm(self, strs: List[str], m: int, n: int) -> int:

        length = len(strs)
        dp = [[[0] * (n+1) for _ in range(m+1)] for _ in range(length+1)]

        for i in range(1, length+1):
            c0 = strs[i-1].count('0')       # 当前字符串中0的数目
            c1 = len(strs[i-1]) - c0        # 当前字符串中1的数目
            for j in range(m+1):            # 第二层循环:0的背包容量
                for k in range(n+1):        # 第三层循环:1的背包容量
                    if j < c0 or k < c1:    # 无法添加当前字符串
                        dp[i][j][k] = dp[i-1][j][k]
                    else:                   # 可选或不选当前字符串,取两者之间的较大值
                        dp[i][j][k] = max( dp[i-1][j][k], dp[i-1][j-c0][k-c1] + 1 )
        
        return dp[length][m][n]

 

标签:target,nums,neg,1049,range,494,day43,sum,dp
From: https://www.cnblogs.com/cp1999/p/17375006.html

相关文章

  • LeetCode 1049. 最后一块石头的重量 II
    思路任何时刻,某个石头的重量永远都是若干石头加减运算的绝对值如a-b+c合并石头都是减法,但仍可能出现+运算符,如a-(b-c)=a-b+c任何一种合并方法,最后一个石头的重量都可以表示成一种代数形式,如a+b-c+d+e+f-g不是所有的代数形式都可以转换为一种合并方法,如a+b+c因此......
  • 7-013-(LeetCode- 494) 目标和
    1.题目读题 考查点 2.解法思路 代码逻辑 具体实现113.总结......
  • ASEMI代理ADI亚德诺ADA4940-1ACPZ-R7车规级芯片
    编辑-ZADA4940-1ACPZ-R7芯片参数:型号:ADA4940-1ACPZ-R7−3dB小信号带宽:260MHz−3dB大信号带宽:25MHz0.1dB平坦度的带宽:14.5MHz斜率:95V/µs超速恢复时间:86ns输入电压噪声:3.9nV/√Hz输入电流噪声:0.81pA/√Hz输入偏移电压:±0.06mV输入失调电流:±50nA输入电阻:33......
  • 洛谷P5494 【模板】线段树分裂
    传送门  需要的前置知识:线段树合并。  感觉会了线段树合并这个就很简单,线段树分裂就是在把一颗权值线段树值域在[x,y]的区间分裂出来单独成一个线段树,那么我们只需要从新树q和旧树p的根节点一起走,如果走到当前p被[x,y]完全包含的路径就把p的编号给q,并且把p改为0就行了,注意......
  • ASEMI代理ADA4940-1ACPZ-R7原装ADI车规级ADA4940-1ACPZ-R7
    编辑:llASEMI代理ADA4940-1ACPZ-R7原装ADI车规级ADA4940-1ACPZ-R7型号:ADA4940-1ACPZ-R7品牌:ADI/亚德诺封装:LFCSP-16批号:2023+引脚数量:16安装类型:表面贴装型ADA4940-1ACPZ-R7汽车芯片ADA4940-1ACPZ-R7特征小信号带宽:260MHz超低功率1.25mA极低谐波失真−122dBTHD,50kHz时1MHz时的......
  • ASEMI代理ADA4940-1ACPZ-R7原装ADI车规级ADA4940-1ACPZ-R7
    编辑:llASEMI代理ADA4940-1ACPZ-R7原装ADI车规级ADA4940-1ACPZ-R7型号:ADA4940-1ACPZ-R7品牌:ADI/亚德诺封装:LFCSP-16批号:2023+引脚数量:16安装类型:表面贴装型ADA4940-1ACPZ-R7汽车芯片ADA4940-1ACPZ-R7特征小信号带宽:260MHz超低功率1.25mA极低谐波失真−122dBTHD,50k......
  • 494. 目标和
    classSolution{public:intf[25][2010];//体积范围从-1000~1000intfindTargetSumWays(vector<int>&nums,inttarget){intn=nums.size(),offset=1000;//价值总和不超过1000,因此偏移量设置1000即可f[0][0+offset]=1;for(inti=1;i<=n;......
  • 决战圣地玛丽乔亚Day43
    Springboot的自动装配原理:@SpringBootApplication  进入 AutoConfigurationImportSelector类中,会调用 selectImports(方法),用于选择需要自动配置的类,并返回它们的......
  • PAT Basic 1049. 数列的片段和
    PATBasic1049.数列的片段和1.题目描述:给定一个正数数列,我们可以从中截取任意的连续的几个数,称为片段。例如,给定数列{0.1,0.2,0.3,0.4},我们有(0.1)(0.1,0.2)......
  • 494.Target Sum
    Youaregivenalistofnon-negativeintegers,a1,a2,...,an,andatarget,S.Nowyouhave2symbols + and -.Foreachinteger,youshouldchooseonefro......