From 9c070a028f5571cb1498ea39e07b3ce95704d40e Mon Sep 17 00:00:00 2001 From: krahets Date: Thu, 27 Apr 2023 01:29:00 +0800 Subject: [PATCH] Update the code of permutations I and II --- .../chapter_backtracking/permutations_i.cs | 27 ++++++++----- .../chapter_backtracking/permutations_ii.cs | 27 ++++++++----- .../permutations_problem.md | 40 +++++++++++++++++++ 3 files changed, 72 insertions(+), 22 deletions(-) diff --git a/codes/csharp/chapter_backtracking/permutations_i.cs b/codes/csharp/chapter_backtracking/permutations_i.cs index a024f4674..3b41b5277 100644 --- a/codes/csharp/chapter_backtracking/permutations_i.cs +++ b/codes/csharp/chapter_backtracking/permutations_i.cs @@ -7,11 +7,11 @@ using hello_algo.utils; using NUnit.Framework; -namespace hello_algo.chapter_backtracking; +namespace hello_algo.chapter_backtracking; public class permutations_i { /* 回溯算法:全排列 I */ - public static void backtrack(List state, int[] choices, bool[] selected, List> res) { + static void backtrack(List state, int[] choices, bool[] selected, List> res) { // 当状态长度等于元素数量时,记录解 if (state.Count == choices.Length) { res.Add(new List(state)); @@ -22,24 +22,29 @@ public class permutations_i { int choice = choices[i]; // 剪枝:不允许重复选择元素 且 不允许重复选择相等元素 if (!selected[i]) { - // 尝试 - selected[i] = true; // 做出选择 - state.Add(choice); // 更新状态 + // 尝试:做出选择,更新状态 + selected[i] = true; + state.Add(choice); backtrack(state, choices, selected, res); - // 回退 - selected[i] = false; // 撤销选择 - state.RemoveAt(state.Count - 1); // 恢复到之前的状态 + // 回退:撤销选择,恢复到之前的状态 + selected[i] = false; + state.RemoveAt(state.Count - 1); } } } + /* 全排列 I */ + static List> permutationsI(int[] nums) { + List> res = new List>(); + backtrack(new List(), nums, new bool[nums.Length], res); + return res; + } + [Test] public void Test() { int[] nums = { 1, 2, 3 }; - // 回溯算法 - List> res = new List>(); - backtrack(new List(), nums, new bool[nums.Length], res); + List> res = permutationsI(nums); Console.WriteLine("输入数组 nums = " + string.Join(", ", nums)); Console.WriteLine("所有排列 res = "); diff --git a/codes/csharp/chapter_backtracking/permutations_ii.cs b/codes/csharp/chapter_backtracking/permutations_ii.cs index 390e816e1..5c4cf0cf0 100644 --- a/codes/csharp/chapter_backtracking/permutations_ii.cs +++ b/codes/csharp/chapter_backtracking/permutations_ii.cs @@ -7,11 +7,11 @@ using hello_algo.utils; using NUnit.Framework; -namespace hello_algo.chapter_backtracking; +namespace hello_algo.chapter_backtracking; public class permutations_ii { /* 回溯算法:全排列 II */ - public static void backtrack(List state, int[] choices, bool[] selected, List> res) { + static void backtrack(List state, int[] choices, bool[] selected, List> res) { // 当状态长度等于元素数量时,记录解 if (state.Count == choices.Length) { res.Add(new List(state)); @@ -23,25 +23,30 @@ public class permutations_ii { int choice = choices[i]; // 剪枝:不允许重复选择元素 且 不允许重复选择相等元素 if (!selected[i] && !duplicated.Contains(choice)) { - // 尝试 + // 尝试:做出选择,更新状态 duplicated.Add(choice); // 记录选择过的元素值 - selected[i] = true; // 做出选择 - state.Add(choice); // 更新状态 + selected[i] = true; + state.Add(choice); backtrack(state, choices, selected, res); - // 回退 - selected[i] = false; // 撤销选择 - state.RemoveAt(state.Count - 1); // 恢复到之前的状态 + // 回退:撤销选择,恢复到之前的状态 + selected[i] = false; + state.RemoveAt(state.Count - 1); } } } + /* 全排列 II */ + static List> permutationsII(int[] nums) { + List> res = new List>(); + backtrack(new List(), nums, new bool[nums.Length], res); + return res; + } + [Test] public void Test() { int[] nums = { 1, 2, 2 }; - // 回溯算法 - List> res = new List>(); - backtrack(new List(), nums, new bool[nums.Length], res); + List> res = permutationsII(nums); Console.WriteLine("输入数组 nums = " + string.Join(", ", nums)); Console.WriteLine("所有排列 res = "); diff --git a/docs/chapter_backtracking/permutations_problem.md b/docs/chapter_backtracking/permutations_problem.md index c09ce9803..7d240412a 100644 --- a/docs/chapter_backtracking/permutations_problem.md +++ b/docs/chapter_backtracking/permutations_problem.md @@ -32,60 +32,80 @@ ```java title="permutations_i.java" [class]{permutations_i}-[func]{backtrack} + + [class]{permutations_i}-[func]{permutationsI} ``` === "C++" ```cpp title="permutations_i.cpp" [class]{}-[func]{backtrack} + + [class]{}-[func]{permutationsI} ``` === "Python" ```python title="permutations_i.py" [class]{}-[func]{backtrack} + + [class]{}-[func]{permutations_i} ``` === "Go" ```go title="permutations_i.go" [class]{}-[func]{backtrack} + + [class]{}-[func]{permutationsI} ``` === "JavaScript" ```javascript title="permutations_i.js" [class]{}-[func]{backtrack} + + [class]{}-[func]{permutationsI} ``` === "TypeScript" ```typescript title="permutations_i.ts" [class]{}-[func]{backtrack} + + [class]{}-[func]{permutationsI} ``` === "C" ```c title="permutations_i.c" [class]{}-[func]{backtrack} + + [class]{}-[func]{permutationsI} ``` === "C#" ```csharp title="permutations_i.cs" [class]{permutations_i}-[func]{backtrack} + + [class]{permutations_i}-[func]{permutationsI} ``` === "Swift" ```swift title="permutations_i.swift" [class]{}-[func]{backtrack} + + [class]{}-[func]{permutationsI} ``` === "Zig" ```zig title="permutations_i.zig" [class]{}-[func]{backtrack} + + [class]{}-[func]{permutationsI} ``` 需要重点关注的是,我们引入了一个布尔型数组 `selected` ,它的长度与输入数组长度相等,其中 `selected[i]` 表示 `choices[i]` 是否已被选择。我们利用 `selected` 避免某个元素被重复选择,从而实现剪枝。 @@ -114,60 +134,80 @@ ```java title="permutations_ii.java" [class]{permutations_ii}-[func]{backtrack} + + [class]{permutations_ii}-[func]{permutationsII} ``` === "C++" ```cpp title="permutations_ii.cpp" [class]{}-[func]{backtrack} + + [class]{}-[func]{permutationsII} ``` === "Python" ```python title="permutations_ii.py" [class]{}-[func]{backtrack} + + [class]{}-[func]{permutations_ii} ``` === "Go" ```go title="permutations_ii.go" [class]{}-[func]{backtrack} + + [class]{}-[func]{permutationsII} ``` === "JavaScript" ```javascript title="permutations_ii.js" [class]{}-[func]{backtrack} + + [class]{}-[func]{permutationsII} ``` === "TypeScript" ```typescript title="permutations_ii.ts" [class]{}-[func]{backtrack} + + [class]{}-[func]{permutationsII} ``` === "C" ```c title="permutations_ii.c" [class]{}-[func]{backtrack} + + [class]{}-[func]{permutationsII} ``` === "C#" ```csharp title="permutations_ii.cs" [class]{permutations_ii}-[func]{backtrack} + + [class]{permutations_ii}-[func]{permutationsII} ``` === "Swift" ```swift title="permutations_ii.swift" [class]{}-[func]{backtrack} + + [class]{}-[func]{permutationsII} ``` === "Zig" ```zig title="permutations_ii.zig" [class]{}-[func]{backtrack} + + [class]{}-[func]{permutationsII} ``` 注意,虽然 `selected` 和 `duplicated` 都起到剪枝的作用,但他们剪掉的是不同的分支: