排列组合
子集合 subset(medium)
输入一个含有
不同数字的序列,输出所有可能的集合(含空集)。要求1 集合里元素有序排列;2 输出结果不含有重复集合;
举例:输入{1,2,3], 输出{},{1},{2},{3},{1,2},{1,3},{2,3},{1,2,3}
原题:https://leetcode.com/problems/subsets/
思路图:
Amortized 分期偿还(只是个名字而已)的思路:
public static IList> Subsets(int[] nums)
{
IList> resSet = new List>();
Array.Sort(nums);
//初始化,加入空集
resSet.Add(new List());
for (int i = 0; i < nums.Length; i++)
{
IList> tmp = new List>();
foreach (var list in resSet)
{
//保留原结果
tmp.Add(list);
List clone = new List(list);
//在原有结果里加入新元素
clone.Add(nums[i]);
tmp.Add(clone);
}
resSet = tmp;
}
return resSet;
}
递归代码(DFS):
public static IList> SubSetRecrisive(int[] ints)
{
IList> resSet = new List>();
if (ints == null || ints.Length == 0)
{
return resSet;
}
//Array.Sort(ints);//排序是为了方便有重复输入时判断重复;
Helper(ints, 0, new List(), resSet);
return resSet;
}
public static void Helper(int[] s, int start, List subset, IList> resSet)
{
//保留中间结果,不能直接添加resSet,因为这是传址,它每次都变化;
IList clone = new List(subset);
resSet.Add(clone);
for (int i = start; i < s.Length; i++)
{
subset.Add(s[i]);//加入新元素,并递归调用下一个元素;
Helper(s,i+1,subset,resSet);
subset.RemoveAt(subset.Count-1);//退回,移除subset中最后一个索引位元素
}
}
备注:变种思路,如果输入数组有重复值怎么办?
答案
1 主函数中需要先排序,为Helper函数去重打基础;
2 如果s[i]==s[i-1],直接跳到下一步;
---------------------------------------------------------------------------------
全排列permutation( Medium)
题目内容,输入一个不含相同数字的序列,输出所有可能的排列permutation, 需要注意顺序
举例
输入{ 1,2,3 }
返回: {1,2,3},{1,3,2},{2,1,3},{2,3,1},{3,1,2},{3,2,1}
原题:https://leetcode.com/problems/permutations/
思路:与全子集相似,使用递归方法
区别: 必须等到所有数字均在集合里才能输出。所以需要辅助数组bool[] used=new bool[arr.Length]来记录元素使用情况
问题:
为什么元素不能重复使用?为什么架构与subset不同?
自我解答,欢迎补充:使用1,2作为输入,确实能够得到答案,只能说此架构设计比较巧妙。长期来看只能靠记忆
public static IList> PermuteRecrusive(int[] ints)
{
IList> resSet = new List>();
if (ints == null || ints.Length == 0)
{
return resSet;
}
Array.Sort(ints);
PermuteHelper(ints, new List(), resSet);
return resSet;
}
///
/// 1 为什么循环中不需要pos参数? 2为什么参数不能重复使用?
///
///
///
///
///
public static void PermuteHelper(int[] ints, List subset, IList> resSet)
{
if (subset.Count == ints.Length)
{
resSet.Add(new List(subset));
return; //为什么需要这个?因为add后需要回到上一层递归;
}
for (int i = 0; i < ints.Length; i++)
{
if (subset.Contains(ints[i])) continue; //不能重复使用已有元素,为什么?
subset.Add(ints[i]);//加入新元素,递归调用下一个元素
PermuteHelper(ints, subset, resSet);
subset.RemoveAt(subset.Count-1);//回退
}
}