算法通关村第18关【白银】| 回溯热门问题

news2025/1/10 3:00:58

1.组合总和问题

思路:回溯模板

(1)确定方法返回值和参数

分析可知遍历数组然后求和值,不需要返回什么值

参数也就是candidates,list,path,target,start

(2)确定回溯终止条件

当满足求和的时候终结

(3)确定单层逻辑

判断当前是否满足条件是就添加进条件,然后返回

不是就继续向下递归,这里需要注意从i开始,也就是可以取自己

当递归返回的时候需要进行回溯,也就是弹出上一个已经使用过的值

class Solution {
    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        List<List<Integer>> list = new ArrayList<List<Integer>>();
        List<Integer> path = new ArrayList<Integer>();
        trace(list,path,candidates,target,0);
        return list;

    }
    public void trace(List list,List path,int[] candidates,int target,int start){ 
        if(target<0){
            return;
        }
        if(target == 0){
            list.add(new ArrayList<>(path));
            return;
        }
        for(int i = start;i<candidates.length;i++){
            path.add(candidates[i]);
            trace(list,path,candidates,target - candidates[i],i);
            path.remove(path.size()-1);
        }
    }
}

2.分割回文串

思路: 

(1)确定方法返回值和参数

分析可知遍历字符串进行分割,不需要返回什么值

参数也就是s,list,path,start

(2)确定回溯终止条件

当遍历完字符串就结束一次递归

(3)确定单层逻辑

判断当前分割方案是否是回文串不是继续往后纳入字母

是就继续向下递归,这里需要注意从i+1开始,也就是不可以取自己

当递归返回的时候需要进行回溯,也就是弹出上一个已经使用过的方案

class Solution {
    public List<List<String>> partition(String s) {
        List<List<String>> list = new ArrayList<List<String>>();
        List<String> path = new ArrayList<String>();
        trace(s,0,list,path);
        return list;

    }
    public boolean isPalindrom(String s,int l,int r){
        for(int i = l,j = r;i<j;i++,j--){
            if(s.charAt(i) != s.charAt(j)){
                return false;
            }
        }
        return true;
    }
    public void trace(String c,int start,List list,List path){
        if(start >= c.length()){
            list.add(new ArrayList<String>(path));
            return;
        }
        for(int i = start;i<c.length();i++){
            if(!isPalindrom(c,start,i)){
                continue;
            }
            String str = c.substring(start,i + 1);
            path.add(str);
            trace(c,i+1,list,path);
            path.remove(path.size()-1);
        }

    }
}

3.子集问题

 思路:子集问题不需要剪枝,遍历全部并且每次都加添加进结果集

(1)确定方法返回值和参数

分析可知遍历数组,不需要返回什么值

参数也就是nums,list,path,start

(2)确定回溯终止条件

当遍历完数组就结束一次递归

(3)确定单层逻辑

将当前数字添加进path,继续向下递归,这里需要注意从i+1开始,也就是不可以取自己

当递归返回的时候需要进行回溯,也就是弹出上一个已经使用过的数字

class Solution {
    public List<List<Integer>> subsets(int[] nums) {
         List<List<Integer>> list = new ArrayList<List<Integer>>();
         List<Integer> path = new ArrayList<Integer>();
         trace(list,path,nums,0);
         return list;
    }

    public void trace(List list,List path,int[] nums,int start){
        if(start > nums.length){
            return;
        }
        list.add(new ArrayList<>(path));
        for(int i = start;i<nums.length;i++){
            path.add(nums[i]);
            trace(list,path,nums,i+1);
            path.remove(path.size()-1);
        }
    }
}

4.排列问题

思路:

(1)确定方法返回值和参数

分析可知遍历数组,不需要返回什么值

参数也就是nums,list,path

(2)确定回溯终止条件

当遍历完数组就结束一次递归

(3)确定单层逻辑

注意这里的for循环从0开始,代表可以重复取。

判断当前数字是否已经在path里面了,是的话就跳过当前数字

否则将当前数字添加进path,继续向下递归,这里需要注意从i+1开始,也就是不可以取自己

当递归返回的时候需要进行回溯,也就是弹出上一个已经使用过的数字

class Solution {
    boolean[] used;
    public List<List<Integer>> permute(int[] nums) {
        List<List<Integer>> list = new ArrayList<List<Integer>>();
        List<Integer> path = new ArrayList<Integer>();
        used = new boolean[nums.length];
        trace(list,path,nums);
        return list;
    }

    public void trace(List list,List path,int[] nums){
        if(path.size()==nums.length){
            list.add(new ArrayList<Integer>(path));
            return;
        }
        for(int i = 0;i<nums.length;i++){
            if(used[i]){
                continue;
            }
            path.add(nums[i]);
            used[i] = true;
            trace(list,path,nums,i+1);
            path.remove(path.size()-1);
            used[i] = false;
        }
    }
}

5.字母大小写全排列

思路:回溯模板

深度:s.length()-数字

宽度:2(小写、大写)

跳过数字,将字母大小写转换,然后进行递归,触底加入结果集。

返回进行回溯,转换大小写,继续递归。

class Solution {
    public List<String> letterCasePermutation(String s) {
         List<String> list = new ArrayList<>();
         trace(list,s.toCharArray(),0);
         return list;
    }

    public void trace(List list,char[] s,int start){
        while(start<s.length&&Character.isDigit(s[start])){
            start++;
        }
        if(start == s.length){
            list.add(new String(s));
            return;
        }
        s[start] ^= 32;
        trace(list,s,start+1);
        s[start] ^=32;
        trace(list,s,start+1);
    }
}

6.单词搜索

思路:

(1)确定方法返回值和参数

分析可知遍需要返回boolean,参数自然需要board、i、j、word、len、cur

(2)确定回溯终止条件

当碰到不符合的字母就返回false代表这一条支路不行,word长度和递归深度一致时代表这条支路可以返回true

(3)确定单层逻辑

从当前的i,j出发,上下左右四个方向可以选择,只要是没用访问过的点和边界内的就进行递归,并且标记当前的点为已使用,补上参数visited

当递归返回的时候需要进行回溯,也就是清除已使用的标记

class Solution {
    public boolean exist(char[][] board, String word) {
        int h = board.length, w = board[0].length;
        boolean[][] visited = new boolean[h][w];
        char[] s = word.toCharArray();
        for (int i = 0; i < h; i++) {
            for (int j = 0; j < w; j++) {
                boolean flag = trace(board,visited,i,j,word.length(),1,s);
                if(flag){
                    return true;
                }
            }
        }
        return false;
    }
    public boolean trace(char[][] board,boolean[][] visited,int i,int j,int len,int cur,char[] word){
        if (board[i][j] != word[cur-1]) {
            return false;
        } 
        if(len == cur){
            return true;
        }
        visited[i][j] = true;
        boolean a=false,b=false,c=false,d=false;
        if(i+1<board.length&&visited[i+1][j]==false) {
             a = trace(board,visited,i+1,j,len,cur+1,word);
        }
           
        if(i-1>=0&&visited[i-1][j]==false){
            b = trace(board,visited,i-1,j,len,cur+1,word);
        } 
            
        if(j+1<board[0].length&&visited[i][j+1]==false) {
            c = trace(board,visited,i,j+1,len,cur+1,word);
        }
        if(j-1>=0&&visited[i][j-1]==false) {
            d = trace(board,visited,i,j-1,len,cur+1,word);
        }
         visited[i][j] = false;
        return a|b|c|d;
    }
}

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

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

相关文章

【2023研电赛】基于三维视觉感知的可重构智能表面通信方案

该作品参与极术社区组织的研电赛作品征集活动&#xff0c;欢迎同学们投稿&#xff0c;获取作品传播推广&#xff0c;并有丰富礼品哦~ 基于三维视觉感知的可重构智能表面通信方案 参赛单位&#xff1a;华北水利水电大学 参赛队伍&#xff1a;智能队 指导老师&#xff1a;邵霞 参…

