• lintcode 中等题:subSets 子集


    题目

    子集 

    给定一个含不同整数的集合,返回其所有的子集

    样例

    如果 S = [1,2,3],有如下的解:

    [
      [3],
      [1],
      [2],
      [1,2,3],
      [1,3],
      [2,3],
      [1,2],
      []
    ]
    
    注意

    子集中的元素排列必须是非降序的,解集必须不包含重复的子集

    挑战

    你可以同时用递归与非递归的方式解决么?

    解题

    根据上面求排列的思想很类似,还是深度优先遍历。由于输出每个子集需要升序,所以要先对数组进行排序。求出所以的子集,也就是求出所以的组合方式 + 空集

    问题转化为求组合方式的问题

    参考链接不仅要考虑起始位置,还需要考虑长度,这样才是组合 C(n,k),由于我只想到要考虑起始位置,而长度问题在程序中增加,一直没有解决问题

    核心程序

        public void helper(int[] nums,int start,int len,
        ArrayList<Integer> list,ArrayList<ArrayList<Integer>> res){
            if( list.size() == len){
                res.add(new ArrayList<Integer>(list));
                return;
            }
            for(int i=start;i< nums.length;i++){
                if(list.contains(nums[i])){
                    continue;
                }
                list.add(nums[i]);
                helper(nums,i+1,len,list,res);
                list.remove(list.size()-1);
                }
            
        }
    class Solution {
        /**
         * @param S: A set of numbers.
         * @return: A list of lists. All valid subsets.
         */
        public ArrayList<ArrayList<Integer>> subsets(int[] nums) {
            // write your code here
            ArrayList<Integer> list = new ArrayList<Integer>();
            ArrayList<ArrayList<Integer>> res = new ArrayList<ArrayList<Integer>>();
            if(nums == null || nums.length ==0)
                return res;
            Arrays.sort(nums);
            
            res.add(list);
            for(int len = 1;len<= nums.length;len++){
                helper(nums,0,len,list,res);
                
            }
            return res;
        }
        public void helper(int[] nums,int start,int len,
        ArrayList<Integer> list,ArrayList<ArrayList<Integer>> res){
            if( list.size() == len){
                res.add(new ArrayList<Integer>(list));
                return;
            }
            for(int i=start;i< nums.length;i++){
                if(list.contains(nums[i])){
                    continue;
                }
                list.add(nums[i]);
                helper(nums,i+1,len,list,res);
                list.remove(list.size()-1);
                }
            
        }
    }
    Java Code

    九章中程序进行了优化,长度不考虑,递归一次list的值都是子集的一个元素

    class Solution {
        /**
         * @param S: A set of numbers.
         * @return: A list of lists. All valid subsets.
         */
        public ArrayList<ArrayList<Integer>> subsets(int[] nums) {
            // write your code here
            ArrayList<Integer> list = new ArrayList<Integer>();
            ArrayList<ArrayList<Integer>> res = new ArrayList<ArrayList<Integer>>();
            if(nums == null || nums.length ==0)
                return res;
            Arrays.sort(nums);
            helper(nums,0,list,res);
         
            return res;
        }
        public void helper(int[] nums,int start, ArrayList<Integer> list,ArrayList<ArrayList<Integer>> res){
            res.add(new ArrayList<Integer>(list));
            for(int i=start;i< nums.length;i++){
                if(list.contains(nums[i])){
                    continue;
                }
                list.add(nums[i]);
                helper(nums,i+1,list,res);
                list.remove(list.size()-1);
                }
            
        }
    }
    Java Code
    class Solution:
        """
        @param S: The set of numbers.
        @return: A list of lists. See example.
        """
        def subsets(self, S):
            def dfs(depth, start, valuelist):
                res.append(valuelist)
                if depth == len(S): return
                for i in range(start, len(S)):
                    dfs(depth+1, i+1, valuelist+[S[i]])
            S.sort()
            res = []
            dfs(0, 0, [])
            return res
    Python Code

    根据位运算进行求解

            // 1 << n is 2^n
            // each subset equals to an binary integer between 0 .. 2^n - 1
            // 0 -> 000 -> []
            // 1 -> 001 -> [1]
            // 2 -> 010 -> [2]
            // ..
            // 7 -> 111 -> [1,2,3]

     下面是我自己实现

    class Solution {
        /**
         * @param S: A set of numbers.
         * @return: A list of lists. All valid subsets.
         */
        public ArrayList<ArrayList<Integer>> subsets(int[] nums) {
            // write your code here
            int len = nums.length;
            ArrayList<ArrayList<Integer>> res = new ArrayList<ArrayList<Integer>>();
            if(nums == null || len==0)
                return res;
            Arrays.sort(nums);
            // 1 << n is 2^n
            // each subset equals to an binary integer between 0 .. 2^n - 1
            // 0 -> 000 -> []
            // 1 -> 001 -> [1]
            // 2 -> 010 -> [2]
            // ..
            // 7 -> 111 -> [1,2,3]
            for(int i=0;i< 1<<len ;i++){
                ArrayList<Integer> list = new ArrayList<Integer>();
                // 检测哪一位是 1 
                int n = i;
                for(int j=0;j< len;j++){
                    if(n%2==1)
                        list.add(nums[j]);
                    n=n/2;
                }
                res.add(list);
            }
            return res;
        }
    }
    View Code

    九章中判断第几位是1的程序如下:

     for (int i = 0; i < (1 << n); i++) {
                ArrayList<Integer> subset = new ArrayList<Integer>();
                for (int j = 0; j < n; j++) {
                    // check whether the jth digit in i's binary representation is 1
                    if ((i & (1 << j)) != 0) {
                        subset.add(nums[j]);
                    }
                }
                result.add(subset);
            }

    是懂非懂,好像这样也可以判断第几位是1

    class Solution:
        """
        @param S: The set of numbers.
        @return: A list of lists. See example.
        """
        def subsets(self, nums):
            # write your code here
            res = []
            size = len(nums)
            nums.sort()
            if nums == None or size == 0:
                return res
            for i in range(1<<size):
                lst=[]
                n = i
                for j in range(size):
                    if n%2==1:
                        lst.append(nums[j])
                    n/=2
                res.append(lst)
            return res 
    Python Code
  • 相关阅读:
    Windows 8 C#调用C++编写的Windows运行时组件
    Metro style App Datetime formating.
    《编程匠艺》读书笔记之一
    ContextMenu的使用
    单例模式
    c# 类中字段属性设计
    Metro style app 文件查找
    Win 8 学习资料汇总
    Metro C++ 初体验 第二周
    Metro style app 文件、文件夹的选择、文件的保存。
  • 原文地址:https://www.cnblogs.com/bbbblog/p/5099745.html
Copyright © 2020-2023  润新知