zoukankan      html  css  js  c++  java
  • 78.Subsets

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

    题目大意:给出一个数组序列的所有子集合,包括空集。(数组中的数字唯一)

    法一(借鉴):利用77题组合的思想,只是这里不需要判断集合中总数是不是达到k值,而是将每一次得到的集合都加入结果集中。代码如下(耗时5ms):

     1     public List<List<Integer>> subsets(int[] nums) {
     2         List<List<Integer>> list = new ArrayList<List<Integer>>();
     3         List<Integer> tmp = new ArrayList<Integer>();
     4         dfs(list, tmp, nums, 0);
     5         return list;
     6     }
     7     public static void dfs(List<List<Integer>> list, List<Integer> tmp, int[] nums, int start) {
     8         list.add(new ArrayList<Integer>(tmp));
     9         for(int i = start; i < nums.length; i++) {
    10             tmp.add(nums[i]);
    11             dfs(list, tmp, nums, i + 1);
    12             tmp.remove(tmp.size() - 1);
    13         }
    14     }
    View Code

    法二(借鉴):非递归,与46题的法二的非递归方法很类似,只是这里少了内层的for循环代码,因为是组合,所以不需要考虑当前下标之前的数。代码如下(耗时3ms):

     1     public List<List<Integer>> subsets(int[] nums) {
     2         List<List<Integer>> res = new ArrayList<List<Integer>>();
     3         res.add(new ArrayList<Integer>());//加入空集
     4         for(int num : nums) {//遍历nums数组
     5             List<List<Integer>> tmp = new ArrayList<List<Integer>>();//临时结果集
     6             for(List<Integer> r : res) {//遍历结果集
     7                 //新建一个对象a指向r地址空间,在执行完a.add()之后,a的地址空间发生变化,得到一个新的地址空间,而res结果集中的原地址空间中的数据仍保持不变,保证了一致性,不会篡改数据
     8         //        System.out.println("r:" + r.hashCode());
     9                 List<Integer> a = new ArrayList<Integer>(r);
    10         //        System.out.println("a:" + a.hashCode());
    11                 a.add(num);
    12         //        System.out.println(":" + a.hashCode());
    13                  tmp.add(a);//将新得到的结果放入临时结果集
    14                  
    15                  //虽然你看上去上面的代码新建了一个变量,使得代码更加繁琐,但是其实是有必要而且必须的
    16                  //下面的这段代码不可行,因为r所拿到的其实是res结果集里面的某一个list的地址,而且并没有新开辟空间,也就没有更换地址
    17                  //这样在执行r.add()函数的时候,加入的num值就是在原地址空间的基础上加的,但是在执行完add()函数之后,r的地址会变成一个新的地址,至于为什么,看了源码也无从得知
    18                 //而由于在r.add()之后r的地址已经变了,下面new一个新对象,指向变后的地址空间,让其存留,但是此时其实res结果集中的数据也已经变了,因为r是在原地址上做的操作
    19                 //当再次执行下面的res.addAll()的操作时,会得到很多个地址空间相同的对象,因为其实一直都指向一个地址空间,也就是r的地址空间
    20             //    r.add(num);
    21                 //new的作用仅仅是将原始数据存留,而不是新开辟一个地址空间,也就是新建一个对象指向r地址空间
    22             //    tmp.add(new ArrayList<Integer>(r));
    23             }
    24             //addAll()是在res原结果集的基础上将tmp整个的加入res结果集中,而不是用tmp将res覆盖
    25             res.addAll(tmp);//将临时结果集赋给res结果集
    26 
    27         }
    28         return res;
    29     }
    View Code

    当nums={1,2,3}时,运行结果如下:

    [1]--->第一次外层for循环
    list:[[], [1]]
    [2]--->第二次外层for循环
    [1, 2]
    list:[[], [1], [2], [1, 2]]
    [3]--->第三次外层for循环
    [1, 3]
    [2, 3]
    [1, 2, 3]
    list:[[], [1], [2], [1, 2], [3], [1, 3], [2, 3], [1, 2, 3]]
    [[], [1], [2], [1, 2], [3], [1, 3], [2, 3], [1, 2, 3]]

     法三(借鉴):位运算,还不是很懂,参考http://m.blog.csdn.net/camellhf/article/details/73551410。代码如下(耗时3ms):

     1     public List<List<Integer>> subsets(int[] nums) {
     2         List<List<Integer>> res = new ArrayList<List<Integer>>();
     3         int length = nums.length;//记录数组个数
     4         int num = (int) Math.pow(2, length);//记录子集个数
     5         for(int i = 0; i < num; i++) {//初始化结果集,必须的,如果不初始化下面res.get()的时候会出错
     6             res.add(new ArrayList<Integer>());
     7         }
     8         for(int i = 0; i < nums.length; i++) {
     9             for(int j = 0; j < num; j++) {
    10                 //System.out.println(j + "," + (j>>i));
    11                 if(((j >> i) & 1) == 0) {
    12                     res.get(j).add(nums[i]);
    13                 }
    14             }
    15         }
    16         return res;
    17     }
    View Code
  • 相关阅读:
    2018年NGINX最新版高级视频教程
    PHP 高级工程面试题汇总
    2018年最全Go语言教程零基础入门到进阶实战视频
    Mac和window生成ssh和查看ssh key
    33款可用来抓数据的开源爬虫软件工具
    什么是CMS系统
    对于做需求分析时的一些心得
    WPF和Silverlight的关系
    My97日期控件 My97 DatePicker Ver 3.0 正式版(转)
    HTML教程HTML技巧层的高级应用
  • 原文地址:https://www.cnblogs.com/cing/p/7877813.html
Copyright © 2011-2022 走看看