zoukankan      html  css  js  c++  java
  • 77.Combinations

    题目链接:https://leetcode.com/problems/combinations/description/

    题目大意:组合问题,给出一个数n以及要组合的数的个数k,输出所有组合数。

    法一(借鉴):虽然前面做了排列的题,可惜还是不会做这个组合题。代码如下(耗时76ms):

     1     public List<List<Integer>> combine(int n, int k) {
     2         List<List<Integer>> res = new ArrayList<List<Integer>>();
     3         List<Integer> tmp = new ArrayList<Integer>();
     4         dfs(res, tmp, n, k, 1);
     5         return res;
     6     }
     7     public static void dfs(List<List<Integer>> res, List<Integer> tmp, int n, int k, int start) {
     8     //    System.out.println(tmp);
     9         if(tmp.size() == k) {
    10             res.add(new ArrayList<Integer>(tmp));
    11             return;
    12         }
    13         for(int i = start; i <= n; i++) {
    14             tmp.add(i);
    15             dfs(res, tmp, n, k, i + 1);
    16             tmp.remove(tmp.size() - 1);//回溯删除
    17         }
    18     }
    View Code

    当n=4,k=2时的运行结果:

    []
    [1]
    [1, 2]--->return执行i++ -> add
    [1, 3]--->return执行i++ -> add
    [1, 4]--->return执行i++ -> add
    [2]--->return到1dfs后执行remove操作,再i++ -> add
    [2, 3]
    [2, 4]
    [3]
    [3, 4]
    [4]
    [[1, 2], [1, 3], [1, 4], [2, 3], [2, 4], [3, 4]]

    优化剪枝:http://blog.csdn.net/wys2011101169/article/details/72887512 

    根据这个博客剪枝,原因可见博客。代码如下(耗时4ms):

     1     public List<List<Integer>> combine(int n, int k) {
     2         List<List<Integer>> res = new ArrayList<List<Integer>>();
     3         List<Integer> tmp = new ArrayList<Integer>();
     4         dfs(res, tmp, n, k, 1);
     5         return res;
     6     }
     7     public static void dfs(List<List<Integer>> res, List<Integer> tmp, int n, int k, int start) {
     8         if(tmp.size() == k) {
     9             res.add(new ArrayList<Integer>(tmp));
    10             return;
    11         }
    12         for(int i = start; i <= (n - (k - tmp.size()) + 1); i++) {
    13             //i <= (n - (k - tmp.size()) + 1)剪枝,当可选的数已经不够时,直接剪枝
    14             tmp.add(i);
    15             dfs(res, tmp, n, k, i + 1);
    16             tmp.remove(tmp.size() - 1);//回溯删除
    17         }
    18     }
    View Code

    法二(借鉴):做完78题,回头用78题的非递归代码,发现超时了,按理说这个办法应该是可以过的,但是应该需要合理的剪枝吧。代码如下:

     1     public List<List<Integer>> combine(int n, int k) {
     2         List<List<Integer>> res = new ArrayList<List<Integer>>();
     3         res.add(new ArrayList<Integer>());
     4         for(int i = 1; i <= n; i++) {
     5             List<List<Integer>> tmp = new ArrayList<List<Integer>>();
     6             for(List<Integer> r : res) {
     7                 List<Integer> a = new ArrayList<Integer>(r);
     8                 a.add(i);
     9                 tmp.add(a);
    10             }
    11             res.addAll(tmp);
    12         }
    13         //从所有集合中拿到个数是k的子集合加到结果集中
    14         List<List<Integer>> list = new ArrayList<List<Integer>>();
    15         for(List<Integer> r : res) {
    16             if(r.size() == k) {
    17                 list.add(r);
    18             }
    19         }
    20         return list;
    21     }
    View Code
  • 相关阅读:
    subprocess 子进程模块
    3.5 魔法方法
    ThinkPHP中,display和assign用法详解
    linux常用指令
    退出当前Mysql使用的db_name 的方式
    PHP中GD库是做什么用的? PHP GD库介绍11111111
    include跟include_once 以及跟require的区别
    全局变量跟局部变量
    关于define
    创建、删除索引---高级部分
  • 原文地址:https://www.cnblogs.com/cing/p/7866512.html
Copyright © 2011-2022 走看看