首先來一個別人的代碼
執行結果:
通過
顯示詳情
執行用時 :1 ms, 在所有 Java 提交中擊敗了99.44% 的用戶
內存消耗 :37.5 MB, 在所有 Java 提交中擊敗了15.95%的用戶
題目:
給定一個只包含正整數的非空數組。是否可以將這個數組分割成兩個子集,使得兩個子集的元素和相等。
注意:
每個數組中的元素不會超過 100
數組的大小不會超過 200
示例 1:
輸入: [1, 5, 11, 5]
輸出: true
解釋: 數組可以分割成 [1, 5, 5] 和 [11].
來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/partition-equal-subset-sum
著作權歸領釦網絡所有。商業轉載請聯繫官方授權,非商業轉載請註明出處。
思路:
有很多解法都是嘗試的01揹包問題,但是速度很慢,然後我又找到了一個回溯算法+剪枝,速度還可以
代碼:
class Solution {
public boolean canPartition(int[] nums) {
int sum = 0;
for (int num : nums) {
sum += num;
}
//和爲奇數,肯定不能分割爲兩個和相等的子集
if (sum % 2 != 0) {
return false;
}
sum /= 2;
//將數組做降序排序,是爲了可以進行剪支,避免無用的查找
Arrays.sort(nums);
reverse(nums);
return canPartition(nums, sum, 0);
}
//翻轉數組
public void reverse(int[] data) {
for (int left = 0, right = data.length - 1; left < right; left++, right--) {
// swap the values at the left and right indices
int temp = data[left];
data[left] = data[right];
data[right] = temp;
}
}
private boolean canPartition(int[] nums, int sum, int index) {
if (index >= nums.length || nums[index] > sum) {
return false;
}
if (nums[index] == sum) {
return true;
}
//對於數組每個元素,都有選擇和不選擇兩種可能。
return canPartition(nums, sum - nums[index], index + 1)||canPartition(nums, sum, index + 1) ;
}
}
根據他人的代碼弄了出來,不過感覺其中的reverse沒有什麼必要,因爲從尾部往前索引是一樣的,所以,改了一下代碼,想提升一下效率,可是卻出現了問題,100,100,100.。。。100這個用例通過不了,多次檢查代碼沒什麼問題,可就是不能通過,難受。
我自己的代碼:
class Solution {
public boolean canPartition(int[] nums) {
int sum=0;
for(int num:nums)
{
sum+=num;
}
if(sum%2!=0)
{
return false;
}
sum=sum/2;
Arrays.sort(nums);
return traceback(nums,sum,nums.length-1);
}
public boolean traceback(int[] nums,int sum,int index)
{
if(index<0||nums[index]>sum)
{
return false;
}
if(nums[index]==sum)
{
return true;
}
return traceback(nums,sum,index-1)||traceback(nums,sum-nums[index],index-1);
}
}