【问题标题】:Generate combinations of k numbers in an array with ordering constraints在具有排序约束的数组中生成 k 个数字的组合
【发布时间】:2020-03-19 09:56:57
【问题描述】:

这是我的期中考试题之一。

请跟踪以下程序。修改这个程序,写一个递归程序int combinations(A, n, k),可以打印出所有的 存储在数组A 中的n 不同数字中的k 数字的组合,附加规则如下:

(1) A[0], A[1], ..., A[n-1] 的顺序必须保留并且

(2) 这些k 数字的顺序必须是递增的。

例如,假设有四个数字4, 1, 2, 3 存储在数组int A[4] 中。调用此递归函数combinations(A, 4, 2) 将返回计数3 并打印出(1, 2)(1, 3)(2, 3),或者调用combinations(A, 4, 3) 将返回计数1 并打印出(1, 2, 3)

您的递归程序必须考虑避免不必要的递归函数调用。

老师给出以下代码作为提示:

#include <stdio.h>
#define N 4
int boolfunc(int *var, int m);
int recursivebool(int *var, int n);
int main(){
    int varbool[20];
    recursivebool(varbool, N);
}
int boolfunc(int *var, int m){
    int result=var[0], i;
    for (i=1; i<m; i++) result = (result && var[i]);
    return result;
}

int recursivebool(int *var, int n){
    int localvar[20], i, j;
    if (n == 0){
        for(i=0; i<N; i++) printf("%d ", var[i]);
        printf("%d\n", boolfunc(var, N));
        return;
    }
    for (j=0; j<=1; j++) {
        var[n-1] = j;
        recursivebool(var, n - 1);
    }
}

如果我们运行这个程序,我们可以得到如下输出:

0 0 0 0 0
1 0 0 0 0
0 1 0 0 0
1 1 0 0 0
0 0 1 0 0
1 0 1 0 0
0 1 1 0 0 
1 1 1 0 0
0 0 0 1 0
1 0 0 1 0
0 1 0 1 0
1 1 0 1 0
0 0 1 1 0
1 0 1 1 0
0 1 1 1 0
1 1 1 1 1

我可以理解提示程序。我需要使用这个概念来写int combination(int *A, int n, int k),就像问的问题一样。据我所知,如果k 是 2,我可以使用这个概念来找到两个 1 和两个 0 的场景,如下所示:

1 1 0 0
1 0 1 0
1 0 0 1
0 1 1 0
0 1 0 1
0 0 1 1

然后,我们可以从对应的索引 1 中找到数字,并检查这些数字是否按升序排列。

我非常努力地解决了这个问题。但这太难了。

【问题讨论】:

    标签: c recursion combinations


    【解决方案1】:

    您可以将其视为一个简单的约束满足问题,并使用递归回溯来解决约束。

    正如你提到的,我们可以天真地生成所有可能的组合,然后追溯选择我们想要的组合,但是我们做了很多无用的工作,而这些工作被分配正确地禁止了。

    一种解决方案是在检测到违反约束时立即中断递归搜索并尝试不同的可能性。如果我们达到了满足序列的所有约束的点,我们打印结果。理想情况下,我们会返回一组结果,但不必这样做可以更轻松地专注于算法。

    就满足约束而言,我们可以通过使用start 索引来满足i &lt; j 要求。如果我们将一个数字添加到正在进行的结果中,则结果数组必须为空,或者数组尾部的现有元素小于我们尝试添加的元素。除此之外,我们还有 k 的基本案例。

    #include <stdio.h>
    
    void print_arr(int len, int *a);
    
    int combinations_recurse(int *a, int n, int k, int *selected, 
                             int selected_len, int start) {
        if (selected_len == k) {
            print_arr(selected_len, selected);
            return 1;
        }
    
        int selected_count = 0;
    
        for (int i = start; i < n; i++) {
            if (!selected_len || selected[selected_len-1] < a[i]) {
                selected[selected_len] = a[i];
                selected_count += combinations_recurse(a, n, k, 
                    selected, selected_len + 1, start + 1);
            }
        }
    
        return selected_count;
    }
    
    int combinations(int *a, int n, int k) {
        int selected[n];
        return combinations_recurse(a, n, k, selected, 0, 0);
    }
    
    int main() {
        int a[] = {4, 1, 2, 3};
        printf("count: %d\n\n", combinations(a, 4, 2));
        printf("count: %d\n", combinations(a, 4, 3));
        return 0;
    }
    
    void print_arr(int len, int *a) {
        printf("[");
        for (int i = 0; i < len - 1; printf("%d, ", a[i++]));
        if (len) printf("%d]\n", a[len-1]); 
        else puts("]");
    }
    

    输出:

    [1, 2]
    [1, 3]
    [2, 3]
    count: 3
    
    [1, 2, 3]
    count: 1
    

    【讨论】:

      猜你喜欢
      • 2021-01-30
      • 1970-01-01
      • 2018-04-19
      • 1970-01-01
      • 1970-01-01
      • 2015-09-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多