Subsets C#

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], []]


题意:找已知集合的所有子集,子集中的元素是递增序列,相同子集算一个。因为原题中的integers是distinct的,所以不需要考虑会出现相同子集的情况。

解法1:位操作

这个问题的tag为backtracking,但也可使用其他的办法解决,我第一次看到这个问题时想到的办法是使用位操作解决,方法很简单,nums中有n个integers,从0到2的n次幂-1,使用位操作,取出n位上出现1的index中的元素加入子集。

代码实现:

 public class Solution
    {
        public List<List<int>> Subsets(int[] nums)
        {
            Array.Sort(nums);  //测试集中并未说明原数组是排好序的。
            List<List<int>> ret = new List<List<int>>();
            ret.Add(new List<int>());
            int bit = (int)Math.Pow(2, nums.Length);
            int flag = (int)Math.Pow(2,nums.Length-1);
            for (int i = bit-1; i >0; i--)
            {
                List<int> a = new List<int>();
                int tmp = i;
                for (int j = 0; j < nums.Length; j++)
                {
                    if ((tmp & flag) != 0)
                    {
                        a.Add(nums[j]);
                        tmp = tmp << 1;
                        continue;
                    }
                    tmp = tmp << 1;
                }
                ret.Add(a);
            }
            return ret;          
        }
    }


解法2:backtracking方法

回溯法是比较通用的解决这类表面上看需要穷举才能解决的问题的方法,其重点在于如何恢复第 i 步之后的所有后推解都实验过后的该步的下一可能解。针对这个问题,简单点说就是,前面的 i - 1个元素是否在子集中出现已经固定,第 i 个元素只有两种情况:出现和不出现。当选择出现,完成试探后续元素的所有组合,此时需要恢复第 i 步的情况,即第 i 个元素不出现,子集中没有 i,此时我借住一个数据结构栈来完成这个操作。

(该方法,在C#解法中属于比较高效的,但是由于使用了栈这一数据结构,在将子集加入到解集中时需要将元素倒置,希望以后可以找出替代方法)

代码实现:

  public class Solution
    {
        public List<List<int>> Subsets(int[] nums)
        {
            Array.Sort(nums);
            List<List<int>> ret = new List<List<int>>();
            Stack<int> tmp = new Stack<int>();
            help(ret, tmp, 0, nums);
            return ret;          
        }

        public void help(List<List<int>> ret, Stack<int> tmp, int i, int[] nums)
        {
            if (i == nums.Length)
            {
                ret.Add(new List<int>(tmp.Reverse()));//栈的元素转换成List时 并不是按入栈顺序,所以需要倒置
                return;
            }
            tmp.Push(nums[i]); // 第i个元素入栈
            help(ret, tmp, i + 1, nums);// 试探所有后续元素的组合
            tmp.Pop(); //第i个元素出栈
            help(ret, tmp, i + 1, nums);//试探所有元素的后续组合
        }
    }



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值