簡體   English   中英

給定大量數字,如何找到總和為特定 X 的每個數字組合?

[英]How to find every combination of numbers that sum to a specific X given a large array of numbers?

我有一個很大的整數數組(~3k 項),我想找到每個數字組合的索引,其中所述數字的總和等於 X。如何在程序不花費數年時間執行的情況下執行此操作?

我可以使用以下 Python 代碼找到第一個可能的組合:

def find_numbers_that_sum_to(source_arr, target_number, return_index=True):
    result = []
    result_indices = []
    
    for idx, item in enumerate(source_arr):
        sum_list = sum(result)
        
        assert (sum_list + item) <= target_number
        result.append(item)
        result_indices.append(idx)
        
        if (sum_list + item) == target_number:
            break
    
    return result_indices

但我需要每一種可能的組合。 至少是一種動態生成它們的方法。 我一次只需要其中一個,但如果它給我的索引不符合我需要的另一個標准,我將需要下一組。

不幸的是, 這個問題是 NP-hard ,這意味着目前沒有已知的多項式時間算法。 如果您想將當前代碼與其他實現進行基准測試,這個 SO 問題包含了很多。 這些實現可能更快,但它們的運行時間仍然是指數級的。

好的,所以我知道這不適用於 3000 個值的數組,但我寫了這個並且效果很好。 我不知道 python,抱歉,這里是 c。

#include <stdio.h> 
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>
#include <math.h>

typedef struct {
  int64_t num;
  _Bool free;
} element_t;

element_t input[] = {{5, true}, {2, true}, {5, true}, {-9, true}, {11, true}, {14, true}, {16, true}, {-10, true}, {6, true}, {24, true}, {53, true}, {-46, true}, {34, true}, {19, true}, {7, true}, {55, true}, {69, true}};
int64_t input_size = sizeof(input) / sizeof(element_t);
void printsum() {  
  int64_t i;
  for (i=0; i<input_size; i++) {
    if (!input[i].free) printf("%li(%li) ", input[i].num, i);
  }
  printf("\n");
  return;
}
int64_t getsum() {  
  int64_t i, sum;
  sum = 0;
  for (i=0; i<input_size; i++) {
    if (!input[i].free) sum += input[i].num;
  }
  return sum;
}
void findresults(int64_t target, int64_t current_sum) {
  //if (target < current_sum) return; //NOTE: Comment Out This line If Array Contains -ve Values.
  int64_t i, sum;
  sum = 0;
  for (i=0; i<input_size; i++) {
    if (input[i].free != false) {
      input[i].free = false;
      if (current_sum + input[i].num == target) printsum();
      findresults(target, current_sum + input[i].num);
      input[i].free = true;
    } else {
      return;
    }
  }
}

int main(int argc, char*argv[]) {
  if (argc <= 1) exit(0);
  int64_t target_sum = atol(argv[1]);
  printf("Searching for subsets sums to %li.\n", target_sum);
  findresults(target_sum, 0);
}

這是另一個答案,它可能對您的特定數據集有用。 反過來,從 X 開始。

有一個名為Integer partition的已知問題,意思是找到所有與 X 相加的正整數。

因此,首先將 X 划分為 integer 的集合,然后您可以刪除所有長度超過 N=3k 的集合。 其次,匹配設置回您的 N=3k 數字並查找索引。

從 integer 分區開始的好地方是 Jorg Andt FXT 圖書館和書籍,網址為https://www.jjj.de/

查看https://oeis.org/A000041/graph ,它僅適用於 X 相當小,增長確實呈指數增長(好吧,NP-hard 就是這樣)

暫無
暫無

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

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