返回

破解搜索算法中的搜索策略和剪枝技巧,掌握 LeetCode 数字组合问题!

人工智能

在 LeetCode 的浩瀚题目库中,搜索算法是一道绕不过去的坎。今天,我们来深入剖析数字组合问题,并揭开搜索策略和剪枝技巧的神秘面纱,助你轻松应对这类难题!

算法概要

给定一个候选数字集和一个目标和,要求找出所有数字组合,使得组合中数字之和恰好等于目标和。

暴力解法

初学者可能会想到暴力的回溯算法:枚举所有可能的组合,并检查它们是否满足目标和。但这种方法的复杂度为 O(2^n),其中 n 是候选数字的个数,对于大规模数据集来说是不可行的。

搜索策略

为了优化搜索,我们需要引入以下搜索策略:

  • 深度优先搜索 (DFS): 从候选数字集的第一个数字开始,递归地探索所有可能的组合。
  • 广度优先搜索 (BFS): 将候选数字集的所有排列作为一组队列,并按队列的广度进行探索。

剪枝技巧

剪枝技巧可以大幅减少搜索空间,提高算法效率:

  • 排序剪枝: 将候选数字从小到大排序,可以避免探索重复的组合。
  • 和剪枝: 在 DFS 过程中,如果当前组合的和大于目标和,则可以立即终止该分支的搜索。

LeetCode 样例

考虑 LeetCode 中的经典数字组合问题:

  • 候选数字集: [2, 3, 6, 7]
  • 目标和: 7

解法:

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

public class Solution {

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

    private void dfs(int[] candidates, int target, int start, List<Integer> combination, List<List<Integer>> result) {
        if (target == 0) {
            result.add(new ArrayList<>(combination));
            return;
        }
        if (target < 0) {
            return;
        }
        for (int i = start; i < candidates.length; i++) {
            if (i > start && candidates[i] == candidates[i - 1]) {
                continue;
            }
            combination.add(candidates[i]);
            dfs(candidates, target - candidates[i], i + 1, combination, result);
            combination.remove(combination.size() - 1);
        }
    }
}