Leetcode 416. Partition Equal Subset Sum 對半分 解題報告【修正版】
阿新 • • 發佈:2019-02-15
1 解題思路
leetcode才出來的時候,測試用例比較簡單,所以我之前用的是暴力法,而且AC了,後面有人和我說沒法通過了,所以後面我重新做了下,[並且參照了他的思路(](http://blog.csdn.net/liuyue910828/article/details/52792357)
我多了註釋,做個廣告):
現在用了揹包去解決的,首先:
1、依然陣列的和必須要是偶數,否則無法劃分,共計n個數,這裡價值value/weight都等於nums
2、將問題轉化為揹包問題,即取前I個數(物品),和體積j下,dp[i][j]的最大值
dp[i][j]=max{ dp[i-1][j], dp[i-1][j-nums[i]]+nums[i] }。
3、這樣dp[n][sum/2] 如果等於sum/2 就證明用了這n個數下,正好能加出一個sum/2,所以就自然而然的通過了
PS:最後,我突然覺得其實都沒必要用二位陣列了。。。
原來的暴力解法:
其實所謂的對半分,就是一個數組劃分成兩部分,兩部分的和一樣
所以思路:
1、首先陣列的和必須要是偶數,否則無法劃分
2、直接暴力的DFS+回溯,即查詢是否有1/2與陣列和的存在
3、我是用了排序後,DFS時可以剪枝的方式
4、關於3中排序的開銷是否值得,大家自己測試
總之,是一個暴力而簡單的解法
#2 原題
Given a non-empty array containing only positive integers, find if the array can be partitioned into two subsets such that the sum of elements in both subsets is equal.
Note:
Both the array size and each of the array element will not exceed 100.
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
3 DP版 public class Solution {
public boolean canPartition(int[] nums) {
int sum=0;
for (int num:nums) sum+= num;
if(sum % 2 == 1) return false;
else{
sum /=2;
int n=nums.length;
// dp[i][j] 表示 如果我們取前i個數字,且揹包容量為j的情況下,最多能放入多少東西
int dp[][]=new int[n][sum + 1];
// dp[0][0] 為初始狀態,表示,沒有任何沒有東西沒有體積,其餘部分初始化
for(int i=nums[0];i<=sum;i++){
dp[0][i] = nums[0];
}
//遍歷n個數字,即視為n個產品
for(int i=1;i<n;i++){
//加入了這種物品後更新狀態
for(int j=nums[i];j<=sum;j++){
dp[i][j]=Math.max(dp[i-1][j], dp[i-1][j-nums[i]]+nums[i]);
}
}
//放滿了才能表示正好1/2
if(dp[n-1][sum]==sum)
return true;
else
return false;
}
}
}
4 老舊的暴力法 僅供參考 不可AC
我做的比較早,有人評論說超時了,所以我貼個AC的時間出來。AC區很多人的程式碼也都作廢了。。我也無語
我跑了三次,都是10ms
現在的評測已經和我當時的評測不一樣了,所以以下程式碼作廢了!!!
而且現在我找到的好多程式碼,也都是或多或少不是超時就是錯誤,有人提供一個DP的正確解法麼?最近沒時間再做!!
public class Solution {
/**
* 首先和為奇數的過濾
* 其次使用DFS
* 排序後可以剪枝很多情況
* */
public boolean canPartition(int[] nums) {
Arrays.sort(nums);
int sum=0;
for (int num:nums) sum+= num;
if(sum % 2 == 1) return false;
sum/=2;
return dfs(0,sum,nums);
}
// 一一嘗試
public boolean dfs(int index,int sum,int[] nums){
sum -= nums[index] ;
if(sum == 0) return true;
for(int i=index+1;i<nums.length;i++){
if(sum<nums[i]) break;
if(dfs(i,sum,nums)) return true;
}
return false;
}
}