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

    Given a set of distinct integers, nums, return all possible subsets.

    Note:

    • Elements in a subset must be in non-descending order.
    • The solution set must not contain duplicate subsets.

     For example,

    If nums = [1,2,3], a solution is:

    [
      [3],
      [1],
      [2],
      [1,2,3],
      [1,3],
      [2,3],
      [1,2],
      []
    ]

    【题目分析】

    这个题目是求一个集合的子集,要求子集中的元素不能降序排列,而且不含有重复的元素。


    【思路】

    求一个集合的所有子集我们可以考虑子集中包含集合的若干个元素,从0个到n(集合的大小)。如果含有0个元素,就是空集,含有一个元素的话就是把集合中每个元素取一次,含有两个元素的话就是找到集合中所有两个元素的组合......以此类推。

    问题是这个过程该如何描述呢?假设我们要从一个增序排序的集合中选取所有两个元素的组合,从集合中开始选取一个之前没有选过的元素a,然后再从这个元素后面选择一个元素b。当我们开始找下一个组合时,需要回溯到当前组合,删除元组中的第二个元素b,然后继续向后寻找。同样当我们找到所有第一个元素为a的所有二元子集时,我们需要删除a,然后在a后面找到下一个二元组的开始元素a2,然后继续上面的过程。因此这个过程是一个递归回溯的过程。

    回溯法

    回溯法按深度优先策略搜索问题的解空间树。首先从根节点出发搜索解空间树,当算法搜索至解空间树的某一节点时,先利用剪枝函数判断该节点是否可行(即能得到问题的解)。如果不可行,则跳过对该节点为根的子树的搜索,逐层向其祖先节点回溯;否则,进入该子树,继续按深度优先策略搜索。

    回溯法的基本行为是搜索,搜索过程使用剪枝函数来为了避免无效的搜索。剪枝函数包括两类:1. 使用约束函数,剪去不满足约束条件的路径;2.使用限界函数,剪去不能得到最优解的路径。

    问题的关键在于如何定义问题的解空间,转化成树(即解空间树)。解空间树分为两种:子集树和排列树。两种在算法结构和思路上大体相同。


    【java代码】

     1 public class Solution {
     2     public List<List<Integer>> subsets(int[] nums) {
     3         List<List<Integer>> list = new ArrayList<>();
     4         List<Integer> clist = new ArrayList<>();
     5         list.add(clist);
     6         if(nums == null) return list;
     7         Arrays.sort(nums);
     8         
     9         for(int i = 1; i <= nums.length; i++){
    10             clist.clear();
    11             DFS(nums, 0, i, clist, list);
    12         }
    13         return list;
    14     }
    15     
    16     public void DFS(int[] nums, int start, int number, List<Integer> clist, List<List<Integer>> list){
    17         if(number == clist.size()){
    18             list.add(new ArrayList<>(clist));
    19             return;
    20         }
    21         for(int i = start;i < nums.length; i++) {
    22             clist.add(nums[i]);
    23             DFS(nums, i+1, number, clist, list);
    24             clist.remove(clist.size()-1);
    25         }
    26     }
    27 }
     1 public class Solution {
     2     public List<List<Integer>> subsets(int[] nums) {
     3         Arrays.sort(nums);
     4         List<List<Integer>> ret = new ArrayList<>();
     5         dfs(nums, 0, new ArrayList<>(), ret);
     6         return ret;
     7         
     8     }
     9 
    10     private void dfs(int[] nums, int idx, List<Integer> path, List<List<Integer>> ret) {
    11         ret.add(path);
    12         for (int i = idx; i < nums.length; i++) {
    13             List<Integer> p = new ArrayList<>(path);
    14             p.add(nums[i]);
    15             dfs(nums, i+1, p, ret);
    16         }
    17     }
    18 }
  • 相关阅读:
    客户端本地存储,web存储,localStorage
    js地理定位对象 navigator.geolocation
    使用defined和require引入js
    VUE的使用方法
    $.each()的用法
    jQuery的deferred对象详解
    jquery 中prop()的使用方法
    IE7下对某些seajs压缩文件不兼容的解决方法
    饼状图注释
    $.grep()的用法
  • 原文地址:https://www.cnblogs.com/liujinhong/p/5555139.html
Copyright © 2011-2022 走看看