回溯算法学习

一、电话号码的字母组合

复制代码
import java.util.ArrayList;
import java.util.List;

import javax.management.loading.PrivateClassLoader;

public class letterCombinations {
	private static final String[] KEYPAD= {
			"",  //0
			"",  //1
			"abc", //2
			"def",
			"ghi",
			"jkl",
			"mno",
			"pqrs",
			"tuv",
			"wxyz"		
	};
public List<String> letterCombinations(String digits) {
List<String>result=new ArrayList<>();
if(digits==null||digits.isEmpty()) {
	return result;
}
backtrack(digits,0,new StringBuilder(),result);
return result;
        
    }
private void backtrack(String digits, int index, StringBuilder path, List<String> result) {
	// TODO Auto-generated method stub
	//当路径长度等于数字串长度,加入到结果列表
	if(path.length()==digits.length()) {
		result.add(path.toString());
		return;
	}
	//获取当前数字对应的字母集
	char digit=digits.charAt(index);
	String letterString =KEYPAD[digit-'0'];
	//遍历字母集,递归处理下一个数字
	for(char c:letterString.toCharArray()) {
		path.append(c);
		backtrack(digits, index+1, path, result);
		//回溯,删除最后添加的字符
		path.deleteCharAt(path.length()-1);
	}
}
}

String letterString=Keypad[digit-'0'];

在Java里,字符类型(char)本质上是整数类型,它存储的是字符对应的Unicode码点值。数字字符'0'到'9'的Unicode码点是连续的,其范围是从48(对应字符'0')到57(对应字符'9')。

复制代码
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class CombinationSum {
    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        List<List<Integer>> result = new ArrayList<>();
        List<Integer> path = new ArrayList<>();
        // 排序,方便剪枝
        Arrays.sort(candidates); 
        backtrack(candidates, target, 0, path, result);
        return result;
    }

    private void backtrack(int[] candidates, int remain, int start, 
                           List<Integer> path, List<List<Integer>> result) {
        if (remain == 0) {
            // 找到符合条件的组合,加入结果集(注意要 new 新的 ArrayList 避免引用问题)
            result.add(new ArrayList<>(path)); 
            return;
        }
        for (int i = start; i < candidates.length; i++) {
            if (candidates[i] > remain) {
                // 当前元素已超过剩余目标和,由于数组有序,后续元素更大,直接剪枝
                break; 
            }
            // 选择当前元素
            path.add(candidates[i]); 
            // 递归,可重复选当前元素,所以 start 还是 i
            backtrack(candidates, remain - candidates[i], i, path, result); 
            // 撤销选择,回溯
            path.remove(path.size() - 1); 
        }
    }

    public static void main(String[] args) {
        CombinationSum solution = new CombinationSum();
        int[] candidates = {2, 3, 6, 7};
        int target = 7;
        List<List<Integer>> result = solution.combinationSum(candidates, target);
        for (List<Integer> list : result) {
            System.out.println(list);
        }
    }
}
  • 排序与剪枝 :对 candidates 排序后,当 candidates[i] > remain 时,后续元素必然也大于 remain,直接 break 可减少递归次数,提升效率。
  • 回溯逻辑path 记录当前组合,递归时通过 remain - candidates[i] 更新剩余目标和,start 保持为 i 实现元素可重复选取;递归返回后 path.remove 撤销选择,继续尝试其他分支。
  • 结果收集 :当 remain == 0 时,将 path 复制到新的 ArrayList 再加入 result,避免后续 path 变化影响已加入结果。
相关推荐
简佐义的博客8 分钟前
生信入门进阶指南:学习顶级实验室多组学整合方案,构建肾脏细胞空间分子图谱
人工智能·学习
近津薪荼10 分钟前
dfs专题4——二叉树的深搜(验证二叉搜索树)
c++·学习·算法·深度优先
rannn_11136 分钟前
【苍穹外卖|Day4】套餐页面开发(新增套餐、分页查询、删除套餐、修改套餐、起售停售)
java·spring boot·后端·学习
张人玉1 小时前
VisionPro 定位与卡尺测量学习笔记
笔记·学习·计算机视觉·vsionprp
觉醒大王1 小时前
强女思维:着急,是贪欲外显的相。
java·论文阅读·笔记·深度学习·学习·自然语言处理·学习方法
YCY^v^2 小时前
JeecgBoot 项目运行指南
java·学习
云小逸2 小时前
【nmap源码解析】Nmap OS识别核心模块深度解析:osscan2.cc源码剖析(1)
开发语言·网络·学习·nmap
JustDI-CM3 小时前
AI学习笔记-提示词工程
人工智能·笔记·学习
悟纤3 小时前
学习与专注音乐流派 (Study & Focus Music):AI 音乐创作终极指南 | Suno高级篇 | 第33篇
大数据·人工智能·深度学习·学习·suno·suno api
爱写bug的野原新之助3 小时前
加密摘要算法MD5、SHA、HMAC:学习笔记
笔记·学习