backtracking Leetcode 回溯算法题

77.组合

第一个位置选择有 n 种,接下来每个位置只能在前面选择数字的后面选,所以有了 beg 参数,才能保持不重复

剪枝:res.size + (n - beg + 1) < k , 已有答案的长度 + 剩余所有未选择的个数 都小于最终答案长度了 就没有必要尝试下去

class Solution {List<List<Integer>> ans = new ArrayList<List<Integer>>();public List<List<Integer>> combine(int n, int k) {List<Integer> res = new ArrayList<Integer>();dfs(res, 1, n, k);return ans;}public void dfs(List<Integer> res, int beg, int n, int k){if(k == 0){// 这里一定要 new 一个新的 ArrayList 啊,否则最后加进去的 res 都是 nullans.add(new ArrayList<Integer>(res));return;}if(res.size() + n - beg + 1 < k) return;for(int i = beg; i <= n; ++ i){res.add(i);dfs(res, i + 1, n, k - 1);res.remove(res.size() - 1);}}
}

216.组合总和III

class Solution {List<Integer> res = new ArrayList<>();List<List<Integer>> ans = new ArrayList<List<Integer>>();public List<List<Integer>> combinationSum3(int k, int n) {dfs(1, k, n);return ans;}public void dfs(int beg, int k, int n){if(k < 0 || n < 0){return;}// 剩下最大的 k 个数相加都小于 n || 最小的 k 个数相加都大于 n : 也就没有必要继续遍历了if(k*(19-k)/2 < n || k*(2*beg+k-1)/2 > n){return;}if(k == 0 && n == 0){ans.add(new ArrayList(res));return;}for(int i = beg; i <= 9; ++ i){res.add(i);dfs(i + 1, k - 1, n - i);res.remove(res.size() - 1);}}
}

随想录代码:

class Solution {List<List<Integer>> result = new ArrayList<>();LinkedList<Integer> path = new LinkedList<>();public List<List<Integer>> combinationSum3(int k, int n) {backTracking(n, k, 1, 0);return result;}private void backTracking(int targetSum, int k, int startIndex, int sum) {// 减枝if (sum > targetSum) {return;}if (path.size() == k) {if (sum == targetSum) result.add(new ArrayList<>(path));return;}// 减枝 9 - (k - path.size()) + 1for (int i = startIndex; i <= 9 - (k - path.size()) + 1; i++) {path.add(i);sum += i;backTracking(targetSum, k, i + 1, sum);//回溯path.removeLast();//回溯sum -= i;}}
}

17.电话号码的字母组合

第一次遍历判断第一个位置的 beg 所对应的字符 idx,遍历所有字符的可能

第二次遍历判断第二个位置的 beg + 1 所对应的字符 idx,遍历所有字符的可能

一直到所有位置都被遍历完,也就是 digits 所有位置都被遍历完,那么 beg 就等于 digits.length() 了,此时记录答案

注意,digits 的第 beg 位置,对应的数字是 idx,该 idx 对应的字符才是要遍历的字符

  • 字符串中提取对应位置的字符:digits.chatAt(beg)
  • 字符 char 转为 int 类型:
    • 首先 char 转为 String :String.valueOf(x)
    • String 转为 int : Integer.parseInt(xx)
class Solution {List<String> table = Arrays.asList("", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz");List<String> ans = new ArrayList<>();public List<String> letterCombinations(String digits) {if(digits.equals("")) return ans;dfs(digits, new StringBuilder(), 0);return ans;}public void dfs(String digits, StringBuilder res, int beg){if(beg == digits.length()){ans.add(res.toString());return;}int idx = Integer.parseInt(String.valueOf(digits.charAt(beg)));for(int j = 0; j < table.get(idx).length(); ++j){res.append(table.get(idx).charAt(j));dfs(digits, res, beg + 1);res.delete(beg, beg + 1);}}
}

39.组合总和

不限制元素使用次数,使其达到目标数,的所有不同组合