服务器中了locked勒索病毒怎么办,勒索病毒解密,数据恢复

最近一段时间内&#xff0c;相信很多使用金蝶或用友的办公软件的企业&#xff0c;有很多都经历了locked勒索病毒的攻击&#xff0c;导致企业服务器被加密无法正常使用&#xff0c;严重影响了企业的正常工作。通过云天数据恢复中心的解密恢复发现&#xff0c;在今年locked勒索病…

【LeetCode(数据结构与算法)】:反转链表

给你单链表的头节点 head &#xff0c;请你反转链表&#xff0c;并返回反转后的链表 输入&#xff1a;head [1,2,3,4,5] 输出&#xff1a;[5,4,3,2,1] 输入&#xff1a;head [1,2] 输出&#xff1a;[2,1] 示例 3&#xff1a; 输入&#xff1a;head [] 输出&#xff1a;[] …

Linux下按键驱动实验

按键驱动和LED驱动原理上来讲基本都是一样的&#xff0c;都是操作GPIO&#xff0c;只不过一个是读取GPIO的高低电平&#xff0c;一个是从GPIO输出高低电平给LED。 本实验使用的开发板是IMX6DL&#xff0c;实验中使用的按键是通过使用下图中P1的EIM_A20和VCC3.3V两个引脚实现的&…

如何选择超声波清洗机、超声波清洗机排行榜

眼镜的日常清洗生活中很多人都会把它给忘记&#xff01;长时间下来眼镜支架就会变成黄色的&#xff0c;非常的难洗掉&#xff0c;从而又浪费了一个眼镜。一副好的眼镜也不便宜的&#xff0c;把换眼镜的钱省下来入一款超声波清洗机&#xff0c;可以大大的减少金钱的支持&#xf…

java基于springboot+vue的厨房预订预约管理系统

历经长达几个月的毕业作品制作&#xff0c;我凭借自己的知识技能&#xff0c;还有大家的指导帮助&#xff0c;能够在学校规定的时间段之内提交毕业作品。虽然已经算是完成了毕业作品&#xff0c;但是付出了这么多心血&#xff0c;还是想把这个作品做得更加完美一点。针对我的毕…

如何通过内网穿透实现远程连接NAS群晖drive并挂载电脑硬盘?

文章目录 前言1.群晖Synology Drive套件的安装1.1 安装Synology Drive套件1.2 设置Synology Drive套件1.3 局域网内电脑测试和使用 2.使用cpolar远程访问内网Synology Drive2.1 Cpolar云端设置2.2 Cpolar本地设置2.3 测试和使用 3. 结语 前言 群晖作为专业的数据存储中心&…

hash join的基本原理是怎样的?

我们知道数据库里面两表关联主要有三种常见的关联方式&#xff0c;即 nested loop joinhash joinmerge join nested loop join在OLTP交易场景占比是最多的&#xff0c;常用于关联字段为主键或索引字段的情况&#xff0c;通过主键或索引以及loop的方式&#xff0c;A表可以快速…

BricsCAD 23 for Mac:轻松驾驭CAD建模的强大工具

如果你正在寻找一款功能强大、操作简便的CAD建模软件&#xff0c;那么BricsCAD 23 for Mac绝对值得你考虑。这款软件将为你提供一套完整的2D和3D设计解决方案&#xff0c;让你在Mac上轻松创建、编辑和修改图形。 一、BricsCAD 23的功能特点 高效的2D和3D建模&#xff1a;Bric…

2652. 倍数求和

2652. 倍数求和 题目方法-【枚举】 & 题目特征-【求计算在给定范围内满足某种条件的整数之和】方法-【容斥原理】 & 题目特征-【计算满足多个条件的元素之和&#xff0c;并且需要避免重复计数】 题目 题目链接&#xff1a;https://leetcode.cn/problems/sum-multiples…

倾斜摄影三维模型的根节点合并的重要性分析

