Day27~77. 组合

2023年 10月 2日 62.6k 0

摘要

本文主要介绍了回溯算法的理论基础和回溯法模版,以及LeetCode中77.组合问题的解题思路和代码。

1、回溯算法理论基础

1.1 概念

回溯算法是一种用于解决组合问题、排列问题和搜索问题的常用算法。它基于深度优先搜索的思想,通过不断地尝试各种可能的选择,然后回退到上一步,直到找到问题的解或穷尽所有可能性。

回溯算法的核心思想是构建一棵决策树,每个节点表示在问题中的一个决策点,从根节点出发,逐步向下扩展树,直到找到解或无法继续扩展。如果遇到无法继续扩展的情况,就回退到上一层节点,尝试其他分支。

以下是回溯算法的基本框架和关键要点:

  • 路径(Path): 在算法执行过程中,需要维护一个路径,用于记录当前的选择或决策。
  • 选择列表(Choices): 每一步都有一个或多个选择,算法需要生成当前状态下的所有候选选择。
  • 结束条件(Termination Condition): 定义何时达到问题的解,当满足结束条件时,算法结束。
  • 回溯过程(Backtracking): 如果当前路径无法达到解或满足条件,算法需要回退到上一个状态,尝试其他选择。
  • 下面是一个简单的 Java 示例,用于解决组合问题(找到数组中所有可能的组合):

    import java.util.ArrayList;
    import java.util.List;

    public class BacktrackingExample {
       public List combine(int n, int k) {
           List result = new ArrayList();
           List path = new ArrayList();
           backtrack(result, path, n, k, 1);
           return result;
      }

       private void backtrack(List result, List path, int n, int k, int start) {
           // 结束条件:已选择的元素数量达到 k
           if (path.size() == k) {
               result.add(new ArrayList(path));
               return;
          }

           // 选择列表:从 start 到 n 中选择一个数加入当前组合
           for (int i = start; i n
    时,表示已经考虑完了所有可选数字,直接返回。
  • 进行选择和递归: 在递归函数的主体部分,我们需要考虑两种情况:

    • 选择当前数字 i,将其添加到当前组合中,然后递归调用函数,传递参数 i+ 1k - 1
    • 不选择当前数字 i,直接递归调用函数,传递参数 i+ 1k
  • 撤销选择: 在每一次递归返回后,需要撤销选择,即将当前数字从组合中移除,以便考虑下一个数字的选择。

  • 回溯搜索: 通过不断地进行选择和递归,回溯算法会搜索所有可能的组合。

  • 1、可以剪枝优化吗?

    例如,对于给定的参数 n = 4, k = 2,当遍历选择列表时,需要考虑 k 的值来确定循环的范围。具体来说,当 k = 2 时,如果 n = 3,我们可以继续遍历,但如果 n = 4,则不应该继续遍历。因此,我们可以调整循环变量 i 的取值范围为 [start, (n - k + 1) + linked.size()]

    这个调整确保了在当前状态下,仅考虑那些可以生成有效组合的数字。这是一个很好的优化,以减少不必要的遍历,加快算法的执行速度。

    77.组合4

    2.2 代码

    未剪枝优化

        public List combine(int n, int k) {
           List list = new ArrayList();
           LinkedList linked = new LinkedList();
           combine(list, linked, n, k, 1);
           return list;
      }

       public void combine(List list, LinkedList linked, int n, int k, int start) {
           if(linked.size() == k) {
               list.add(new ArrayList(linked));
               return;
          }

           for(int i=start; i

    相关文章

    JavaScript2024新功能:Object.groupBy、正则表达式v标志
    PHP trim 函数对多字节字符的使用和限制
    新函数 json_validate() 、randomizer 类扩展…20 个PHP 8.3 新特性全面解析
    使用HTMX为WordPress增效:如何在不使用复杂框架的情况下增强平台功能
    为React 19做准备:WordPress 6.6用户指南
    如何删除WordPress中的所有评论

    发布评论