关于回溯算法
问题描述:
关于力扣22题
使用递归的回溯算法实现,波波老师这里我发现一个问题,就是直接在递归函数外面进行变量(本题中的leftCount, rightCount)的改变,无论是++还是+=1跟我想象的答案都不一样,但是如果直接在递归函数中+1就是正确答案,这是什么原因啊老师。虽然感觉这问题很蠢但我还是想不通,明明递归带进去的值都是一样的,结果竟然完全不同
相关代码:
import java.util.LinkedList;
import java.util.List;
class Solution {
/**
* LC.22 括号生成:生成n对括号所有的有效组合
*/
public List<String> generateParenthesis(int n) {
//接受答案string的链表
List<String> res = new LinkedList<>();
//然后调用回溯递归方法
String str = "";
generateParenthesis(n, 0, 0, str, res);
return res;
}
/**
* 递归回溯方法
* 我觉得无从下手的原因有两条
* 1.没有看出左括号数与右括号数的三种情况递归中不同处理
* 而是想的是算出所有可能性,再去判断括号合法性
* 2. 要注意递归函数中是String,需要添加东西时再改成StringBuilder
*
* @param n :括号的对数,当leftCount==rightCount==n的时候 说明可以添加进链表
* @param leftCount :记录左括号的个数
* @param rightCount : 记录右括号的个数
* @param str :传入的字符串,递归的时候一定要固定住当前的字符
* @param res : 答案添加至链表
* 不需要返回值 已经添加再链表里了
*/
private void generateParenthesis(int n, int leftCount, int rightCount, String str, List<String> res) {
//1.一旦leftCount<rightCount 括号无效直接返回
if (rightCount > leftCount) {
return;
}
//2. 一旦left==right==n 直接添加
if (rightCount == n && leftCount == n) {
/**有可能添加元素一样 增加一个判断*/
// System.out.println(str + " Added!");
res.add(str);
return;
}
//3.如果left>=right 只要left<n 就递归添加左括号 只要right<n 递归添加右括号
StringBuilder stringBuilder = new StringBuilder(str);
if (leftCount < n) {
// System.out.println("cur str="+str+" Add (");
// System.out.println("leftCount=" + leftCount + " rightCount=" + rightCount);
stringBuilder.append("(");
// leftCount+=1;
generateParenthesis(n, leftCount + 1, rightCount, stringBuilder.toString(), res);
}
if (rightCount <= leftCount) {
// System.out.println("cur str="+str+" Add )");
// System.out.println("leftCount=" + leftCount + " rightCount=" + rightCount);
stringBuilder.append(")");
// rightCount++;
generateParenthesis(n, leftCount, rightCount + 1, stringBuilder.toString(), res);
}
}
}
源自:非比较排序
1-1 什么是计数排序
13
收起
正在回答
1回答
你的整个思路是正确的,但问题在于,如果 leftCount < n 同时 rightCount <= leftCount 的话,在你的 递归过程中,stringBuilder 先添加了一个左括号,然后在同层,有添加了一个右括号,可实际上,你要表达的逻辑,在每次递归调用中,只能添加一个括号(或左或右)。
所以,你需要在添加左括号以后,将添加的左括号删掉。加上一句话就正确了:
private void generateParenthesis(int n, int leftCount, int rightCount, String str, List<String> res) { if (rightCount > leftCount) return; if (rightCount == n && leftCount == n) { res.add(str); return; } StringBuilder stringBuilder = new StringBuilder(str); if (leftCount < n) { stringBuilder.append("("); generateParenthesis(n, leftCount + 1, rightCount, stringBuilder.toString(), res); // 在这里将添加的左括号删掉!!!! stringBuilder.deleteCharAt(stringBuilder.length() - 1); } if (rightCount <= leftCount) { stringBuilder.append(")"); generateParenthesis(n, leftCount, rightCount + 1, stringBuilder.toString(), res); } }
另外,整个逻辑其实可以不使用 StringBuilder,下面的代码,我基于你的代码,完全使用 String。而且,这样做,我不需要做这个“删掉”的动作。请仔细体会这是为什么。
private void generateParenthesis(int n, int leftCount, int rightCount, String str, List<String> res) { if (rightCount > leftCount) return; if (rightCount == n && leftCount == n) { res.add(str); return; } if (leftCount < n) generateParenthesis(n, leftCount + 1, rightCount, str + "(", res); if (rightCount <= leftCount) generateParenthesis(n, leftCount, rightCount + 1, str + ")", res); }
继续加油!:)
恭喜解决一个难题,获得1积分~
来为老师/同学的回答评分吧
0 星