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
  • 相关阅读:
    086 01 Android 零基础入门 02 Java面向对象 01 Java面向对象基础 03 面向对象基础总结 01 面向对象基础(类和对象)总结
    085 01 Android 零基础入门 02 Java面向对象 01 Java面向对象基础 02 构造方法介绍 04 构造方法调用
    jQuery UI组件库Kendo UI使用技巧小分享
    Kendo UI ListView模板功能,让Web开发更轻松
    UI组件套包DevExpress ASP.NET Core v20.2新版亮点:全新的查询生成器
    Devexpress WinForms最新版开发.NET环境配置Visual Studo和SQL Server对应版本
    全新的桌面应用数据可视化呈现方式,Sankey Diagram控件你了解多少?
    java中的递归方法
    连接数据库查询 将查询结果写入exce文件中
    java连接mysql数据查询数据
  • 原文地址:https://www.cnblogs.com/cing/p/7877813.html
Copyright © 2011-2022 走看看