Leetcode77:组合问题

void backtrack(参数列表) {
    if (终止条件) {
        收集结果;
        return;
    }
    
    for (选择范围内的选项) {
        做出选择;
        backtrack(新参数);  // 递归
        撤销选择;  // 回溯,恢复状态
    }
}

LeetCode 77题(组合)要求从1到n中选择k个数字的所有可能组合,且组合中的元素不能重复,顺序不影响组合的唯一性(例如[1,2]和[2,1]视为同一个组合)。

这是一个典型的组合问题,适合用回溯算法解决。

解题思路解析

  1. 回溯算法框架

    • 选择:从1到n中选择一个数字
    • 约束:每个数字只能选一次,且组合中数字递增(避免重复)
    • 目标:选出k个数字
  2. 关键优化

    • 通过start参数控制每次选择的起始位置,确保组合中的数字递增,避免产生重复组合
    • 剪枝操作:计算i的上限为n - (k - path.size()) + 1,减少不必要的循环
  3. 时间复杂度

    • 生成了C(n,k)个组合,每个组合需要O(k)的时间复制到结果中
    • 总体时间复杂度为O(C(n,k) × k)
import java.util.ArrayList;
import java.util.List;

public class Combinations {
    public List<List<Integer>> combine(int n, int k) {
        List<List<Integer>> result = new ArrayList<>();
        // 处理边界情况
        if (n < k || k <= 0) {
            return result;
        }
        // 调用回溯函数
        backtrack(n, k, 1, new ArrayList<>(), result);
        return result;
    }
    
    /**
     * 回溯函数
     * @param n 范围上限
     * @param k 需要选择的数字个数
     * @param start 起始数字(用于避免重复组合)
     * @param path 当前路径(已选择的数字)
     * @param result 结果集合
     */
    private void backtrack(int n, int k, int start, List<Integer> path, List<List<Integer>> result) {
        // 终止条件:已选择k个数字
        if (path.size() == k) {
            result.add(new ArrayList<>(path));
            return;
        }
        
        // 遍历可能的选择
        // 剪枝优化:i的上限可以计算为n - (k - path.size()) + 1
        for (int i = start; i <= n - (k - path.size()) + 1; i++) {
            // 做出选择
            path.add(i);
            // 递归:下一次选择从i+1开始,避免重复
            backtrack(n, k, i + 1, path, result);
            // 撤销选择(回溯)
            path.remove(path.size() - 1);
        }
    }
    
    public static void main(String[] args) {
        Combinations solution = new Combinations();
        
        // 测试用例
        System.out.println(solution.combine(4, 2));
        // 输出: [[1,2], [1,3], [1,4], [2,3], [2,4], [3,4]]
        
        System.out.println(solution.combine(1, 1));
        // 输出: [[1]]
    }
}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值