代码随想录算法训练营第二十七天| LeetCode39.组合总和、LeetCode40.组合总和II、LeetCode131.分割回文串

LeetCode 39 组合总和

题目链接:39. 组合总和

【解题思路】

本题元素可以重复选取,因此剩余的集合就需要包括当前选取的元素。

【解题步骤】

  • 主函数部分:

    • 【全局变量】path一维数组用来存放单一节点

    • 【全局变量】result二维数组用来存放结果集

    • 调用递归函数,传入candidate,target,0,0

    • return result

  • 递归函数部分:

    • 1.确定参数和返回值:

      • 返回值:

        • void

      • 参数:

        • 题目的数组candidate

        • 目标值target

        • 统计path里面元素的和的变量sum

        • startIndex标志开始遍历的起始位置

    • 2.确定终止条件:

      • 如果sum大于target

        • 直接return

      • 如果sum等于target

        • 收集结果集

        • return

    • 3.确定单层处理逻辑:

      • for循环遍历每一个candidate的数组元素

        • 1)将当前遍历到的元素放入到路径集合path里

        • 2)sum累加当前元素

        • 3)递归,调用当前函数,传入:

          • 数组candidate

          • 目标值target

          • 当前路径总和sum

          • 本题我们可以重复选取元素,因此我们的遍历起始位置在本层是不变的,传入i

        • 4)回溯:

          • sum将当前元素减掉

          • 将当前元素从路径集合path里弹出

【代码部分】

java:

class Solution {
		List<List<Integer>> result = new ArrayList<>();
		List<Integer> path = new ArrayList<>();
    public List<List<Integer>> combinationSum(int[] candidates, int target) {
		Arrays.sort(candidates);
		backTracikng(candidates,target,0,0);
		return result;
    }

	public void backTracikng(int[] candidates,int target,int sum, int startIndex){
		if(sum == target){
			result.add(new ArrayList<>(path));
			return;
		}

		for(int i = startIndex; i< candidates.length; i++){
			if(sum + candidates[i] > target) break;
			path.add(candidates[i]);
			sum+=candidates[i];
			backTracikng(candidates,target,sum,i);
			sum-= candidates[i];
			path.remove(path.size() - 1);//移除最后一个元素
		}
	}

}

LeetCode 40 组合总和II

题目链接:40.组合总和II

【解题思路】

  • 本题元素会有重复,需要进行去重操作

  • 不能出现重复的组合,也不能出现重复的元素

  • 可以在搜索过程中直接进行去重

    • “树层去重”

      • 同一树层上重复元素不可以重复选取

      • 树层去重需要对数组进行排序

      • 用used判断树层元素是否重复

    • “树枝去重”

      • 同一树枝上相同重复元素不可以重复选取

      • 用candidates[i]是否等于candidates[i-1]判断树枝元素是否重复

【解题步骤】

  • 主函数部分:

    • 【全局变量】path一维数组用来存放单一节点

    • 【全局变量】result二维数组用来存放结果集

    • 【全局变量】布尔类型数组used用来记录同一树层上的元素是否使用过

    • 将uesd数组里的元素用false填满

    • 将数组进行排序

    • 调用递归函数,传入candidate,target,0,0

    • return result

  • 递归函数部分:

    • 1.确定参数和返回值:

      • 返回值:

        • void

      • 参数:

        • 题目的数组candidate

        • 目标值target

        • 统计path里面元素的和的变量sum

        • startIndex标志开始遍历的起始位置

    • 2.确定终止条件:

      • 如果sum大于target

        • 直接return

      • 如果sum等于target

        • 收集结果集

        • return

    • 3.确定单层处理逻辑:

      • for循环遍历每一个candidate的数组元素

        • 判断元素是否重复

          • 树枝元素重复:candidates[i]等于candidates[i-1]

          • 树层元素重复:usde[i] == true

        • uesd[i] = true

        • 将当前遍历到的元素放入到路径集合path里

        • sum累加当前元素

        • 递归,调用当前函数,传入:

          • 数组candidate

          • 目标值target

          • 当前路径总和sum

          • 本题我们不可以重复选取元素,因此我们的遍历起始位置需要+1,传入i+1

        • 回溯:

          • used[i] = false

          • sum将当前元素减掉

          • 将当前元素从路径集合path里弹出

