leetcode对应题目地址
【思路】keep一个visited数组,用来记录对应下标的元素是否被访问过,因为每次递归的时候,在for循环那块都会从0重新开始,所以为了避免重复把一个元素加进去好多次,要先判断一下该元素是否被访问过,因为给定输入数组中不存在重复元素,所以这样判断就足够了。
递归结束条件:当用来盛装当前的排列的temp list的元素个数达到输入的元素个数的时候,把temp加入到res中,然后返回。
【易错点】
【代码】
public class Solution {
public IList<IList<int>> Permute(int[] nums) {
var res = new List<IList<int>>();
BackTracking(nums, new bool[nums.Length], res, new List<int>());
return res;
}
public void BackTracking(int[] nums, bool[] visited, List<IList<int>> res, List<int> temp){
if(temp.Count==nums.Length){
res.Add(new List<int>(temp));
return;
}
for(var i=0;i<nums.Length;i++){
if(visited[i])
continue;
temp.Add(nums[i]);
visited[i] = true;
BackTracking(nums, visited, res, temp);
temp.RemoveAt(temp.Count-1);
visited[i] = false;
}
}
}
leetcode对应题目地址
【思路】和上一个的不同就是,先要排个序,因为这个后面需要判断一下nums[i-1]和nums[i]是否相同,如果相同,而且nums[i-1]没有被访问过,则continue,其他的地方跟上一个差不多。
【易错点】
【代码】
public class Solution {
public IList<IList<int>> PermuteUnique(int[] nums) {
Array.Sort(nums);
var res = new List<IList<int>>();
BackTracking(nums, new bool[nums.Length], res, new List<int>());
return res;
}
public void BackTracking(int[] nums, bool[] visited, List<IList<int>> res, List<int> temp){
if(temp.Count==nums.Length){
res.Add(new List<int>(temp));
return;
}
for(var i=0;i<nums.Length;i++){
if(visited[i]|| i>0&&nums[i]==nums[i-1]&&!visited[i-1])
continue;
temp.Add(nums[i]);
visited[i] = true;
BackTracking(nums, visited, res, temp);
temp.RemoveAt(temp.Count-1);
visited[i] = false;
}
}
}
顺便看一道题:下一个排列
例子:1432 -> 2134
public class Solution {
public void NextPermutation(int[] nums) {
var left = -1;
for(var i=nums.Length-1;i>0;i--){
if(nums[i]>nums[i-1]){
left = i-1;break;
}
}
if(left!=-1){
var right = nums.Length-1;
for(var i=nums.Length-1;i>left;i--){
if(nums[i]>nums[left]){
right = i;break;
}
}
Swap(nums, left, right);
}
Reverse(nums, left+1, nums.Length-1);
}
public void Reverse(int[] nums, int left, int right){
while(left<right){
Swap(nums,left,right);
left++;right--;
}
}
public void Swap(int[] nums, int left, int right){
var temp = nums[left];
nums[left] = nums[right];
nums[right] = temp;
}
}
266. 回文排列
267. 回文排列 II
leetcode题目地址
【思路】类似排列,只不过组合是没有顺序的,所以[1,2]和[2,1]是一样的,所以for循环中的起始条件就应该是一个从上一次递归传来的start值,这个start值每深入一层递归就加一,也就是说深入递归的时候不管前面的数只管后面的数,所以就不需要visited数组了,反正也不管前面的数了:-)。
【易错点】注意start值的更新是i+1而不是start+1(细心)
public IList<IList<int>> Combine(int n, int k) {
var res = new List<IList<int>>();
BackTracking(n, k, res, new List<int>(), 1);
return res;
}
public void BackTracking(int n, int k, List<IList<int>> res, List<int> temp, int start){
if(temp.Count==k){
res.Add(new List<int>(temp));
return;
}
for(var i=start;i<=n;i++){
temp.Add(i);
BackTracking(n, k, res, temp, i+1);
temp.RemoveAt(temp.Count-1);
}
}
39. 组合总和
给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
candidates 中的数字可以无限制重复被选取。
说明:
所有数字(包括 target)都是正整数。
解集不能包含重复的组合。
示例 1:
输入: candidates = [2,3,6,7], target = 7,
所求解集为:
[
[7],
[2,2,3]
]
示例 2:
输入: candidates = [2,3,5], target = 8,
所求解集为:
[
[2,2,2,2],
[2,3,3],
[3,5]
]
【思路】不能向回走,所以得有一个start变量
【易错点】如果sum步子迈大了一下子超过了target,那就没必要往前走了直接return
public IList<IList<int>> CombinationSum(int[] candidates, int target) {
var res = new List<IList<int>>();
BackTracking(candidates, target, res, new List<int>(), 0, 0);
return res;
}
public void BackTracking(int[] candidates, int target, List<IList<int>> res, List<int> temp, int start, int sum){
if(sum==target){
res.Add(new List<int>(temp));
}
else if(target<sum){
return;
}
for(var i=start;i<candidates.Length;i++){
temp.Add(candidates[i]);
sum += candidates[i];
BackTracking(candidates, target, res, temp, i, sum);
temp.RemoveAt(temp.Count-1);
sum -= candidates[i];
}
}
40. 组合总和 II
和上一题不同在于:candidates 中的每个数字在每个组合中只能使用一次。
public class Solution {
public List<IList<int>> Ans = new List<IList<int>>();
public IList<IList<int>> CombinationSum2(int[] candidates, int target) {
Array.Sort(candidates);
BackTrack(candidates, target, new List<int>(), 0);
return Ans;
}
public void BackTrack(int[] candidates, int cur, List<int> temp, int start){
if(cur==0){
Ans.Add(new List<int>(temp));
}
else if(cur<0) return;
for(var i=start;i<candidates.Length;i++){
if(i>start&&candidates[i]==candidates[i-1]) continue;
temp.Add(candidates[i]);
BackTrack(candidates, cur-candidates[i], temp, i+1);
temp.RemoveAt(temp.Count-1);
}
}
}
377. 组合总和 Ⅳ
突然冒出来一个dp问题。。
跟I不同的地方在于:给定的数组中含有负数
public class Solution {
//google, facebook
public int CombinationSum4(int[] nums, int target) {
var dp = new int[target + 1];
dp[0] = 1;
for (int i = 1; i <= target; i++)
{
for (int j = 0; j < nums.Length; j++)
{
if (nums[j] <= i)
{
dp[i] = dp[i] + dp[i - nums[j]];
}
}
}
return dp[target];
}
}
216. 组合总和 III
【题目】
找出所有相加之和为 n 的 k 个数的组合。组合中只允许含有 1 - 9 的正整数,并且每种组合中不存在重复的数字。
说明:
所有数字都是正整数。
解集不能包含重复的组合。
示例 1:
输入: k = 3, n = 7
输出: [[1,2,4]]
示例 2:
输入: k = 3, n = 9
输出: [[1,2,6], [1,3,5], [2,3,4]]
public class Solution {
public List<IList<int>> result = new List<IList<int>>();
public IList<IList<int>> CombinationSum3(int k, int n) {
BackTrack(k,n,new List<int>(), 0, 1);
return result;
}
public void BackTrack(int k, int n, List<int> current, int sum, int start){
if(current.Count==k&&sum==n){
result.Add(new List<int>(current));
return;
}
if (sum > n || start > 9 || current.Count > k)
{
return;
}
for(var i=start;i<10;i++){
current.Add(i);
BackTrack(k, n, current, sum+i, i+1);
current.Remove(i);
}
}
}
leetcode题目地址
public class Solution {
public List<IList<int>> result = new List<IList<int>>();
public IList<IList<int>> Subsets(int[] nums) {
BackTrack(nums, new List<int>(), 0);
return result;
}
public void BackTrack(int[] nums, List<int> current, int start){
result.Add(new List<int>(current));
for(var i=start;i<nums.Length;i++){
current.Add(nums[i]);
BackTrack(nums, current, i+1);
current.Remove(nums[i]);
}
}
}
leetcode题目地址
public class Solution {
public List<IList<int>> Ans = new List<IList<int>>();
public IList<IList<int>> SubsetsWithDup(int[] nums) {
Array.Sort(nums);
BackTrack(nums, new List<int>(), 0);
return Ans;
}
public void BackTrack(int[] nums, List<int> temp, int start){
Ans.Add(new List<int>(temp));
for(var i=start;i<nums.Length;i++){
if(i>start&&nums[i]==nums[i-1]) continue;
temp.Add(nums[i]);
BackTrack(nums, temp, i+1);
temp.Remove(nums[i]);
}
}
}
leetcode题目地址
public class Solution {
public bool IsValidSudoku(char[,] board) {
var hDict = new bool[9,9];
var vDict = new bool[9,9];
var xDict = new bool[9,9];
for (int hIndex = 0; hIndex < 9; hIndex++)
{
for (int vIndex = 0; vIndex < 9; vIndex++)
{
var c = board[hIndex, vIndex];
if (c == '.')
{
continue;
}
var cIndex = c - '1';
if (hDict[cIndex, hIndex])
{
return false;
}
if (vDict[cIndex, vIndex])
{
return false;
}
var xIndex = (vIndex / 3) * 3 + (hIndex / 3);
if (xDict[cIndex, xIndex])
{
return false;
}
hDict[cIndex, hIndex] = true;
vDict[cIndex, vIndex] = true;
xDict[cIndex, xIndex] = true;
}
}
return true;
}
}
leetcode题目地址
public class Solution {
public void SolveSudoku(char[,] board) {
Solve(board);
}
public bool Solve(char[,] board){
for(var i=0;i<board.GetLength(0);i++){
for(var j=0;j<board.GetLength(1);j++){
if(board[i,j]=='.'){
for(var c='1';c<='9';c++){
if(IsValid(i, j, c, board)){
board[i,j]=c;
if(Solve(board)){
return true;
}
else{
board[i,j]='.';
}
}
}
return false;
}
}
}
return true;
}
public bool IsValid(int r, int c, int n, char[,] board){
for(var i=0;i<9;i++){
if(board[r,i]==n || board[i,c]==n) return false;
}
for(var i = r/3*3;i<r/3*3+3;i++){
for(var j = c/3*3;j<c/3*3+3;j++){
if(board[i,j]==n) return false;
}
}
return true;
}
}
leetcode题目地址
column数组下标表示第几行,值表示把皇后放在第几列
public class Solution {
List<IList<string>> res = new List<IList<string>>();
int num = 0;
public IList<IList<string>> SolveNQueens(int n) {
num = n;
dfs(new List<int>());
return res;
}
public void dfs(List<int> column) {
if(column.Count==num){
res.Add(new List<string>(draw(column)));
return;
}
for(var i=0;i<num;i++){
if(isValid(i, column)){
column.Add(i);
dfs(column);
column.RemoveAt(column.Count-1);
}
}
}
public bool isValid(int index, List<int> column){
var total = column.Count;
for(var i=0;i<total;i++){
if(column[i]==index||i+column[i]==total+index || i-column[i]==total-index) return false;
}
return true;
}
public List<string> draw(List<int> column) {
var newTable = new List<string>();
for(var i=0;i<num;i++){
var line = new char[num];
for(var j=0;j<num;j++){
if(j==column[i]){
line[j]='Q';
}
else{
line[j]='.';
}
}
newTable.Add(new string(line));
}
return newTable;
}
}
leetcode题目地址
public class Solution {
int res = 0;
int num = 0;
public int TotalNQueens(int n) {
num = n;
dfs(new List<int>());
return res;
}
public void dfs(List<int> column) {
if(column.Count==num){
res++;
return;
}
for(var i=0;i<num;i++){
if(isValid(i, column)){
column.Add(i);
dfs(column);
column.Remove(i);
}
}
}
public bool isValid(int index, List<int> column){
var total = column.Count;
for(var i=0;i<total;i++){
if(column[i]==index) return false;
if(i+column[i]==total+index || i-column[i]==total-index) return false;
}
return true;
}
}
给出 n 代表生成括号的对数,请你写出一个函数,使其能够生成所有可能的并且有效的括号组合。
例如,给出 n = 3,生成结果为:
[
“((()))”,
“(()())”,
“(())()”,
“()(())”,
“()()()”
]
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/generate-parentheses
public class Solution {
public List<string> result = new List<string>();
public IList<string> GenerateParenthesis(int n) {
BackTrack(n,n,n,"");
return result;
}
public void BackTrack(int n, int open, int close, string cur){
if(cur.Length==n*2){
result.Add(cur);
return;
}
if(open>0){
BackTrack(n, open-1, close, cur+"(");
}
if(open<close){
BackTrack(n, open, close-1, cur+")");
}
}
}