![](/img/trans.png)
[英]Given an array of integers and a sum, the task is to find if there exists a subsets of given array with sum equal to given sum
[英]How to find subsets that contains equal sum in an array:
如何在數組中查找包含相等總和的子集。 例如
{1,2,3,4,2}->{1,2,3} && {4,2}
{1,1,3,3,2,8}->{1,3,3,2}&&{1,8}
{1,3,4,7}->no subset
我嘗試使用下面的代碼,但沒有獲得適當的輸出。
import java.util.*
public static void main(String[] args) {
int arr[] = {1,3,4,7};
int sum = getSum(arr, arr.length);
int[] solution = new int[arr.length];
find(arr, 0, 0, sum, solution);
}
public static int getSum(int arr[], int n) {
float sum = 0f;
for (int i = 0; i < n; i++)
sum = sum + arr[i];
return Math.round(sum / 2);
}
public static void find(int[] A, int currSum, int index, int sum,
int[] solution) {
if (currSum == sum) {
System.out.println("\nSum found");
for (int i = 0; i < solution.length; i++) {
if (solution[i] == 1) {
System.out.print(" " + A[i]);
}
}
} else if (index == A.length) {
return;
} else {
solution[index] = 1;// select the element
currSum += A[index];
find(A, currSum, index + 1, sum, solution);
currSum -= A[index];
solution[index] = 0;// do not select the element
find(A, currSum, index + 1, sum, solution);
}
return;
}
這個輸入數組:1,2,3,4,2低於輸出
1 2 3
1 3 2
2 4
4 2
輸入數組:1,1,3,3,2,8
1 3 3 2
1 8
1 3 3 2
1 8
輸入數組:1、3、4、7
1 3 4
1 7
要解決此問題,您的代碼中至少需要3個嵌套循環,sudocode就像
for (i=0,i< array.length-1,i++){
for(k=i;k<array.length-1,k++){
fsum=findSum(i/*from*/,k/*to*/,array);
ssum=0;
for(x=k,x<array.length,x++){
secondsum=findSum(k,x,array);
if(fsum==ssum){
prend(i,k,array);
print(k,x,array);
break;
}
}
}
}
請注意,這只是需要執行的sudo代碼
您的代碼的重復部分工作正常。 在相當外圍的部分中只有兩個小缺陷:
僅當數字之和為偶數時,這兩個子集才存在。 您的代碼未考慮此要求,這是有關{1,3,4,7}失敗的原因。 為此,對主函數的主體進行了一些修改,以便僅對偶數和執行重復操作。
您應該對重復項進行分類,以防止重復與{1,2,3,4,2}和{1,1,3,3,2,8}有關。 為此,必須非常簡單地存儲結果子集。 然后,在消除重復項之后,將剩下的子集打印出來。 為了方便起見,這兩種功能都封裝在添加的SubsetPair類中,該類提供了storeSubsetPair和printSubsetPairList方法分別用於存儲和打印。
修改后的代碼是:
import java.util.*;
public class Main {
public static void main(String[] args) {
int arr[] = {1,3,4,7};
int sum = getSum(arr, arr.length);
int[] solution = new int[arr.length];
// find(arr, 0, 0, sum, solution); // REPLACED WITH: -----------------
if (sum % 2 == 0) {
sum = Math.round(sum / 2f);
find(arr, 0, 0,sum, solution);
}
SubsetPair.printSubsetPairList();
// -------------------------------------------------------------------
}
public static int getSum(int arr[], int n) {
// float sum = 0f; // REPLACED WITH: ---------------------------------
int sum = 0;
// -------------------------------------------------------------------
for (int i = 0; i < n; i++)
sum = sum + arr[i];
// return Math.round(sum / 2); // REPLACED WITH: ---------------------
return sum;
// -------------------------------------------------------------------
}
public static void find(int[] A, int currSum, int index, int sum,
int[] solution) {
if (currSum == sum) {
// System.out.println("\nSum found"); // REPLACED WITH: ----------
// for (int i = 0; i < solution.length; i++) {
// if (solution[i] == 1) {
// System.out.print(" " + A[i]);
// }
// }
SubsetPair.storeSubsetPair(A, solution);
// ---------------------------------------------------------------
} else if (index == A.length) {
return;
} else {
solution[index] = 1;// select the element
currSum += A[index];
find(A, currSum, index + 1, sum, solution);
currSum -= A[index];
solution[index] = 0;// do not select the element
find(A, currSum, index + 1, sum, solution);
}
return;
}
}
//NEW: Class for storage and print:
class SubsetPair {
private static List<SubsetPair> subsetPairList = new ArrayList<>();
private List<Integer> subset1 = new ArrayList<>();
private List<Integer> subset2 = new ArrayList<>();
//
// Storage of the subset pair
//
public static void storeSubsetPair(int[] A, int[] solution) {
SubsetPair subsetPair = new SubsetPair();
for (int i = 0; i < solution.length; i++) {
if (solution[i] == 1) {
subsetPair.subset1.add(A[i]);
} else {
subsetPair.subset2.add(A[i]);
}
}
if (!subsetPair.isDuplicate()) {
subsetPairList.add(subsetPair);
}
}
// Remove duplicates
private boolean isDuplicate() {
for (SubsetPair subsetPair : subsetPairList) {
if (isEqual(subset1, subsetPair.subset2) && isEqual(subset2, subsetPair.subset1) ||
isEqual(subset1, subsetPair.subset1) && isEqual(subset2, subsetPair.subset2)) {
return true;
}
}
return false;
}
private boolean isEqual(List<Integer> subset1, List<Integer> subset2) {
return subset1.containsAll(subset2) && subset2.containsAll(subset1);
}
//
// Output of the subset pairs
//
public static void printSubsetPairList() {
if (subsetPairList.size() == 0) {
System.out.println("No subset-pairs found!");
} else {
for (int i = 0; i < subsetPairList.size(); i++) {
subsetPairList.get(i).printSubsetPair(i + 1);
}
}
}
private void printSubsetPair(int i) {
System.out.print(i + ". Subset-Pair:\n");
System.out.print("Subset 1: ");
for (Integer i1 : subset1) {
System.out.print(i1 + " ");
}
System.out.println();
System.out.print("Subset 2: ");
for (Integer i2 : subset2) {
System.out.print(i2 + " ");
}
System.out.print("\n\n");
}
}
通過這些更改,輸出將變為:
對於{1,2,3,4,2},其和為12:
1. Subset-Pair:
Subset 1: 1 2 3
Subset 2: 4 2
對於{1,1,3,3,2,8,}的偶數為18的情況:
1. Subset-Pair:
Subset 1: 1 3 3 2
Subset 2: 1 8
對於{1,3,4,7},其奇數和為15:
No subset-pairs found!
對於{3,1,1,2,2,1},其和為10:
1. Subset-Pair:
Subset 1: 3 1 1
Subset 2: 2 2 1
2. Subset-Pair:
Subset 1: 3 2
Subset 2: 1 1 2 1
對於{2,4,8},其和為14:
No subset-pairs found!
正如已經在評論中指出的那樣,問題與“分區問題”有關,這是決定是否可以將正整數的多集划分為相等總和的兩個子集的任務。 例如,在https://en.wikipedia.org/wiki/Partition_problem或https://www.geeksforgeeks.org/partition-problem-dp-18/ (后者包括Java實現)中對此進行了詳細說明。 但是,這兩個問題不完全相同 ,因為“分區問題”的解決方案只是回答如果多集可以划分為兩個子集的問題,但並沒有明確確定的子集本身。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.