簡體   English   中英

子集和負值

[英]Subset sum negative values

我想知道如何處理負值和負目標,現在我的程序會在給這些變量賦予負值時給出索引越界錯誤。 我需要我的 hasSum 函數為這個項目使用負值,我不能只是假設為正值。

import java.util.Stack;
import java.util.Scanner;

public class subsetSum {
    static Scanner input = new Scanner(System.in);
    static {
        System.out.print("Enter the target  (T)" + "\n");
    }

    /** Set a value for target sum */
    static int TARGET_SUM = input.nextInt(); //this is the target 

    /** Store the sum of current elements stored in stack */
    static int sumInStack = 0;

    Stack<Integer> stack = new Stack<Integer>();

    public static void main(String[] args) {

        //the size is S
        System.out.println("\n" + "Enter the size of the set (S)");
        int values = input.nextInt(); //size = "values"

        //value of each size entry
        System.out.println("\n" + "Enter the value of each entry for S");

        int [] numbers = new int[values];

        for(int i = 0; i < values; i++) //for reading array
        {
            numbers[i] = input.nextInt();                 
        }

        if(hasSum(numbers, TARGET_SUM)){
            System.out.println("\n" + "Can: ");
            subsetSum get = new subsetSum(); // encapsulation
            get.populateSubset(numbers, 0, numbers.length); 
        }else{
            System.out.println("\n" + "Cannot");
        }
    }

    //method based on dynamic programming O(sum*length)
    public static boolean hasSum(int [] array, int sum)
    {
        int i;
        int len = array.length;
        boolean[][] table = new boolean[sum + 1][len + 1]; //this has to be changed for negative

        //If sum is zero; empty subset always has a sum 0; hence true
        for(i = 0; i <= len; i++){
            table[0][i] = true;
        }

        //If set is empty; no way to find the subset with non zero sum; hence false
        for(i = 1; i <= sum; i++){
            table[i][0] = false;
        }

        //calculate the table entries in terms of previous values
        for(i = 1; i <= sum; i++)
        {
            for(int j = 1; j <= len; j++)
            {
                table[i][j] = table[i][j - 1]; 
                if(!table[i][j] && i >= array[j - 1]){
                    table[i][j] = table[i - array[j - 1]][j - 1];
                }
            }
        }     
        return table[sum][len]; //this has to be changed for negative
    }

    public void populateSubset(int[] data, int fromIndex, int endIndex) {
        /*
         * Check if sum of elements stored in Stack is equal to the expected
         * target sum.
         * 
         * If so, call print method to print the candidate satisfied result.
         */
        if (sumInStack >= TARGET_SUM) {
            if (sumInStack == TARGET_SUM) {
                print(stack);
            }
            // there is no need to continue when we have an answer
            // because nothing we add from here on in will make it
            // add to anything less than what we have...
            return;
        }

        for (int currentIndex = fromIndex; currentIndex < endIndex; currentIndex++) {
            if (sumInStack + data[currentIndex] <= TARGET_SUM) {
                stack.push(data[currentIndex]);
                sumInStack += data[currentIndex];
                /*
                 * Make the currentIndex +1, and then use recursion to proceed
                 * further.
                 */
                populateSubset(data, currentIndex + 1, endIndex);
                sumInStack -= (Integer) stack.pop();
            }
        }
    }

    /**
     * Print satisfied result. i.e. 5 = 1, 4
     */
    private void print(Stack<Integer> stack) {
        StringBuilder sb = new StringBuilder();
        for (Integer i : stack) {
            sb.append(i).append(",");
        }
        // .deleteCharAt(sb.length() - 1)
        System.out.println(sb.deleteCharAt(sb.length() - 1).toString());
    }
}

你想找到一個子集或一個數組的總和嗎?
如果是一個子集,那么一個簡單的遞歸就可以解決問題,例如:

public static boolean hasSum(int [] array, int sum)
{
    return hasSum(array, 0, 0, sum);
}

private static boolean hasSum(int[] array, int index, int currentSum, int targetSum) {
    if (currentSum == targetSum)
        return true;
    if (index == array.length)
        return false;
    return hasSum(array, index + 1, currentSum + array[index], targetSum) || // this recursion branch includes current element
           hasSum(array, index + 1, currentSum, targetSum); // this doesn't
}

如果你想找到一個subarray ,我會使用前綴 sums ,例如:

public static boolean hasSum(int [] array, int sum)
{
    int[] prefixSums = new int[array.length];
    for (int i = 0; i < prefixSums.length; i++) {
        prefixSums[i] = (i == 0) ? array[i] : array[i] + prefixSums[i - 1];
    }

    for (int to = 0; to < prefixSums.length; to++) {
        if (prefixSums[to] == sum)
            return true; // interval [0 .. to]
        for (int from = 0; from < to; from++) {
            if (prefixSums[to] - prefixSums[from] == sum)
                return true; // interval (from .. to]
        }
    }
    return false;
}

順便說一句,我認為從靜態初始化Scanner讀取輸入值是一個壞主意,為什么不將它們移動到main()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM