• 最后一块石头的重量 II


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

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

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

    示例 1:

    输入:stones = [2,7,4,1,8,1]
    输出:1
    解释:
    组合 2 和 4,得到 2,所以数组转化为 [2,7,1,8,1],
    组合 7 和 8,得到 1,所以数组转化为 [2,1,1,1],
    组合 2 和 1,得到 1,所以数组转化为 [1,1,1],
    组合 1 和 1,得到 0,所以数组转化为 [1],这就是最优值。
    

    示例 2:

    输入:stones = [31,26,33,21,40]
    输出:5
    

    示例 3:

    输入:stones = [1,2]
    输出:1
    

    错误解法

    ​ 每次都将最大和次大的石头进行消除,此目的在于每次都将最大的石头消除。解法为:每次循环之前先将数组进行从小到大排序,然后取最大和次大的相减,将得到的值重新放入到数组中,并且将最大和次大的值从数组中删除。直到数组的长度等于1或者零,结束循环。

    func lastStoneWeightII(stones []int) int {
    	if len(stones)==0 {
    		return 0
    	}
    
    	if len(stones)==1{
    		return stones[0]
    	}
    	sort.Ints(stones)
    	a := len(stones)-1
    	b := a - 1
    	tmp := 0
    	tmp = stones[a] -stones[b]
    	if tmp!=0{
    		stones = stones[:len(stones)-2]
    		stones = append(stones,tmp)
    	}
    	return lastStoneWeightII(stones)
    }
    

    结果错误:一种情况是,当出现两个最大的时候,然后其他的又比较靠近的时候,这种解法就会出现错误。

    正确解法

    ​ 从计算表达式上看,结合减数和被减数,只要这两个值相减的结果越小越好。假设减数为n,则被减数为sum-n。因此所求的结果为:sum-2n。因此我们只要求出n越接近sum/2越好。对于从一堆数组中求出越接近n的问题跟01背包问题的解法一样。

    dp[i]/[j]表示前i个数能凑成和不超过j的最大值。每个物品都有选和不选的两种决策。对于前i(从1开始)个物品来说,如果stones[i-1]>j的话,此时的dp[i]/[j] = dp[i-1]/[j],即不选。如果前i个物品,如果stones[i-1] <= j,此时可以选和可以不选,我们只要这两个决策中的最大值:dp[i]/[j] = max(dp[i-1]/[j],dp[i-1]/[j-stons[i-1]]+stones[i-1])。

    代码实现:

    package main
    
    import (
    	"log"
    )
    
    func lastStoneWeightII(stones []int) int {
    	sum :=0
    	for i:=0;i<len(stones);i++{
    		sum += stones[i]
    	}
    	sum2 := sum / 2
    	dp := make([][]int,len(stones)+1)
    	for i:=0;i<len(dp);i++{
    		dp[i] = make([]int,sum2+1)
    	}
    	n := len(stones)
    	for i:=1;i<=n;i++{
    		for j:=0;j<=sum2;j++{
    				if j<stones[i-1]{
    				dp[i][j] = dp[i-1][j]
    				}else if j>=stones[i-1] {
    					// 这里有点迷惑:为什么是取最大值呢
    					dp[i][j] = max(dp[i-1][j],dp[i-1][j-stones[i-1]] + stones[i-1])
    				}
    		}
    	}
    	return sum - 2 * dp[n][sum2]
    }
    
    func max(a,b int)int{
    	if a>b{
    		return a
    	}
    	return b
    }
    
    func main(){
    	log.Println(lastStoneWeightII([]int{31,26,33,21,40}))
    }
    
    
  • 相关阅读:
    SQL一条语句统计记录总数及各状态数
    火狐登录国际账户
    HTML基础笔记
    增强for、lambda for、stream 遍历List 结束方法 or 跳过循环本次循环
    nginx
    前端问题总结
    Node.js
    Actuator
    ssh免密登录实现及Python实现
    【Mac渗透测试】之SQL注入Demo
  • 原文地址:https://www.cnblogs.com/MyUniverse/p/14862514.html
Copyright © 2020-2023  润新知