  • 由于可以重复选取,所以 i 没有+1
  • 由于结果要求组合不同,所以不能选 i 之前的数,这里用for循环让 i 只能往后选择剩余的数
class Solution {List<Integer> res = new ArrayList<>();List<List<Integer>> ans = new ArrayList<List<Integer>>();public List<List<Integer>> combinationSum(int[] candidates, int target) {dfs(res, candidates, target, 0);return ans;}public void dfs(List<Integer> res, int[] candidates, int target, int beg){if(target < 0){return;}if(target == 0){ans.add(new ArrayList(res));return;}for(int i = beg; i < candidates.length; ++ i){res.add(candidates[i]);dfs(res, candidates, target - candidates[i], i);res.remove(res.size() - 1);}}
}

40.组合总和II

元素有重复,选出总和达到目标数的不同组合

由于元素有重复,所以一个数只能连续的被使用,那么就需要对原数组排序

我这里使用了一个freq记录每个数的可使用次数,当这个数的使用次数被用完,或者以后都不打算使用这个数的时候,才可以用下一个数

class Solution {List<int[]> freq = new ArrayList<>();List<Integer> res = new ArrayList<>();List<List<Integer>> ans = new ArrayList<List<Integer>>();public List<List<Integer>> combinationSum2(int[] candidates, int target) {Arrays.sort(candidates);int num = 1, size = candidates.length;for(int i = 0; i < size; ++ i){if(i < size -1 && candidates[i] == candidates[i+1]){++num;}else{freq.add(new int[]{candidates[i], num});num = 1;}}dfs(target, 0);return ans;}public void dfs(int target, int beg){if(target < 0){return;}if(target == 0){ans.add(new ArrayList<>(res));}for(int i = beg; i < freq.size(); ++i){res.add(freq.get(i)[0]);--freq.get(i)[1];dfs(target-freq.get(i)[0], freq.get(i)[1] == 0 ? i+1 : i);res.remove(res.size() - 1);++freq.get(i)[1];}}
}

更优雅

另一个方法是让当前搜索层级里不出现相同的元素,要想同一个值使用多次,则必须在dfs的下一个层级

class Solution {List<Integer> res = new ArrayList<>();List<List<Integer>> ans = new ArrayList<List<Integer>>();public List<List<Integer>> combinationSum2(int[] candidates, int target) {Arrays.sort(candidates);dfs(candidates, target, 0);return ans;}public void dfs(int[] candidates, int target, int beg){if(target < 0){return;}if(target == 0){ans.add(new ArrayList<>(res));}for(int i = beg; i < candidates.length; ++i){if(i > beg && candidates[i] == candidates[i-1]){continue;}res.add(candidates[i]);dfs(candidates, target-candidates[i], i+1);res.remove(res.size() - 1);}}
}

131.分割回文串

动态规划

动态规划判断一个字串是否回文:

f[i][j] = f[i+1][j-1] && (s.charAt(i) == s.charAt(j));

注意,先定后边界 j,再遍历所有前边界 i

dfs 遍历所有可能划分

class Solution {boolean[][] f;List<String> seq = new ArrayList<>();List<List<String>> res = new ArrayList<List<String>>();public List<List<String>> partition(String s) {int n = s.length();f = new boolean[n][n];for(int i = 0; i < n; ++ i){for(int j = 0; j <= i; ++ j){f[i][j] = true;}}for(int j = 1; j < n; ++ j){for(int i = 0; i < j; ++ i){f[i][j] = f[i+1][j-1] && (s.charAt(i) == s.charAt(j));}}dfs(s, 0);return res;}public void dfs(String s, int beg){if(beg == s.length()){res.add(new ArrayList<String>(seq));return;}for(int j = beg; j < s.length(); ++ j){if(f[beg][j]){seq.add(s.substring(beg, j + 1));dfs(s, j + 1);seq.remove(seq.size() - 1);}}}
}

记忆化搜索

将回文串的判断用dfs实现:

class Solution {int[][] f;List<String> seq = new ArrayList<>();List<List<String>> res = new ArrayList<List<String>>();public List<List<String>> partition(String s) {int n = s.length();f = new int[n][n];dfs(s, 0);return res;}public void dfs(String s, int beg){if(beg == s.length()){res.add(new ArrayList<String>(seq));return;}for(int j = beg; j < s.length(); ++ j){if(isHuiwen(s, beg, j) == 1){seq.add(s.substring(beg, j + 1));dfs(s, j + 1);seq.remove(seq.size() - 1);}}}public int isHuiwen(String s, int i, int j){if(f[i][j] != 0){return f[i][j];}if(i >= j){f[i][j] = 1;}else if(s.charAt(i) == s.charAt(j)){f[i][j] = isHuiwen(s, i+1, j-1);}else{f[i][j] = -1;}return f[i][j];}
}

78.子集

