回溯算法主要用于解决组合,切割,排序,子集,棋盘问题。
给定两个整数 n 和 k,返回范围 [1, n] 中所有可能的 k 个数的组合。
你可以按 任何顺序 返回答案。
示例 1:
输入:n = 4, k = 2
输出:
[
[2,4],
[3,4],
[2,3],
[1,2],
[1,3],
[1,4],
]
public List<List<Integer>> combine(int n, int k) {
List<List<Integer>> lists=new ArrayList<>();
if(k<=0||n<k)
return lists;
ArrayList<Integer> list=new ArrayList<>();
backtack(n,k,1,lists,list);
return lists;
}
public void backtracking(int n,int k,int start,List<List<Integer>> lists,ArrayList<Integer> list){
if(list.size()==k){
lists.add(new ArrayList<>(list));
return;
}
for(int i=start;i<=n;i++){
// if(list.contains(i))
// continue;
list.add(i);
backtack(n,k,i+1,lists,list);
list.remove(list.size()-1);
}
}
给定一个候选人编号的集合 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
candidates 中的每个数字在每个组合中只能使用 一次 。
输入: candidates = [10,1,2,7,6,1,5], target = 8,
输出:
[
[1,1,6],
[1,2,5],
[1,7],
[2,6]
]
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
List<List<Integer>> lists=new ArrayList<>();
List<Integer> list=new ArrayList<>();
Arrays.sort(candidates);
backtracking(lists,list,target,candidates,0);
return lists;
}
public void backtracking(List<List<Integer>> lists,List<Integer> list,int target,int[] candidates,int start){
Integer collect = list.stream().collect(Collectors.summingInt(Integer::intValue));
if(collect==target) {
lists.add(new ArrayList<>(list));
return;
}
if(collect>target)
return;
for(int i=start;i<candidates.length;i++){
//大剪枝,如果target -candidates[i] < 0,那么后面的元素都会小于0,需要剪掉
if(candidates[i]>target)
continue;
//同一层数值相同,需要剪掉,不然会造成重复
if(i > start && candidates[i] == candidates[i-1]){
continue;
}
list.add(candidates[i]);
backtracking(lists,list,target,candidates,i+1);
list.remove(list.size()-1);
}
}
找出所有相加之和为 n 的 k 个数的组合,且满足下列条件:
只使用数字1到9
每个数字 最多使用一次
返回 所有可能的有效组合的列表 。该列表不能包含相同的组合两次,组合可以以任何顺序返回。
输入:k = 3, n = 7 输出: [[1,2,4]] 解释: 1 + 2 + 4 = 7 没有其他符合的组合了。
public List<List<Integer>> combinationSum3(int k, int n) {
List<List<Integer>> lists=new ArrayList<>();
List<Integer> list=new ArrayList<>();
int[] array=new int[]{1,2,3,4,5,6,7,8,9};
int sum = Arrays.stream(array).limit(k).sum();
if(sum>n)
return lists;
tracking(lists,list,k,n,0,array);
return lists;
}
public void tracking(List<List<Integer>> lists,List<Integer> list,int k,int n,int start,int[] array){
int sum = list.stream().mapToInt(Integer::intValue).sum();
if(sum==n&&list.size()==k){
lists.add(new ArrayList<>(list));
return;
}
if(sum>n||list.size()>k)
return;
for(int i=start;i<array.length;i++){
if(array[i]>n)
continue;
list.add(array[i]);
tracking(lists,list,k,n,i+1,array);
list.remove(list.size()-1);
}
}
给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。
输入:nums = [1,2,3] 输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
public List<List<Integer>> permute(int[] nums) {
List<List<Integer>> lists=new ArrayList<>();
if(nums.length==0)
return lists;
ArrayList<Integer> list=new ArrayList<>();
backtracking(lists,list,nums);
return lists;
}
public void backtracking(List<List<Integer>> lists,ArrayList<Integer> list,int[] nums){
if(list.size()==nums.length){
lists.add(new ArrayList<>(list));
return;
}
for(int i=0;i<nums.length;i++){
if(list.contains(nums[i]))
continue;
list.add(nums[i]);
backtracking(lists,list,nums);
list.remove(list.size()-1);
}
}
已知一个长度为 N 的数组:A1, A2, A3, …AN 恰好是 1 ∼ N 的一个排列。现在要求你将 A 数组切分成若干个 (最少一个,最多 N 个) 连续的子数组,并且每个子数组中包含的整数恰好可以组成一段连续的自然数。
例如对于 A = {1, 3, 2, 4}, 一共有 5 种切分方法:
{1}{3}{2}{4}:每个单独的数显然是 (长度为 1 的)
一段连续的自然数。
{1}{3, 2}{4}:{3, 2} 包含 2 到 3,是
一段连续的自然数,另外 {1} 和 {4} 显然也是。
{1}{3, 2, 4}:{3, 2, 4} 包含 2 到 4,是
一段连续的自然数,另外 {1} 显然也是。
{1, 3, 2}{4}:{1, 3, 2} 包含 1 到 3,是
一段连续的自然数,另外 {4} 显然也是。
{1, 3, 2, 4}:只有一个子数组,包含 1 到 4,是
一段连续的自然数。
输入格式
第一行包含一个整数 N。第二行包含 N 个整数,代表 A 数组。
输出格式
输出一个整数表示答案。由于答案可能很大,所以输出其对 1000000007 取模后的值。
样例输入
复制
4 1 3 2 4
样例输出
复制
5
public class m {
static int result=0;
public static void main(String[] args) {
Scanner sc=newScanner(System.in);
int n=sc.nextInt();
int[] arr=newint[n];
for(int i=0;i<arr.length;i++)
arr[i]=sc.nextInt();
backtreeing(arr, 0);
System.out.println(result);
}
public static void backtreeing(int arr[],int start) {
if(start==arr.length) {
result++;
return;
}
for(int i=start;i<arr.length;i++) {
if(check(arr, start, i)) {
backtreeing(arr, i+1);
}
}
}
private static boolean check(int[] a, int l, int r) {
intmax= Integer.MIN_VALUE, min = Integer.MAX_VALUE;
for (int i= l; i <= r; i++) {
if (a[i] > max) max = a[i];
if (a[i] < min) min = a[i];
}
return max - min == r - l;
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/143061.html