zoukankan      html  css  js  c++  java
  • 416. Partition Equal Subset Sum

    问题:

    给定一组数,请问是否将其分为两个数组,使得二者和相等。

    Note:
    Each of the array element will not exceed 100.
    The array size will not exceed 200.
     
    
    Example 1:
    Input: [1, 5, 11, 5]
    Output: true
    Explanation: The array can be partitioned as [1, 5, 5] and [11].
    
    Example 2:
    Input: [1, 2, 3, 5]
    Output: false
    Explanation: The array cannot be partitioned into equal sum subsets.
    

      

    解法:DP(动态规划) 0-1 knapsack problem(0-1背包问题)

    1.确定【状态】:

    • 可选择的数:前 i 个数
    • 和:s:0~全元素和/2

    2.确定【选择】:

    • 选择当前的数nums[i]
    • 不选择当前的数nums[i]

    3. dp[i][s]的含义:

    前 i 个数中,组成和=s 的可能是否存在。

    4. 状态转移:

    dp[i][s]= OR {

    • 选择 nums[i]:dp[i-1][s-nums[i]]:=前 i-1 个元素可组成和为 s-nums[i] 的可能性
    • 不选择 nums[i]:dp[i-1][s]:=前 i-1 个元素可组成和为 s 的可能性

    }

    5. base case:

    • dp[0][s]=false
    • dp[i][0]=true
    • dp[0][0]=true

    代码参考:

     1 class Solution {
     2 public:
     3     //dp[i][s]: in first i items, sum is s, exists?
     4     //case_1,choose i-th item: dp[i-1][s-val[i]]
     5     //case_2,don't choose: dp[i-1][s]
     6     //dp[i][s] = case_1 OR case_2
     7     //base case: dp[0][s] = false
     8     //dp[i][0] = true
     9     //dp[0][0] = true
    10     bool canPartition(vector<int>& nums) {
    11         bool res;
    12         int sum = 0;
    13         for(int n:nums){
    14             sum+=n;
    15         }
    16         if(sum%2) return false;
    17         sum/=2;
    18         vector<vector<bool>> dp(nums.size()+1, vector<bool>(sum+1, false));
    19         dp[0][0] = true;
    20         for(int i = 1; i<=nums.size(); i++) {
    21             for(int s = 1; s<=sum; s++) {
    22                 if(s-nums[i-1]<0) dp[i][s] = dp[i-1][s];
    23                 else dp[i][s] = dp[i-1][s-nums[i-1]] || dp[i-1][s];
    24             }
    25         }
    26         return dp[nums.size()][sum];
    27     }
    28 };

    ♻️ 优化:空间复杂度:2维->1维

    去掉 i 

    将 s 倒序遍历。

    if(s-nums[i-1]<0) dp[i][s] = dp[i-1][s];
    else dp[i][s] = dp[i-1][s-nums[i-1]] || dp[i-1][s];

    上述状态转移中,i 代表行,s 代表列

    则都为 更新本行 : 使用上一行的 本列前面的列 来计算覆盖本列

    顺序遍历的话,更新后面列的时候,会用到已经被覆盖掉的本列。而我们期望用的是上一行的本列

    因此 将 s 倒序遍历。更新前面的列,用的上一行本列,还未被本行操作更新。

    代码参考:

     1 class Solution {
     2 public:
     3     //dp[i][s]: in first i items, sum is s, exists?
     4     //case_1,choose i-th item: dp[i-1][s-val[i]]
     5     //case_2,don't choose: dp[i-1][s]
     6     //dp[i][s] = case_1 OR case_2
     7     //base case: dp[0][s] = false
     8     //dp[i][0] = true
     9     //dp[0][0] = true
    10     bool canPartition(vector<int>& nums) {
    11         bool res;
    12         int sum = 0;
    13         for(int n:nums){
    14             sum+=n;
    15         }
    16         if(sum%2) return false;
    17         sum/=2;
    18         vector<bool> dp(sum+1, false);
    19         dp[0] = true;
    20         for(int i = 1; i<=nums.size(); i++) {
    21             for(int s = sum; s>0; s--) {
    22                 if(s-nums[i-1]>=0) {
    23                     dp[s] = dp[s-nums[i-1]] || dp[s];
    24                 }
    25             }
    26         }
    27         return dp[sum];
    28     }
    29 };
  • 相关阅读:
    深入浅出Mybatis系列(一)---Mybatis入门
    深入浅出Mybatis系列(十)---SQL执行流程分析(源码篇)
    深入浅出Mybatis系列(九)---强大的动态SQL
    ZK请求处理
    ZK配置文件
    ZK数据同步
    集群间通信的消息类型
    ZK客户端
    Zookeeper崩溃恢复过程(Leader选举)
    Windows编程
  • 原文地址:https://www.cnblogs.com/habibah-chang/p/13581649.html
Copyright © 2011-2022 走看看