【问题标题】:Find all combinations in an array查找数组中的所有组合
【发布时间】:2017-07-02 10:33:26
【问题描述】:

我正在使用 Java 在 Android Studio 中开发游戏,但我在计算分数的方法上遇到了一些问题。基本上在游戏中我有一个骰子数组,其值从 1 到 6。在这些值中,我需要找出特殊值出现的次数。

现在我有一种方法可以很好地查找所有单个值(如所有值为 5 的骰子),以及两个骰子加起来为特殊值(如 2 + 3 或 1 + 4)。但是当两个以上的骰子相加时(如1 + 1 + 3),它不会找到特殊值

示例:如果我有值 [1, 2, 2, 2, 3, 5] 的骰子 结果应该是三个“numberOfPairs”(1+2+2、2+3、5),因此该方法应该返回 15,但对我来说它只返回 10。

我真的很感激一些想法如何改变这种方法以更好地工作。

这是我现在一直在研究的方法:

public static int evaluatePoints(Dice dices[], int sumToReach) {
    int values[] = new int[dices.length];
    int numberOfPairs = 0;
    int left = 0;
    int right = values.length - 1;

    for(int i = 0; i < dices.length; i++){
            values[i] = dices[i].getValue();
            if(values[i] == sumToReach){
                numberOfPairs++;
                values[i] = 0;
            }

    }

    Arrays.sort(values);

    while (values[right] > sumToReach + values[0]) {
        right--;
    }

    while (left < right) {
        if (values[left] + values[right] == sumToReach) {
            numberOfPairs++;
            left++;
            right--;
        }
        else if(values[left] + values[right]  < sumToReach) {
            left++;
        }
        else right--;
    }
    return numberOfPairs*sumToReach;
}

【问题讨论】:

  • 请在minimal reproducible example 上发布失败的Dice dices[] 示例
  • @c0der 示例:我正在寻找值 5。如果我有值 [1, 2, 2, 2, 3, 5] 的骰子,结果应该是三个“numberOfPairs”(1+2+2、2+3、5),因此该方法应该返回 15,但是对我来说它只返回 10。
  • 如果考虑所有组合1+2+2应该出现两次,2+3应该出现两次,3+2应该出现3次,2+2+1也是一个有效的组合
  • 您想要一个组合吗?我的意思是对于一个三元组,只有一个三元组还是所有可能存在的三元组?
  • @VidorVistrom 所以基本上在游戏中我的玩家掷了六个骰子,然后游戏应该从这些骰子中计算出这些骰子中有多少加起来是一个特殊的数字。但是每个骰子只能使用一次。因此,如果骰子变为 [1, 2, 2, 2, 3, 5] 并且搜索到的值为 5,那么我希望该方法输出存在 3 个子集加起来为 5(1 + 2 + 2 和 2 + 3 和 5。不是 3 + 2 等,因为所有骰子都已经用过了)

标签: java arrays subset


【解决方案1】:

您的问题可以解释为“将所有可能的数字表示形式作为其他自然数的总和”。 Here 是很好的解决方案。

【讨论】:

  • 对不起,如果我完全误解了你,但是当你有一个数字并且你想找到所有可能的组合时,这种方法不好吗?在我的问题中,我有一个数字数组,我需要将这些值加起来形成一个数字的组合。但也许你的意思是我应该使用这种技术并改变它?
  • 是的。有区别。例如,从 1 到最大值的所有数字,在您的情况下,您应该只从某个数字数组中获取数字。基本上,您可以用遍历您的数字数组的循环替换 for 循环,将 max 迭代为 1。
【解决方案2】:

算法说明:

Suppose the input array is [1 2 2 2 3 5]

First the program will search for grpSize 6 i.e. 6 elements that sum upto sum of 5
Then the program will search for grpSize 5 i.e. 5 elements that sum upto sum of 5
.
.
.
then the program will search for grpSize 1 i.e. 1 element that sums upto sum of 5

If a set is found then elements will be removed from the resultList

Warning: This approach is recursive, may lead to stack overflow if number of dice increases manyfold

public static boolean func(int grpSize,int sum,int index,List<Integer> resultList,ArrayList<Integer> values) {
  if(grpSize==1) {
       int j;
       for(j = index; j < resultList.size(); j++) {
           if(resultList.get(j) == sum) {
               values.add(resultList.get(j));
               resultList.remove(j);
               return true;
           }
       }
   }

   for(; index < resultList.size(); index++) {
       if(func(grpSize-1, sum-resultList.get(index), index+1, resultList, values)) {
           values.add(resultList.get(index));
           resultList.remove(index);
           return true;
       }
  }
  return false;   
}


public static void main(String[] args) {
    List<Integer> resultList = new ArrayList<>();
    ArrayList<ArrayList<Integer>> values = new ArrayList<>();

    resultList.add(1);
    resultList.add(2);
    resultList.add(2);
    resultList.add(2);
    resultList.add(3);
    resultList.add(5);
    //3 2 2 2 3 5

    int sum = 5;    
    int n = resultList.size();

    for(int i = 0; i < n; i++) {
        int k=i;
        while(true) {
            values.add(new ArrayList<>());
            func(n-i, sum, 0, resultList, values.get(values.size() - 1));
                if(values.get(k).isEmpty()) {
                    break;
                } else {
                    k++;
                }
            }
        }

        values.removeIf(p -> p.isEmpty());

        System.out.println("Number of pairs: "+values.size());

        values.forEach((it) -> {
            System.out.println(it);
        });

        int temp = 0;

        for(int i = 0; i < values.size(); i++) {
            for(int j = 0; j < values.get(i).size(); j++) {
                temp += values.get(i).get(j);
            }
        }
        System.out.println("sum: "+temp);
    }
}

递归函数的工作原理:

此功能需要

  • 要搜索的组大小
  • 要搜索的总和
  • 始终为零的起始索引(可以(应该)清理)
  • 每个骰子的列表
  • 添加找到值的列表

这是一个布尔函数,如果发现一个特定的集合加起来等于 THE SUM,它将返回 true。这个概念是基本的Backtracking

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-08-10
    • 1970-01-01
    • 2017-01-31
    • 2013-04-25
    • 2020-10-21
    • 1970-01-01
    • 2018-08-18
    相关资源
    最近更新 更多