回溯法---

算法核心

for循环中,处理节点 放一些和回溯中间变量相关的操作,然后在第三步的回溯操作中,对处理节点的操作做回溯处理

void backtracking(参数) {
 if (终⽌条件) {
 存放结果;
 return;
 }
 for (选择:本层集合中元素(树中节点孩⼦的数量就是集合的⼤⼩)) {
 处理节点;
 backtracking(路径,选择列表); // 递归
 回溯,撤销处理结果
 }
}

联系

leetcode_22

括号。设计一种算法,打印n对括号的所有合法的(例如,开闭一一对应)组合

思路

主要思路还是上面的方法。
终止条件分为两种,一种是列举完所有的括号后,将结果存入到最终的集合中;因为这里要求了合法结果,所以还有一个判断的过程,这里的合法很好判断,左括号大于等于右括号的数量,则一定合法。

循环没有使用for循环,因为只有左右两种,所以穷举了出来,配合两个计数变量。 穷举时,先左后右,处理结果、递归和回溯,这三步不变。

储存中间变量用的集合是栈,方便回溯。

	List<String> result = new ArrayList<>();

    public List<String> generateParenthesis(int n) {
        // 这里的参数使用栈,方便回溯
        backtracking(n, n, new Stack<>());
        return result;
    }

    public void backtracking(int left, int right, Stack<Character> stack) {
        // 剩余的左括号数量更大的话,则不合法,直接退出
        if (left > right) {
            return;
        }
        // 所有情况都列举完,也直接推出
        if (left == 0 && right == 0) {
            result.add(toString(stack));
        }
        // 插入左
        if (left > 0) {
            stack.push('(');
            backtracking(--left, right, stack);
            stack.pop();
            left++;
        }
        // 插入右
        if (right > 0) {
            stack.push(')');
            backtracking(left, --right, stack);
            stack.pop();
            right++;
        }
    }

    public String toString(Stack<Character> stack) {
        StringBuilder sb = new StringBuilder();
        stack.stream().forEach(item -> sb.append(item));
        return sb.toString();
    }

leetcode_39

class Solution {
  List<List<Integer>> result = new ArrayList<>();
    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        for (int i = 0; i < candidates.length; i++) {
            List<Integer> start = new ArrayList<>();
            start.add(candidates[i]);
            back(start, candidates[i], target, i, candidates);
        }
        return result;
    }

    public void back(List<Integer> list, int sum, int target, int currentIndex, int[] candidates) {
        if (sum > target || candidates[currentIndex] > target) {
            return;
        }
        if (sum == target) {
            result.add(new ArrayList<>(list));
            return;
        }

        for (int i = currentIndex ; i < candidates.length; i++) {
            sum += candidates[i];
            list.add(candidates[i]);
            back(list, sum, target, i, candidates);
            sum -= candidates[i];
            list.remove(list.size() - 1);
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值