39.组合总和
思路:递归结束条件就是找到了这个target,并将结果放进去。至于超过target的情况就break,不找了。因为从小到大,接着找只会越来越大。其他情况就是小于那么先将当前的candidate[i] 放进temp 接着backtracing下一个数。
关键点:注意是可以重复的所以,在递归的时候的i不应去加1了。要是加一就是不重复的代码。
class Solution {
List<List<Integer>> ans = new ArrayList<>();
LinkedList<Integer> temp = new LinkedList<>();
public List<List<Integer>> combinationSum(int[] candidates, int target) {
// 这里的是可以重复使用
Arrays.sort(candidates); // 要先进行排序 从小到大。不然第一个就超出了后面就不运行了
backtracking(candidates, target,0,ans,temp);
return ans;
}
public void backtracking(int[] candidates, int target, int index, List<List<Integer>> ans, LinkedList<Integer> temp){
if(target == 0){
ans.add(new ArrayList(temp));
return;
}
for(int i=index;i<candidates.length;i++){
if(target - candidates[i]<0){
break;
}
temp.add(candidates[i]);
backtracking(candidates,target-candidates[i],i,ans,temp); // 因为可以重复,所以i 不用+1
temp.remove(temp.size() -1);
}
}
}
LeetCode40组合总和2
思路:这里的区别主要是去重。
而且是对每一层中不可以去重复数。节点内可以重复的。
这里没有使用一个辅助数组,只是在for循环的逻辑加了一个判断,前后不可以数字相等。
class Solution {
List<List<Integer>> ans = new ArrayList<>();
LinkedList<Integer> temp = new LinkedList<>();
public List<List<Integer>> combinationSum2(int[] candidates, int target){
// 本题candidates 中的每个数字在每个组合中只能使用一次。
// 本题数组candidates的元素是有重复的,而39.组合总和 (opens new window)是无重复元素的数组candidates
// 这题多了一层去重的逻辑
Arrays.sort(candidates);
backtracing(candidates, target, 0, ans, temp);
return ans;
}
public void backtracing(int[] candidates, int target, int index, List<List<Integer>> ans, LinkedList<Integer> temp){
if(target == 0){
ans.add(new ArrayList(temp));
}
for(int i=index;i<candidates.length;i++){
if(target - candidates[i]<0){
break;
}
if(i>index && candidates[i] == candidates[i-1]){ // 加了一个逻辑来判断这个数之前是否选过。而且这里的去重是对每一层里面不能选重复的,而不是叶子里不能选重复的。按照那个图来理解。
continue;
}
temp.add(candidates[i]);
backtracing(candidates, target-candidates[i], i+1, ans, temp); // 元素只能使用一次,因此i+1
temp.remove(temp.size() - 1);
}
}
}
LeetCode131分割回文串
关于String的处理函数要熟悉
在Java中,String类提供了许多用于处理字符串的常见函数。以下是一些常用的String函数:
-
length(): 返回字符串的长度。
String str = "Hello"; int length = str.length(); // length = 5
-
charAt(int index): 返回字符串中指定索引位置的字符。
String str = "Hello"; char ch = str.charAt(1); // ch = 'e'
-
substring(int beginIndex): 返回从指定索引位置开始到字符串末尾的子字符串。
String str = "Hello"; String subStr = str.substring(1); // subStr = "ello"
-
substring(int beginIndex, int endIndex): 返回从指定的开始索引位置到指定的结束索引位置之间的子字符串。
String str = "Hello"; String subStr = str.substring(1, 4); // subStr = "ell"
-
equals(String anotherString): 比较两个字符串是否相等。
String str1 = "Hello"; String str2 = "hello"; boolean isEqual = str1.equals(str2); // isEqual = false
-
equalsIgnoreCase(String anotherString): 忽略大小写,比较两个字符串是否相等。
String str1 = "Hello"; String str2 = "hello"; boolean isEqual = str1.equalsIgnoreCase(str2); // isEqual = true
-
indexOf(String str): 返回指定子字符串第一次出现的索引位置。
String str = "Hello world"; int index = str.indexOf("world"); // index = 6
-
lastIndexOf(String str): 返回指定子字符串最后一次出现的索引位置。
String str = "Hello world"; int index = str.lastIndexOf("o"); // index = 7
-
replace(char oldChar, char newChar): 将字符串中的指定字符替换为新的字符。
String str = "Hello"; String newStr = str.replace('l', 'L'); // newStr = "HeLLo"
-
toLowerCase(): 将字符串转换为小写。
String str = "Hello"; String lowerCaseStr = str.toLowerCase(); // lowerCaseStr = "hello"
-
toUpperCase(): 将字符串转换为大写。
String str = "Hello"; String upperCaseStr = str.toUpperCase(); // upperCaseStr = "HELLO"
这只是一些常见的String函数示例,Java的String类还提供了许多其他有用的函数,可以根据具体的需求选择适当的函数进行字符串处理。
思路:
- 切割问题可以抽象为组合问题
- 如何模拟那些切割线
- 切割问题中递归如何终止
- 在递归循环中如何截取子串
- 如何判断回文
和组合一致,横向for的时候依次向后面选(划分)。只不过在内部要判断从当前index开始到后面每个字符能不能组成回文。
满足回文的情况就添加到temp 并递归回溯。
class Solution {
List<List<String>> ans = new ArrayList<>();
LinkedList<String> temp = new LinkedList<>();
public List<List<String>> partition(String s) {
backtracing(s,0);
return ans;
}
public void backtracing(String s, int index){
if(index == s.length()){ // index是便利s中的元素,如果index已经超过了s.length 表示有结果了
ans.add(new ArrayList(temp));
}
for(int i=index;i<s.length();i++){
if(isPalindrome(s, index, i)){ // 从每个index开始遍历后面的字符 判断是否为回文
String strSub = s.substring(index, i+1); // 左闭右开
temp.add(strSub);
backtracing(s, i+1);
temp.removeLast();
}
// else{
// continue; // 如果不是回文,则下面的代码也不执行,并且跳到下一个
// }
}
}
private boolean isPalindrome(String s, int start, int end){ // 判断是否为回文的基础方法,这里可以用动态规划来做优化。
for(int i=start,j=end;i<j;i++,j--){
if(s.charAt(i) != s.charAt(j)){
return false;
}
}
return true;
}
}