【代码部分】

java:

class Solution {
		List<List<Integer>> result = new LinkedList<>();
		List<Integer> path = new ArrayList<>();
		boolean[] used;
    public List<List<Integer>> combinationSum2(int[] candidates, int target) {
		used = new boolean[candidates.length];
		Arrays.fill(used,false);
		Arrays.sort(candidates);
		backTracking(candidates,target,0,0);
		return result;
    }
	public void backTracking(int[] candidates, int target, int sum, int starIndex){
		if(sum == target){
			result.add(new ArrayList<>(path));
		}
		for(int i = starIndex ; i < candidates.length ; i++){
			if(sum + candidates[i] > target)break;
			if( i > 0 && candidates[i] == candidates[i-1] && !used[i-1]){
				continue;
			}
			used[i] = true;
			sum += candidates[i];
			path.add(candidates[i]);

			backTracking(candidates,target,sum,i+1);

			used[i] = false;
			sum -= candidates[i];
			path.remove(path.size() - 1);

		}
	}
}

LeetCode 131 分割回文串

题目链接:131. 分割回文串

【解题思路】

本题是一个分割问题,也可以看作一个树形结构,分割了一个字符之后,再从剩下的字符里进行分割。

【解题步骤】

  • 主函数部分:

    • 【全局变量】path一维数组用来存放单一的分割方案(其实就是收集路径的过程)

    • 【全局变量】result二维数组用来存放符合条件的path

    • 调用递归函数,传入字符串s,开始位置0

    • return result

  • 递归函数部分:

    • 1.确定参数和返回值:

      • 返回值:

        • void

      • 参数:

        • 题目给出的字符串String s

        • startIndex标志开始遍历的起始位置

    • 2.确定终止条件:

      • 如果startIndex大于等于字符串s的长度,说明已经切割到结尾了

        • 收集结果集

        • return

        • 疑问:为什么直接收集结果集,不判断结果是否符合回文字符串的条件呢?

          • 因为在单层搜索逻辑里已经有判断的逻辑了,如果当前不是回文,就不会进行下一次递归

    • 3.确定单层处理逻辑:

      • for循环遍历字符串中的每一个字符

        • 定义一个函数isPalindrome()判断当前切割的子串是否为回文子串,传入起始位置和终止位置

          • 如果当前子串为回文子串,则将其加入path数组里

          • 如果当前子串不是会为子串,直接跳到下一个i

        • 递归,调用当前函数,传入:

          • 字符串s

          • 起始位置i+1

        • 回溯:

          • 将当前字符从path里弹出

【代码部分】

java:

class Solution {
	List<List<String>> result = new ArrayList<>();
	Deque<String> path = new LinkedList<>();

	public List<List<String>> partition(String s) {
		backTracking(s,0);
		return result;
	}

	public void backTracking(String s, int starIndex){
		if(starIndex >= s.length()){
			result.add(new ArrayList(path));
			return;
		}
		for (int i = starIndex; i <s.length() ; i++) {
			if(isPalindrome(s,starIndex,i)){
				String str = s.substring(starIndex,i+1);
				path.addLast(str);
			}else{
				continue;
			}

			backTracking(s,i+1);

			path.removeLast();
		}
	}

	public boolean isPalindrome(String s,int startIndex, int end){
		for(int i= startIndex , j = end; i < j ; i++, j--){
			if(s.charAt(i) != s.charAt(j))return false;
		}
		return true;
	}
}

  • 26
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值