【问题标题】:how to generate the following sequence?如何生成以下序列?
【发布时间】:2013-02-23 07:12:42
【问题描述】:

我要生成以下序列:

set S = {1,2,3}
op = {{1,2},{1,3},{2,3}}

set S = {1,2,3,4}
op = {{1,2,3},{1,2,4},{1,3,4},{2,3,4}}

set S = {1,2,3,4,5}
op = {{1,2,3,4},{1,2,3,5},{1,2,4,5},{1,3,4,5},{2,3,4,5}}

一般来说,给定一组 n 个数字,我必须找到 (n-1) 个数字的所有可能子集,并限制它们按字母顺序(数字按顺序排列)。

是否有任何算法或方法来解决特定问题?我知道我们可以使用递归来生成更小的子集。

【问题讨论】:

    标签: algorithm permutation combinations apriori


    【解决方案1】:

    只有n 这样的子集;每个都带有从原始集合中删除的n 原始数字之一。因此,对集合进行排序,并为每个数字创建一个集合,该集合是删除该数字的原始集合。

    一个可能的警告是,如果原始集合中有重复的数字,您将只有与原始集合中的唯一数字一样多的子集,因此在这种情况下可能少于 n

    【讨论】:

      【解决方案2】:

      某些语言内置了此功能。例如 Python 的itertools.combinations() method。在你的情况下:

      >>> import itertools
      >>> l = [1,2,3,4]
      >>> combinations = itertools.combinations(l, len(l) -  1) #for the list of numbers l, for sublists with a length 1 less than l's length
      >>> for comb in combinations:
      ...     print comb
      ...
      (1, 2, 3)
      (1, 2, 4)
      (1, 3, 4)
      (2, 3, 4)
      >>>
      

      但是,如果您想自己实现它,上面的链接可能仍然有用,因为它显示了等效代码。您可以使用此代码以任何语言制作您自己的实现。

      【讨论】:

        【解决方案3】:

        这应该很简单。让 arr 具有 sorted 集,n 是元素的数量:

        int arr[100];
        int n;
        printf("{");
        for (int i = n - 1; i >= 0; i--){
            printf("{");
            for (int j = 0; j < n; j++) {
                if (i == j) {
                    continue;
                }
                printf("%d, ", arr[j]);
            }
            printf("}, ");
        }
        printf("}\n");
        

        上面打印了一些额外的逗号,您可以自己过滤掉它们。

        【讨论】:

          【解决方案4】:

          想想

          • 如何生成集合 1..N
          • 如何识别要从每个集合中删除的数字 n (n: N .. 1)

          从 1..N 生成/打印一个集合

          print "{"
          for i=1 to N
            if (i > 1) print ","
            print i
          end
          print "}"
          

          如何创建一个从 N 到 1 选择 n 的循环

          for j=N to 1 
            ...
          end
          

          使用最后一个循环作为上面循环的包装器 - 并在上面的循环中测试当前选择的数字 j 是否等于 i 并且不打印在那种情况下。

          为了好玩,一个不假装优化的 Perl 实现:-)

          $N = 5;
          
          sub rec {
            my($j,$i,@a) = @_;
            if ($j > 0) {
              while (++$i <= $N) { push(@a,$i) if ($i != $j); }
              print('{' . join(',', @a) . "}\n");
              &rec($j-1);
            }
          }
          
          &rec($N);
          

          或者这个,(也许)更传统的

          for ($i=$N ; $i>0 ; $i--) {
            @a = ();
            for (1..$N) { push(@a,$_) if ($i != $_); }
            print('{' . join(',', @a) . "}\n");
          }
          

          【讨论】:

            【解决方案5】:

            在 Haskell 中你可以做 this:

            import Data.List
            
            combinations 0 _  = [ [] ]
            combinations n xs = [ y:ys | y:xs' <- tails xs
                                       , ys <- combinations (n-1) xs']
            
            subsets set =  combinations (length set - 1) (sort set)
            


            Haskell,简单地说:

            _                                   =>    anyting
            []                                  =>    empty list
            a = 1; as = [2,3]                   =>    a:as = [1,2,3]
            [a:b | a <- [1], b <- [[2],[3]]]    =>    [[1,2],[1,3]]
            tails [1,2,3]                       =>    [[1,2,3],[2,3],[3],[]]
            


            比如“组合2[1,2,3]”:

            tails xs = [[1,2,3],[2,3],[3],[]]
            
            [1,2,3]   =>   y = 1; ys = [[2],[3]]    =>    [1,2],[1,3]
            [2,3]     =>   y = 2; ys = [[3]]        =>    [2,3]
            [3]       =>   y = 3; ys = NULL         =>    []
            
            Result [[1,2],[1,3],[2,3]]
            

            【讨论】:

              猜你喜欢
              • 2022-01-20
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2017-02-13
              • 2011-04-24
              • 2021-09-12
              相关资源
              最近更新 更多