美文网首页程序员
Hackrank 统计十日通(第三天) 组合与排列

Hackrank 统计十日通(第三天) 组合与排列

作者: cfcodefans | 来源:发表于2017-04-11 23:02 被阅读0次

    来源: 同花色的牌

    下列高亮的术语将对你完成今天的挑战非常有用.

    也许你已经注意到, 从事件发生的可能性中发现规律,非常利于我们从样本空间中计算所求事件的数量. 有两种这么做的最简单的方法是, 用排列(permutation, 有顺序)和组合(combination, 顺序无关).

    排列 Permutation

    注: 其实排列是Arrangement, 全排列才是Permutation?

    从一个n个元素的集合A中, 取r个对象的有序排列(注, 有序,例如a,b和b,a这两个是不一样的), (其中0 < r ≤ n), 这就叫一个A集合的r元素排列. 你也可以把这当作A的全排列中一次取r个元素的排列. 一个n元素的集合的r元素排列的数量可以表示为以下公式:

    注意: 我们定义0!的值为1, 否则的话, nPn就成了n!/(n-n)! → n!/0!

    组合 Combinations

    从一个n个元素的集合A中, 取r个对象的无序排列(注, 无序,例如a,b和b,a这两个是一样的,只有有a有b就行), (其中0 < r ≤ n), 这就叫一个A集合的r元素组合.

    因为排列和组合的唯一区别就是组合是无序的. 我们通过从排列中约去r的全排列(r!):


    当我们说到组合时, 我们指n元素集合中取出r元素的子集的可能取法的数量. 实际上, nCr通常被称为"n选r". 因为, 这个就是计算n元素集合中取出r元素的子集有多少可能取法.
    nCr也通常写成

    求1,2...n的r排列

    假设有n=6元素集合1, 2, 3, 4, 5, 6, 求r=3的所有排列, 例如:
    1,2,3
    1,3,2
    2,1,3
    2,3,1
    3,1,2
    3,2,1
    1,2,4
    1,4,2
    .......

    输入约束

    • 0 < n ≤ 10
    • 0 < r ≤ n

    输出示例

    例如1 ~ 9中取5个元素的所有组合
    1 [1, 2, 3, 4, 5]
    2 [1, 2, 3, 4, 6]
    3 [1, 2, 3, 4, 7]
    4 [1, 2, 3, 4, 8]
    ......
    126 [5, 6, 7, 8, 9]
    注:这个题我自己出的,我看了一下hackrank好像没有找到这道题.....

    java + 递归

    public class CombinationTest {
        static ConcurrentLinkedQueue<Collection<Integer>> buf = new ConcurrentLinkedQueue<>();
    
        private static void collect(Collection<Integer> combination) {
            buf.offer(combination);
        }
    
        static void iterateForCombination(List<Integer> src, Collection<Integer> combination, int c) {
            if (c == 1) {
                for (Integer e : src) {
                    final ArrayList<Integer> _combination = copyOnAppend(combination, e);
                    collect(_combination);
                }
                return;
            }
    
            for (int i = 0, j = src.size(); i < j; i++) {
                if (j - i <= c) {
                    combination.addAll(src.subList(i, src.size()));
                    collect(combination);
                    break;
                }
                final Integer e = src.get(i);
                final ArrayList<Integer> _combination = copyOnAppend(combination, e);
                iterateForCombination(src.subList(i + 1, j), _combination, c - 1);
            }
        }
    
        private static ArrayList<Integer> copyOnAppend(Collection<Integer> combination, Integer e) {
            final ArrayList<Integer> _combination = new ArrayList<>(combination.size() + 1);
            _combination.addAll(combination);
            _combination.add(e);
            return _combination;
        }
    
        public static void main(String[] args) {
            List<Integer> list = IntStream.range(1, 6).mapToObj(Integer::valueOf).collect(Collectors.toList());
            System.out.println(list);
            int r = 3;
            iterateForCombination(list, new ArrayList<>(), r);
            buf.forEach(combination -> System.out.printf("%s\n", combination));
        }
    }
    

    java + ForkJoinTask

    public class CombinationTest {
        static ConcurrentLinkedQueue<Collection<Integer>> buf = new ConcurrentLinkedQueue<>();
    
        private static void collect(Collection<Integer> combination) {
            buf.offer(combination);
        }
    
        private static void iterateForCombinationsWithForkJoin(List<Integer> list, int r) {
            final CombinationTask ct = new CombinationTask(list, new ArrayList<>(r), r);
            ct.invoke();
            try { ct.join(); } catch (Exception e) { e.printStackTrace(); }
        }
    
        static class CombinationTask extends RecursiveAction {
            List<Integer> src;
            Collection<Integer> combination;
            int c;
    
            public CombinationTask(List<Integer> list, Collection<Integer> combination, int c) {
                this.src = list;
                this.combination = combination;
                this.c = c;
            }
    
            @Override
            protected void compute() {
                if (c == 1) {
                    for (Integer e : src) {
                        final ArrayList<Integer> _combination = copyOnAppend(this.combination, e);
                        collect(_combination);
                    }
                    return;
                }
    
                List<CombinationTask> taskList = new ArrayList<>(c);
                for (int i = 0, j = src.size(); i < j; i++) {
                    if (j - i <= c) {
                        combination.addAll(src.subList(i, j));
                        collect(combination);
                        break;
                    }
                    final Integer e = src.get(i);
                    final ArrayList<Integer> _combination = copyOnAppend(this.combination, e);
                    taskList.add(new CombinationTask(src.subList(i + 1, j), _combination, c - 1));
                }
                invokeAll(taskList);
            }
        }
    
        private static ArrayList<Integer> copyOnAppend(Collection<Integer> combination, Integer e) {
            final ArrayList<Integer> _combination = new ArrayList<>(combination.size() + 1);
            _combination.addAll(combination);
            _combination.add(e);
            return _combination;
        }
    
        public static void main(String[] args) {
            List<Integer> list = IntStream.range(1, 6).mapToObj(Integer::valueOf).collect(Collectors.toList());
            System.out.println(list);
            int r = 3;
            iterateForCombinationsWithForkJoin(list, r);
            buf.forEach(combination -> System.out.printf("%s\n", combination));
        }
    }
    

    java + 栈 + 循环

    public class CombinationTest {
        static ConcurrentLinkedQueue<Collection<Integer>> buf = new ConcurrentLinkedQueue<>();
    
        private static void collect(Collection<Integer> combination) {
            buf.offer(combination);
        }
    
        static class StackFrame {
            List<Integer> src;
            Collection<Integer> combination;
            int c;
    
            public StackFrame(List<Integer> list, Collection<Integer> combination, int c) {
                this.src = list;
                this.combination = combination;
                this.c = c;
            }
        }
    
        static void iterateForCombinationWithStack(List<Integer> _src, int _c) {
            ArrayDeque<StackFrame> stack = new ArrayDeque<>(1000000);
            stack.push(new StackFrame(_src, new ArrayList<>(_c), _c));
            while (!stack.isEmpty()) {
                StackFrame sf = stack.pop();
    
                List<Integer> src = sf.src;
                int c = sf.c;
                Collection<Integer> combination = sf.combination;
    
                if (c == 1) {
                    for (Integer e : src) {
                        final ArrayList<Integer> _combination = copyOnAppend(combination, e);
                        collect(_combination);
                    }
                    continue;
                }
    
                for (int _i = 0, j = src.size(); _i < j; _i++) {
                    if (j - _i <= c) {
                        combination.addAll(src.subList(_i, src.size()));
                        collect(combination);
                        break;
                    }
                    final Integer e = src.get(_i);
                    final ArrayList<Integer> _combination = copyOnAppend(combination, e);
                    stack.push(new StackFrame(src.subList(_i + 1, j), _combination, c - 1));
                }
            }
        }
    
        private static ArrayList<Integer> copyOnAppend(Collection<Integer> combination, Integer e) {
            final ArrayList<Integer> _combination = new ArrayList<>(combination.size() + 1);
            _combination.addAll(combination);
            _combination.add(e);
            return _combination;
        }
    
        public static void main(String[] args) {
            List<Integer> list = IntStream.range(1, 6).mapToObj(Integer::valueOf).collect(Collectors.toList());
            System.out.println(list);
            int r = 3;
            iterateForCombinationWithStack(list, r);
            buf.forEach(combination -> System.out.printf("%s\n", combination));
        }
    }
    

    Scala 代码好特么简洁啊!!!!

     @Test def combinations(): Unit = {
            val list: List[Int] = 1 to 5 toList
            val r: Int = 3
            val buf: ConcurrentLinkedQueue[List[Int]] = new ConcurrentLinkedQueue[List[Int]]()
    
            def iterateForCombination(src: List[Int], combination: List[Int], c: Int): Unit = {
                if (c == 1) {
                    src.foreach(e => buf.offer(e +: combination))
                    return
                }
    
                val j: Int = src.size
                for (i <- 0 to j) {
                    if (j - i <= c) {
                        buf.offer(combination ++ src.slice(i, j))
                        return
                    }
                    iterateForCombination(src.slice(i + 1, j), src(i) +: combination, c - 1)
                }
            }
    
            iterateForCombination(list, List.empty[Int], r)
            import collection.JavaConverters._
            buf.asScala.zipWithIndex.foreach(line => println(s"${line._2}\t ${line._1.mkString(", ")}"))
        }
    

    python 和scala差不多的感觉

    def combinations():
        _list = list(range(1, 6))
        print(_list)
    
        r = 3
        buf = []
    
        def iterate_for_combinations(src, combination=[], c=r):
            if c == 1:
                for e in src:
                    buf.append(combination + [e])
                return
    
            j = len(src)
            for i in range(0, j):
                if j - i <= c:
                    buf.append(combination + src[i:j])
                    return
                iterate_for_combinations(src[i + 1:j], combination + [src[i]], c - 1)
    
        iterate_for_combinations(_list)
        for c in buf:
            print(c)
    
    
    if __name__ == '__main__':
        combinations()
    

    相关文章

      网友评论

        本文标题:Hackrank 统计十日通(第三天) 组合与排列

        本文链接:https://www.haomeiwen.com/subject/elruattx.html