力扣https://leetcode.cn/problems/VvJkup/
给定一个不含重复数字的整数数组 nums ,返回其 所有可能的全排列 。可以 按任意顺序 返回答案。
示例 1:
输入:nums = [1,2,3]
输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
示例 2:输入:nums = [0,1]
输出:[[0,1],[1,0]]
示例 3:输入:nums = [1]
输出:[[1]]
提示:
1 <= nums.length <= 6
-10 <= nums[i] <= 10
nums 中的所有整数 互不相同
与排列不同的是,组合不需要保持元素间的相对位置保持不变(元素位置调换是一种新的组合),因此对于每一层的递归中,都需要从头开始选择元素加入备选数据中,但是data中可能存在重复元素,因此我们需要使用一个choose数组来判断该元素是否已经被选择, 同时使用下标index作为递归结束的指标
class Solution {
//存放元素的队列
private List>res=new LinkedList<>();
private LinkedListdata=new LinkedList<>();
//存放元素是否选择的数组
boolean isChoose[];
public List> permute(int[] nums) {
//初始化选择数组
isChoose=new boolean[nums.length];
reverse(nums,0);
return res;
}
//递归函数
public void reverse(int[]nums,int index){
//递归出口
if(index==nums.length){
res.add(new LinkedList(data));
}
//遍历添加
for(int i=0;i
力扣https://leetcode.cn/problems/7p8L0Z/
给定一个可包含重复数字的整数集合 nums ,按任意顺序 返回它所有不重复的全排列。
示例 1:
输入:nums = [1,1,2]
输出:
[[1,1,2],
[1,2,1],
[2,1,1]]
示例 2:输入:nums = [1,2,3]
输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
提示:
1 <= nums.length <= 8
-10 <= nums[i] <= 10
与上题有所不同的是,num数组中存在重复的元素,但是重复的元素在进行组合过程中会产生重复结果,因此我们需要进行剪枝处理,我们的剪枝策略如下:如果nums[i]==nums[i-1]相等,并且当前data中没有选择nums[i-1]但是选择了nums[i],将这种情况进行去除(因为前面没选择但是后面选择了说明前面元素已经选择过了),同样需要一个index,当index指向最后元素时,递归结束
class Solution {
//在求无相同元素的基础上加之排序将问题解决
//存放元素的队列
private List>res=new LinkedList<>();
private LinkedListdata=new LinkedList<>();
//存放元素是否选择的数组
boolean isChoose[];
public List> permuteUnique(int[] nums) {
isChoose=new boolean[nums.length];
//排序
Arrays.sort(nums);
reverse(nums,0);
return res;
}
//递归函数
public void reverse(int[]nums,int index){
//递归出口
if(index==nums.length){
//加入结果
res.add(new LinkedList(data));
}
//循环加入、
for(int i=0;i0&&nums[i]==nums[i-1]&&!isChoose[i-1]){
//剪枝2
continue;
}
//结果加入数据
data.add(nums[i]);
isChoose[i]=true;
//递归
reverse(nums,index+1);
//回溯
isChoose[i]=false;
data.removeLast();
}
}
}
力扣https://leetcode.cn/problems/M99OJA/
正整数 n 代表生成括号的对数,请设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。
示例 1:
输入:n = 3
输出:["((()))","(()())","(())()","()(())","()()()"]
示例 2:输入:n = 1
输出:["()"]
提示:
1 <= n <= 8
本题为括号问题,面对这种题目,如果递归随意组合会产生很多错误的结果,所以必须对其进行合适的剪枝,而剪枝策略也比较简单,当左括号的个数小于右括号或者当左括号或者右括号的个数大于n的时候,直接进行剪枝即可,将最后符合要求的结果放入结果集即可
class Solution {
private Listres=new LinkedList<>();
private char[] data=null;
public List generateParenthesis(int n) {
data=new char[2*n];
reverse(n,0,0);
return res;
}
//递归函数
public void reverse(int n,int leftCount,int rightCount){
if(leftCount>n||rightCount>n||leftCount
力扣https://leetcode.cn/problems/palindromic-substrings/
给你一个字符串 s ,请你统计并返回这个字符串中 回文子串 的数目。
回文字符串 是正着读和倒过来读一样的字符串。
子字符串 是字符串中的由连续字符组成的一个序列。
具有不同开始位置或结束位置的子串,即使是由相同的字符组成,也会被视作不同的子串。
示例 1:
输入:s = "abc"
输出:3
解释:三个回文子串: "a", "b", "c"
示例 2:输入:s = "aaa"
输出:6
解释:6个回文子串: "a", "a", "a", "aa", "aa", "aaa"
提示:
1 <= s.length <= 1000
s 由小写英文字母组成
使用动态规划对此题进行求解,创建二维数组dp[i][j],其含义为从i到j该字符串是否为回文串,而判断回文子串的规则为:如果j-i<=1且char[i]==char[j] ,表示两个字符为一个字符或者两个字符串相连,此时两者为组成的字符串为回文子串,如果j-i>1且char[i]==char[j],若dp[i+1][j-1]=true,则说明从i到j组成的字符串为回文串,初始化,因为没有验证是否为回文串,每个字符串刚开始全部为false,遍历顺序-> dp[i][j]=dp[i+1][j-1],所以遍历顺序为从下到上,从左向右进行遍历
class Solution {
public int countSubstrings(String s) {
int res=0;
//直接使用动态规划进行求解
int n=s.length();
boolean dp[][]=new boolean[n][n];
//将s转化为数组
char[]ch=s.toCharArray();
for(int i=n-1;i>=0;--i){
for(int j=i;j