  • 迭代法:可以枚举二进制
  • 回溯法:
class Solution {List<List<Integer>> res = new ArrayList<List<Integer>>();List<Integer> ans = new ArrayList<>();public List<List<Integer>> subsets(int[] nums) {dfs(nums, 0);return res;}public void dfs(int[] nums, int beg){res.add(new ArrayList(ans));if(beg == nums.length){return;}for(int i = beg; i < nums.length; ++ i){ans.add(nums[i]);dfs(nums, i + 1);ans.remove(ans.size()-1);}}
}

90.子集II

与之前的 40.组合总和II 解法相同,但没有达到目标数的要求,更简单。

class Solution {List<List<Integer>> res = new ArrayList<List<Integer>>();List<Integer> ans = new ArrayList<>();public List<List<Integer>> subsetsWithDup(int[] nums) {Arrays.sort(nums);dfs(nums, 0);return res;}public void dfs(int[] nums, int beg){res.add(new ArrayList(ans));for(int i = beg; i < nums.length; ++ i){if(i > beg && (nums[i-1] == nums[i])){continue;}ans.add(nums[i]);dfs(nums, i + 1);ans.remove(ans.size() - 1);}}
}

491.递增子序列

由于元素有重复且需要维护相对顺序,所以无法通过排序去重

使用 HashSet 对同一层的数据去重

class Solution {List<List<Integer>> res = new ArrayList<List<Integer>>();List<Integer> ans = new ArrayList<>();public List<List<Integer>> findSubsequences(int[] nums) {dfs(nums, 0, -101);return res;}public void dfs(int[] nums, int beg, int pre){if(ans.size() > 1){res.add(new ArrayList(ans));}Set<Integer> used = new HashSet<>();for(int i = beg; i < nums.length; ++ i){if(nums[i] < pre || used.contains(nums[i])) {continue;}used.add(nums[i]);ans.add(nums[i]);dfs(nums, i + 1, nums[i]);ans.remove(ans.size() - 1);}}
}

46.全排列

将一个无重复元素的数组全排列

used 记录已经使用过的元素

每次都遍历所有,只往下 dfs 未使用的元素

class Solution {boolean[] used;int n;List<Integer> ans = new ArrayList<>();List<List<Integer>> res = new ArrayList<List<Integer>>();public List<List<Integer>> permute(int[] nums) {n = nums.length;used = new boolean[n];dfs(nums);return res;}public void dfs(int[] nums){if(ans.size() == n){res.add(new ArrayList(ans));return;}for(int i = 0; i < n; ++ i){if(used[i] == false){ans.add(nums[i]);used[i] = true;dfs(nums);used[i] = false;ans.removeLast();}}}
}

47.全排列II

有重复元素的全排列

求全排列的方法加上去重算法

由于顺序无所谓,所以可以先排序,

对于同一层的搜索:让上一次搜索的元素与下一次搜索的元素不同

记录上一次用到的元素,判断当前元素是否与前一个元素相同

class Solution {boolean[] used;int n;List<Integer> ans = new ArrayList<>();List<List<Integer>> res = new ArrayList<List<Integer>>();public List<List<Integer>> permuteUnique(int[] nums) {n = nums.length;used = new boolean[n];Arrays.sort(nums);dfs(nums);return res;}public void dfs(int[] nums){if(ans.size() == n){res.add(new ArrayList(ans));return;}int pre = 100;for(int i = 0; i < n; ++ i){if(used[i] == false && nums[i] != pre){ans.add(nums[i]);used[i] = true;pre = nums[i];dfs(nums);used[i] = false;ans.removeLast();}}}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/825194.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Unity类银河恶魔城学习记录13-1 p142 Save system源代码

Alex教程每一P的教程原代码加上我自己的理解初步理解写的注释&#xff0c;可供学习Alex教程的人参考 此代码仅为较上一P有所改变的代码 【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili FileDataHandler.cs using System; using System.IO; using UnityEngine; p…

数据结构学习记录

数据结构 数组 & 链表 相连性 | 指向性 数组可以迅速定位到数组中某一个节点的位置 链表则需要通过前一个元素指向下一个元素&#xff0c;需要前后依赖顺序查找&#xff0c;效率较低 实现链表 // head > node1 > node2 > ... > nullclass Node {constructo…

基于springboot+vue+Mysql的社区维修平台

开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;…

软件产品许可证书 Licence 全流程研发(使用非对称加密技术,既安全又简单)

本篇博客对应的代码地址&#xff1a; Gitee 仓库地址&#xff1a;https://gitee.com/biandanLoveyou/licence 源代码百度网盘链接: https://pan.baidu.com/s/1_ZhdcENcrk2ZuL11hWDLTQ?pwdbmxi 提取码: bmxi 1、背景介绍 公司是做软件 SAAS 服务的&#xff0c;一般来说软件部…

RabbitMQ项目实战(一)

文章目录 RabbitMQ项目实战选择客户端基础实战 前情提要&#xff1a;我们了解了消息队列&#xff0c;RabbitMQ的入门&#xff0c;交换机&#xff0c;以及核心特性等知识&#xff0c;现在终于来到了激动人心的项目实战环节&#xff01;本小节主要介绍通过Spring Boot RabbitMQ S…

2021年全国大学生电子设计竞赛D题——基于互联网的摄像测量系统(三)

13 测试方案和测量结果 测量一个边长为1米的正方形&#xff0c;取三个顶点分别作为O、A、B点。 在O点上方&#xff0c;用细线悬挂激光笔&#xff0c;激光笔常亮向下指示&#xff0c;静止时激光笔的光点和O点重合。 将两个D8M摄像头子卡插到DE10-Nano开发板上&#xff0c;放…

MySQL Linux环境安装部署

目录 1、mysql安装包下载 2、安装mysql服务 3、启动mysql服务 4、登录mysql服务 1、mysql安装包下载 1、查看centos的版本 cat /etc/redhat-release 2、进入官网地址下载对应系统版本的安装包 地址&#xff1a;MySQL :: Download MySQL Yum Repository 2、安装mysql服务 …

恒峰智慧科技-森林消防便捷泵:轻松应对火灾危机!

在广袤无垠的森林中&#xff0c;绿色是生命的象征&#xff0c;是自然的馈赠。然而&#xff0c;当火魔无情地吞噬这片生命的绿洲时&#xff0c;我们需要一种快速、高效、可靠的消防工具来守护这片绿色。此时&#xff0c;森林消防便捷泵应运而生&#xff0c;成为了守护森林安全的…

Oracle数据库 :查询表结构脚本

查询脚本 &#xff1a; SELECT CASE WHEN a.column_id1 THEN a.TABLE_NAME ELSE END AS 表名, a.column_id AS 序号, a.column_name as 列名, REPLACE(comments, CHR(10), ) as 列说明, a.data_type || ( || a.data_length || ) as 数据类型, a.DATA_LENGTH AS 长度, a.DATA_…

idea中停止运行Vue

在里面敲入Ctrlc 输入y确定即可。

【微服务-Ribbon】什么是负载均衡?微服务中负载均衡有哪些策略呢?

前面几篇文章&#xff0c;我们了解了一下Nacos的单机部署、集群部署以及微服务接入Nacos的步骤。从本篇开始&#xff0c;我们来看一下微服务第二个通用组件-负载均衡&#xff08;Ribbon&#xff09;。 1、Ribbon负载均衡器 负载均衡顾名思义&#xff0c;是指通过软件或者硬件…

电能质量分析仪是什么

TH-6500电能质量分析仪是一种用于记录和分析现场电能质量参数的设备。它能够检测并记录电力系统的电压波动、频率偏差、谐波、三相不平衡等参数&#xff0c;帮助用户了解电力系统的运行状态&#xff0c;及时发现并解决潜在的电能质量问题。 该设备具备多种测量功能&#xff0c…

嵌入式工程师有哪些必备技能,和电子爱好者有很大区别!

要掌握的技能实际上是非常多的。在这里&#xff0c;我来结合自己亲身经历&#xff0c;从技术、思维、项目管理等方面来谈一下我认为嵌入式开发需要掌握的技能。 技术方面 C语言和汇编语言能力 C语言是嵌入式开发最核心的编程语言。在我的初学阶段&#xff0c;我花费了很多时间…

生成人工智能体:人类行为的交互式模拟论文与源码架构解析(4)——架构分析 - 核心操作提示词构造

4.4.4.核心操作与提示词构造 &#xff08;1&#xff09;感知 0.根据vision_r参数&#xff0c;获取NPC周边(2*vision_r 1) **2个tile 1.将这些空间信息存储在NPC的空间记忆字典树 2.基于0的范围&#xff0c;获取当前NPC所在arena的所有事件&#xff0c;计算事件源距离NPC的…

我用AI帮我画刘亦菲写真,绘画写真某一天是否可以取代照相馆?

我用AI帮我画刘亦菲写真&#xff0c;绘画写真某一天是否可以取代照相馆&#xff1f; 最近我试了用FaceChain人物写真生成来测试帮我绘图&#xff0c;为了不翻车&#xff0c;我在网上随便找了刘亦菲的日常照片10多张左右作为训练原图。 真随便找的 生成效果有多种选择 下面…

【问题处理】银河麒麟操作系统实例分享,服务器操作系统VNC远程问题分析

1.服务器环境以及配置 【内核版本】 4.19.90-23.8.v2101.ky10.aarch64 【OS镜像版本】 0518-server 2.问题现象描述 服务器通过vncserver:1.service服务启动的vnc服务后&#xff0c;普通用户用vnc连接时&#xff0c;锁屏后&#xff0c;然后输入登陆密码会报密码错误&…

备考2024年小学生古诗文大会:吃透历年真题和知识点(持续讲题)

对上海小学生的小升初和各种评优争章来说&#xff0c;语文、数学、英语的含金量较高的证书还是很有价值和帮助的。对于语文类的竞赛&#xff0c;小学生古诗文大会和汉字小达人通常是必不可少的&#xff0c;因为这两个针对性强&#xff0c;而且具有很强的上海本地特色。 根据往…

【nnUNetv2进阶】六、nnUNetv2 魔改网络-小试牛刀-加入注意力机制CBAM

nnUNet是一个自适应的深度学习框架&#xff0c;专为医学图像分割任务设计。以下是关于nnUNet的详细解释和特点&#xff1a; 自适应框架&#xff1a;nnUNet能够根据具体的医学图像分割任务自动调整模型结构、训练参数等&#xff0c;从而避免了繁琐的手工调参过程。 自动化流程&a…

Shopee虾皮批量上传全球产品指南

当shopee虾皮需要大量上架新产品时&#xff0c;批量工具可以更好的提升效率。通过本指南&#xff0c;你将了解如何批量上传全球商品&#xff0c;本指南适用于所有站点。 一、什么是批量上传&#xff1f; 您可以通过【中国卖家中心>>全球商品>>批量上传】功能&…

一文教您理解Playwright是如何实现动态等待的

使用过Playwright的同学都会有这样的感受&#xff0c;Playwright对UI页面中元素的识别非常稳定&#xff0c;这离不开其强大的动态等待机制&#xff01;简单的解释就是&#xff0c;Playwright在对UI页面中的任何元素操作之前&#xff0c;都需要做出一些列的校验工作来确保能够稳…