您的位置:首页 > 编程语言 > C#

Subsets C#

2015-08-26 14:16 357 查看
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);//试探所有元素的后续组合
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  leetcode C# Subsets