1. 括号生成
给出 n 代表生成括号的对数,请你写出一个函数,使其能够生成所有可能的并且有效的括号组合。
例如,给出 n = 3,生成结果为:
[
"((()))",
"(()())",
"(())()",
"()(())",
"()()()"
]
public class Solution {
public List<String> generateParenthesis(int n) {
List<String> result = new ArrayList<>();
handle("", result, n , n);
return result;
}
private void handle(String s, List<String> list, int left, int right) {
if(left > right) {
return;
}
if(left > 0) {
handle(s+"(", list, left-1, right);
}
if(right > 0) {
handle(s+")", list, left, right-1);
}
if(left == 0 && right == 0) {
list.add(s);
return;
}
}
}
2. 子集
给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。
说明:解集不能包含重复的子集。
示例:
输入: nums = [1,2,3]
输出:
[
[3],
[1],
[2],
[1,2,3],
[1,3],
[2,3],
[1,2],
[]
]
public class Solution {
//写法一
public List<List<Integer>> subsets(int[] nums) {
List<List<Integer>> res = new ArrayList<>();
List<Integer> list = new ArrayList<>();
if(nums == null || nums.length == 0) {
return null;
}
Arrays.sort(nums); //进行排序
dfs(nums, 0, list, res);
res.add(list); //增加为[]的情况
return res;
}
private void dfs(int[] nums, int start, List<Integer> list, List<List<Integer>> res) {
for(int i = start; i<nums.length; i++) {
list.add(nums[i]);
res.add(new ArrayList<>(list)); //注意
dfs(nums, i+1, list, res);
list.remove(list.size() - 1);
}
}
//写法二
public List<List<Integer>> subsets(int[] nums) {
List<List<Integer>> res = new ArrayList<>();
List<Integer> list = new ArrayList<>();
dfs(nums,0, res, list);
return r
}
private void dfs(int[] nums, int i, List<List<Integer>> res, List<Integer> list) {
res.add(new ArrayList<>(list)); //注意:Java deep copy
for (int j = i; j < nums.length; j++) {
list.add(nums[j]);
dfs(nums, j + 1, res, list);
list.remove(list.size() - 1);
}
}
}
3. 全排列
给定一个没有重复数字的序列,返回其所有可能的全排列。
示例:
输入: [1,2,3]
输出:
[
[1,2,3],
[1,3,2],
[2,1,3],
[2,3,1],
[3,1,2],
[3,2,1]
]
public class Solution {
/*
思路1
回溯法
*/
public List<List<Integer>> permute(int[] nums) {
List<List<Integer>> res = new ArrayList<>();
List<Integer> tmp = new ArrayList<>();
boolean[] visited = new boolean[nums.length];
dfs(nums, res, tmp, visited);
return res;
}
public void dfs(int[] nums, List<List<Integer>> res, List<Integer> tmp, boolean[] visited){
// 如果tmp中存放的数字已经将所有nums中的数字都放入了,那么就将其输入到res中
if(tmp.size() == nums.length)
res.add(new ArrayList<>(tmp));
else { // 否则,开始循环遍历
for(int i = 0;i < nums.length; i++){
if(!visited[i]) {
visited[i] = true;
tmp.add(nums[i]);
dfs(nums, res, tmp, visited);
tmp.remove(tmp.size() - 1);
visited[i] = false;
}
}
}
}
/*
思路2:
交换法
*/
public List<List<Integer>> permute2(int[] nums) {
List<List<Integer>> res = new ArrayList<>();
helper(nums, res, 0);
return res;
}
public void helper(int[] nums, List<List<Integer>> res, int i){
// 找到转置完成后的解,将其存入列表中
if(i == nums.length - 1){
List<Integer> list = new ArrayList<>();
for(int j = 0; j < nums.length; j++){
list.add(nums[j]);
}
res.add(list);
}
// 将当前位置的数跟后面的数交换,并搜索解
for(int j = i; j < nums.length; j++){
swap(nums, i , j);
helper(nums, res, i + 1);
swap(nums, i, j);
}
}
private void swap(int[] nums, int i, int j){
int tmp = nums[i];
nums[i] = nums[j];
nums[j] = tmp;
}
}