491. 递增子序列
思路: 难点在于单层去重。
public class Solution {
private IList<IList<int>> result = new List<IList<int>>();
private IList<int> path = new List<int>();
public IList<IList<int>> FindSubsequences(int[] nums) {
BackTracking(nums, 0);
return result;
}
public void BackTracking(int[] nums, int startIndex)
{ if(path.Count >= 2)
{
List<int> tmp = new List<int>();
for(int i = 0;i < path.Count;i++)
{
tmp.Add(path[i]);
}
result.Add(tmp);
}
if(startIndex >= nums.Length)
{
return;
}
int[] used = new int[201];
for(int i = startIndex;i < nums.Length;i++)
{
if((startIndex > 0 && nums[i] < path[path.Count-1]) || used[nums[i]+100]==1)continue;//此行为难点。
used[nums[i]+100]=1;
path.Add(nums[i]);
BackTracking(nums,i+1);
path.RemoveAt(path.Count - 1);
}
}
}
46. 全排列
思路: 491.递增子序列 是树层去重。本题是树枝去重。
大家此时可以感受出排列问题的不同:
- 每层都是从0开始搜索而不是startIndex
- 需要used数组记录path里都放了哪些元素了
排列问题是回溯算法解决的经典题目,大家可以好好体会体会。
public class Solution {
private IList<IList<int>> result = new List<IList<int>>();
private IList<int> path = new List<int>();
public IList<IList<int>> Permute(int[] nums) {
int[] used = new int[21];
BackTracking(nums, used);
return result;
}
public void BackTracking(int[] nums, int[] used)
{ if(path.Count == nums.Length)
{
List<int> tmp = new List<int>();
for(int i = 0;i < path.Count;i++)
{
tmp.Add(path[i]);
}
result.Add(tmp);
return;
}
for(int i = 0;i < nums.Length;i++)
{
if(used[nums[i]+10] == 1)continue;
used[nums[i]+10] = 1;
path.Add(nums[i]);
BackTracking(nums, used);
used[nums[i]+10] = 0;
path.RemoveAt(path.Count - 1);
}
}
}
47. 全排列 II
思路: 树层去重 和 树枝去重 同时使用。
public class Solution {
private IList<IList<int>> result = new List<IList<int>>();
private IList<int> path = new List<int>();
public IList<IList<int>> PermuteUnique(int[] nums) {
int[] used = new int[nums.Length];
BackTracking(nums, used);
return result;
}
public void BackTracking(int[] nums, int[] used)
{ if(path.Count == nums.Length)
{
List<int> tmp = new List<int>();
for(int i = 0;i < path.Count;i++)
{
tmp.Add(path[i]);
}
result.Add(tmp);
return;
}
int[] duplicated = new int[21];
for(int i = 0;i < nums.Length;i++)
{
if(used[i] == 1 || duplicated[nums[i]+10]==1)continue;
used[i] = 1;
duplicated[nums[i]+10] = 1;
path.Add(nums[i]);
BackTracking(nums, used);
used[i] = 0;
path.RemoveAt(path.Count - 1);
}
}
}