-
Notifications
You must be signed in to change notification settings - Fork 212
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
nibnait
committed
Oct 25, 2020
1 parent
9560901
commit 2e3e310
Showing
17 changed files
with
1,014 additions
and
3 deletions.
There are no files selected for viewing
167 changes: 167 additions & 0 deletions
167
src/main/java/algorithm_practice/LeetCode/code000/H051_N皇后.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,167 @@ | ||
package algorithm_practice.LeetCode.code000; | ||
|
||
import com.google.common.collect.Lists; | ||
import org.junit.Assert; | ||
import org.junit.Test; | ||
|
||
import java.util.ArrayList; | ||
import java.util.Iterator; | ||
import java.util.List; | ||
|
||
/* | ||
n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。 | ||
[".Q..", | ||
"...Q", | ||
"Q...", | ||
"..Q."] | ||
上图为 8 皇后问题的一种解法。 | ||
给定一个整数 n,返回所有不同的 n 皇后问题的解决方案。 | ||
每一种解法包含一个明确的 n 皇后问题的棋子放置方案,该方案中 'Q' 和 '.' 分别代表了皇后和空位。 | ||
示例: | ||
输入:4 | ||
输出:[ | ||
[".Q..", // 解法 1 | ||
"...Q", | ||
"Q...", | ||
"..Q."], | ||
["..Q.", // 解法 2 | ||
"Q...", | ||
"...Q", | ||
".Q.."] | ||
] | ||
解释: 4 皇后问题存在两个不同的解法。 | ||
提示: | ||
皇后彼此不能相互攻击,也就是说:任何两个皇后都不能处于同一条横行、纵行或斜线上。 | ||
来源:力扣(LeetCode) | ||
链接:https://leetcode-cn.com/problems/n-queens | ||
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 | ||
*/ | ||
public class H051_N皇后 { | ||
|
||
@Test | ||
public void testCase() { | ||
int n = 4; | ||
List<List<String>> excepted = Lists.newArrayList( | ||
Lists.newArrayList(".Q..", "...Q", "Q...", "..Q."), | ||
Lists.newArrayList(".Q..", "...Q", "Q...", "..Q.") | ||
); | ||
|
||
List<List<String>> result = solveNQueens(n); | ||
Assert.assertEquals(excepted, result); | ||
} | ||
|
||
public List<List<String>> solveNQueens(int n) { | ||
List<List<String>> result = new ArrayList<>(); | ||
List<String> path = new ArrayList<>(); | ||
|
||
for (int i = 0; i < n; i++) { | ||
StringBuilder sb = new StringBuilder(); | ||
for (int j = 0; j < n; j++) { | ||
sb.append("."); | ||
} | ||
path.add(sb.toString()); | ||
} | ||
|
||
return backTrack(result, path, 0); | ||
} | ||
|
||
// 路径:第 row 行之前,都已经放置好 Q 了 | ||
// 选择列表:row 这一行的所有列 | ||
// 结束条件:row == path.size | ||
private List<List<String>> backTrack(List<List<String>> result, List<String> path, int row) { | ||
if (row == path.size()) { | ||
result.add(newArrayList(path.iterator())); | ||
return result; | ||
} | ||
|
||
for (int column = 0; column < path.get(0).length(); column++) { | ||
if (!isValid(path, row, column)) { | ||
continue; | ||
} | ||
|
||
path = putQueen(path, row, column); | ||
|
||
backTrack(result, path, row + 1); | ||
|
||
path = popQueen(path, row, column); | ||
|
||
} | ||
return result; | ||
} | ||
|
||
private List<String> popQueen(List<String> path, int row, int column) { | ||
return changeQ(path, row, column, '.'); | ||
} | ||
|
||
private List<String> putQueen(List<String> path, int row, int column) { | ||
return changeQ(path, row, column, 'Q'); | ||
} | ||
|
||
private List<String> changeQ(List<String> path, int row, int column, char c) { | ||
char[] chars = path.get(row).toCharArray(); | ||
chars[column] = c; | ||
|
||
List<String> result = new ArrayList<>(); | ||
for (int i = 0; i < path.size(); i++) { | ||
if (i == row) { | ||
result.add(String.valueOf(chars)); | ||
continue; | ||
} | ||
result.add(path.get(i)); | ||
} | ||
|
||
return result; | ||
} | ||
|
||
private boolean isValid(List<String> path, int row, int column) { | ||
for (int i = 0; i < path.size(); i++) { // 行 | ||
String rowList = path.get(i); | ||
for (int j = 0; j < rowList.length(); j++) { // 列 | ||
|
||
// 第 column 列有 Q | ||
if (j == column && 'Q' == rowList.charAt(j)) { | ||
return false; | ||
} | ||
|
||
// 左前右下方向 有 Q | ||
if (i != row && column != j | ||
&& row - i == column - j | ||
&& 'Q' == rowList.charAt(j)) { | ||
return false; | ||
} | ||
|
||
// 右上左下方向 有 Q | ||
if (i != row && column != j | ||
&& row - i == j - column | ||
&& 'Q' == rowList.charAt(j)) { | ||
return false; | ||
} | ||
} | ||
} | ||
return true; | ||
} | ||
|
||
private List<String> newArrayList(Iterator<String> iterator) { | ||
List<String> result = new ArrayList<>(); | ||
|
||
while (iterator.hasNext()) { | ||
result.add(iterator.next()); | ||
} | ||
|
||
return result; | ||
} | ||
} |
111 changes: 111 additions & 0 deletions
111
src/main/java/algorithm_practice/LeetCode/code000/M046_全排列.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
package algorithm_practice.LeetCode.code000; | ||
|
||
import com.google.common.collect.Lists; | ||
import org.junit.Assert; | ||
import org.junit.Test; | ||
|
||
import java.util.ArrayList; | ||
import java.util.Arrays; | ||
import java.util.Iterator; | ||
import java.util.List; | ||
|
||
/* | ||
给定一个 没有重复 数字的序列,返回其所有可能的全排列。 | ||
示例: | ||
输入: [1,2,3] | ||
输出: | ||
[ | ||
[1,2,3], | ||
[1,3,2], | ||
[2,1,3], | ||
[2,3,1], | ||
[3,1,2], | ||
[3,2,1] | ||
] | ||
来源:力扣(LeetCode) | ||
链接:https://leetcode-cn.com/problems/permutations | ||
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 | ||
*/ | ||
public class M046_全排列 { | ||
|
||
@Test | ||
public void testCase() { | ||
int[] nums = new int[]{1,2,3}; | ||
List<List<Integer>> excepted = Lists.newArrayList( | ||
Lists.newArrayList(1,2,3), | ||
Lists.newArrayList(1,3,2), | ||
Lists.newArrayList(2,1,3), | ||
Lists.newArrayList(2,3,1), | ||
Lists.newArrayList(3,1,2), | ||
Lists.newArrayList(3,2,1)); | ||
List<List<Integer>> result = permute(nums); | ||
Assert.assertEquals(excepted, result); | ||
|
||
} | ||
|
||
/* | ||
回溯框架 | ||
result = [] | ||
def backtrack(路径,选择列表) { | ||
if (满足借宿条件) { | ||
result.add(选择); | ||
} | ||
for 选择 in 选择列表: | ||
if 选择不满足当前选择条件: | ||
continue; | ||
做选择; | ||
backtrace(路径, 选择列表); | ||
撤销选择; | ||
} | ||
*/ | ||
|
||
public List<List<Integer>> permute(int[] nums) { | ||
List<List<Integer>> result = new ArrayList<>(); | ||
List<Integer> path = new ArrayList<>(); | ||
|
||
return backTrack(result, path, nums); | ||
} | ||
|
||
private List<List<Integer>> backTrack(List<List<Integer>> result, List<Integer> path, int[]nums) { | ||
if (path.size() == nums.length) { | ||
result.add(newArrayList(path.iterator())); | ||
return result; | ||
} | ||
|
||
for (int i = 0; i < nums.length; i++) { | ||
int num = nums[i]; | ||
if (path.contains(num)) { | ||
continue; | ||
} | ||
|
||
path.add(num); | ||
|
||
backTrack(result, path, nums); | ||
|
||
path.remove(path.size()-1); | ||
} | ||
|
||
return result; | ||
} | ||
|
||
private List<Integer> newArrayList(Iterator<Integer> iterator) { | ||
ArrayList list = new ArrayList<>(); | ||
|
||
while(iterator.hasNext()) { | ||
list.add(iterator.next()); | ||
} | ||
|
||
return list; | ||
} | ||
|
||
} |
84 changes: 84 additions & 0 deletions
84
src/main/java/algorithm_practice/LeetCode/code000/M047_全排列2.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
package algorithm_practice.LeetCode.code000; | ||
|
||
import com.google.common.collect.Lists; | ||
import org.junit.Assert; | ||
import org.junit.Test; | ||
|
||
import java.util.ArrayList; | ||
import java.util.Iterator; | ||
import java.util.List; | ||
|
||
/* | ||
给定一个可包含重复数字的序列,返回所有不重复的全排列。 | ||
示例: | ||
输入: [1,1,2] | ||
输出: | ||
[ | ||
[1,1,2], | ||
[1,2,1], | ||
[2,1,1] | ||
] | ||
来源:力扣(LeetCode) | ||
链接:https://leetcode-cn.com/problems/permutations-ii | ||
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 | ||
*/ | ||
public class M047_全排列2 { | ||
|
||
@Test | ||
public void testCase() { | ||
int[] nums = new int[]{1,1,2}; | ||
List<List<Integer>> excepted = Lists.newArrayList( | ||
Lists.newArrayList(1,1,2), | ||
Lists.newArrayList(1,2,1), | ||
Lists.newArrayList(2,1,1)); | ||
List<List<Integer>> result = permuteUnique(nums); | ||
Assert.assertEquals(excepted, result); | ||
|
||
|
||
} | ||
|
||
public List<List<Integer>> permuteUnique(int[] nums) { | ||
List<List<Integer>> result = new ArrayList<>(); | ||
List<Integer> path = new ArrayList<>(); | ||
boolean[] used = new boolean[nums.length]; | ||
|
||
return backTrack(result, path, nums, used); | ||
} | ||
|
||
private List<List<Integer>> backTrack(List<List<Integer>> result, List<Integer> path, int[] nums, boolean[] used) { | ||
if (path.size() == nums.length) { | ||
if (!result.contains(path)) { | ||
result.add(newArrayList(path.iterator())); | ||
} | ||
return result; | ||
} | ||
|
||
for (int i = 0; i < nums.length; i++) { | ||
if (used[i]) { | ||
continue; | ||
} | ||
|
||
used[i] = true; | ||
path.add(nums[i]); | ||
|
||
backTrack(result, path, nums, used); | ||
|
||
used[i] = false; | ||
path.remove(path.size() - 1); | ||
} | ||
|
||
return result; | ||
} | ||
|
||
private List<Integer> newArrayList(Iterator<Integer> iterator) { | ||
List<Integer> result = new ArrayList<>(); | ||
while (iterator.hasNext()) { | ||
result.add(iterator.next()); | ||
} | ||
return result; | ||
} | ||
} |
Oops, something went wrong.