倾斜摄影三维模型的根节点合并的重要性分析 倾斜摄影三维模型的根节点合并是整个模型构建过程中的一个重要环节&#xff0c;具有重要的意义和作用。本文将对倾斜摄影三维模型的根节点合并的重要性进行详细分析。 一、定义和概述 在倾斜摄影三维模型的构建过程中&#xff0c;根…

概率神经网络分类问题程序

欢迎关注“电击小子程高兴的MATLAB小屋” %% 概率神经网络 %% 解决分类问题 clear all; close all; P[1:8]; Tc[2 3 1 2 3 2 1 1]; Tind2vec(Tc) %数据类型的转换 netnewpnn(P,T); Ysim(net,P); Ycvec2ind(Y) %转换回来

一文带你认识高速低侧栅极驱动器 FAN3111ESX 带你深入了解其特点及应用

FAN3111ESX一款低端驱动器产品&#xff0c;是外部 DC 2 至 5 V 参考输入、单通道同相输出、1.4 A 峰值灌电流、1.4 A 源电流低端栅极驱动器。 FAN3111ESX 1A栅极驱动器为驱动一个在低侧开关应用中的 N沟道增强型 MOSFET 而设计。 对于使用低压控制器和其它和驱动器相比使用更…

二维码智慧门牌管理系统:地址管理的现代革命

文章目录 前言一、标准地址的革新二、广泛的应用前景 前言 在科技不断发展和社会进步的背景下&#xff0c;高效、精准、智能的管理系统已经成为当今社会的迫切需求。传统的门牌管理系统在应对这一需求方面已显得力不从心&#xff0c;因此&#xff0c;二维码智慧门牌管理系统的…

力扣每日一题43:字符串相乘

题目描述&#xff1a; 给定两个以字符串形式表示的非负整数 num1 和 num2&#xff0c;返回 num1 和 num2 的乘积&#xff0c;它们的乘积也表示为字符串形式。 注意&#xff1a;不能使用任何内置的 BigInteger 库或直接将输入转换为整数。 示例 1: 输入: num1 "2"…

强化学习基础(1)- 理论和算法

目录 1.基本概念 1.1组成部分 1.2 马尔可夫决策过程 2 有模型强化学习 2.1状态值函数 2.2动作值函数 2.3二者关系 2.4 探索和利用 2.5动态规划&#xff08;DP&#xff09;&#xff08;有模型求解方法&#xff09; 2.5.1预测任务 2.5.1控制任务 3.无模型强化学习 3.1 Valu…

AI全栈大模型工程师(四)OpenAI API初探

五、它是怎么生成结果的? 其实,它只是根据上文,猜下一个词(的概率)…… OpenAI 的接口名就叫「completion」,也证明了其只会「生成」的本质。 下面用程序演示「生成下一个字」。你可以自己修改 prompt 试试。还可以使用相同的 prompt 运行多次。 import openai import…

哪个牌子的电容笔好用?ipad触控笔推荐平价

有哪些电容笔适合学生党入手&#xff1f;苹果Pencil虽然与普通的电容笔&#xff0c;不同的是&#xff0c;这款电容笔同时具有重力传感器和倾斜传感器&#xff0c;而平替电容笔&#xff0c;只有一种倾斜传感器&#xff0c;但在书写方面的体验很不错&#xff0c;可以用来写字&…

JAMA | 多中心临床试验也用RCS方法分析,卒中患者强化血压管理更有利用康复

郑老师统计课程&#xff0c;欢迎点击报名&#xff1a;临床设计与数据分析 课程 2023年9月&#xff0c;外国学者在《JAMA》&#xff08;一区&#xff0c;IF120.7&#xff09;发表题为&#xff1a;" Intensive vs Conventional Blood Pressure Lowering After Endovascular …

MySQL初级之战

华子目录 什么是数据库&#xff1f;数据库管理系统&#xff08;DBMS&#xff09;数据库系统与文件系统的区别数据库的发展史常见数据库关系性数据库关系型数据库的4大特性关系型数据库的优缺点非关系型数据库非关系数据库的优点和缺点 DBMS支持的数据模型MySQL体系架构连接层SQ…