一个月速刷leetcodeHOT100 day15 彻底搞懂回溯算法 以及相关题目

回溯算法采用试错的思想,它尝试分步的去解决一个问题。在分步解决问题的过程中,当它通过尝试发现现有的分步答案不能得到有效的正确的解答的时候,它将取消上一步甚至是上几步的计算,再通过其它的可能的分步解答再次尝试寻找问题的答案

全排列

给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。

示例 1:

**输入:**nums = [1,2,3]
输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]

示例 2:

**输入:**nums = [0,1]
输出:[[0,1],[1,0]]

示例 3:

**输入:**nums = [1]
输出:[[1]]

const permute = (nums) => {
// 1. 设置结果集

const result = [];

// 2. 回溯

const recursion = (path, set) => {

// 2.1 设置回溯终止条件

if (path.length === nums.length) {

// 2.1.1 推入结果集

result.push(path.concat());

// 2.1.2 终止递归

return;

}

// 2.2 遍历数组

for (let i = 0; i < nums.length; i++) {

// 2.2.1 必须是不存在 set 中的坐标

if (!set.has(i)) {

// 2.2.2 本地递归条件(用完记得删除)

path.push(nums[i]);

set.add(i);

// 2.2.3 进一步递归

recursion(path, set);

// 2.2.4 回溯:撤回 2.2.2 的操作

path.pop();

set.delete(i);

}

}

};

recursion([], new Set());

// 3. 返回结果

return result;

};

子集

给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的
子集
(幂集)。
解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。
示例 1:
**输入:**nums = [1,2,3]
输出:[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]

示例 2:

**输入:**nums = [0]
输出:[[],[0]]

var letterCombinations = (digits) => {

if (digits.length == 0) return [];

const res = [];

const map = {//建立电话号码和字母的映射关系

2: "abc",

3: "def",

4: "ghi",

5: "jkl",

6: "mno",

7: "pqrs",

8: "tuv",

9: "wxyz",

};

  

const dfs = (curStr, i) => {//curStr是递归每一层的字符串,i是扫描的指针

if (i > digits.length - 1) {//边界条件,递归的出口

res.push(curStr); //其中一个分支的解推入res

return; //结束递归分支,进入另一个分支

}

const letters = map[digits[i]]; //取出数字对应的字母

for (const l of letters) {

//进入不同字母的分支

dfs(curStr + l, i + 1); //参数传入新的字符串,i右移,继续递归

}

};

dfs("", 0); // 递归入口,传入空字符串,i初始为0的位置

return res;

};

数组总和

给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target ,找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 ,并以列表形式返回。你可以按 任意顺序 返回这些组合。

candidates 中的 同一个 数字可以 无限制重复被选取 。如果至少一个数字的被选数量不同,则两种组合是不同的。

对于给定的输入,保证和为 target 的不同组合数少于 150 个。

示例 1:

**输入:**candidates = [2,3,6,7], target = 7
输出:[[2,2,3],[7]]
解释:
2 和 3 可以形成一组候选,2 + 2 + 3 = 7 。注意 2 可以使用多次。
7 也是一个候选, 7 = 7 。
仅有这两种组合。

示例 2:

输入: candidates = [2,3,5], target = 8
输出: [[2,2,2,2],[2,3,3],[3,5]]

示例 3:

输入: candidates = [2], target = 1
输出: []

var combinationSum = function(candidates, target) {

// 先队候选数字排序

candidates = candidates.sort((a,b)=>a-b);

const result = []; // 存储最后返回的结果

const path = []; // 路径

// sum 为当前路径上的所有元素之和

function backTrack(startIndex,sum) {

// 判断 和 是否与target相等

if( sum === target) {

result.push([...path]);

}

for(let i = startIndex; i < candidates.length; i++){

// 剪枝

if(candidates[i]+sum > target) return;

path.push(candidates[i]);

// candidates[i]表示候选数组中第i个元素的值

backTrack(i, sum + candidates[i]);

path.pop();

}

}

backTrack(0 , 0);

return result;

};

括号生成

数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。

示例 1:

**输入:**n = 3
输出:[“((()))”,“(()())”,“(())()”,“()(())”,“()()()”]

示例 2:

**输入:**n = 1
输出:[“()”]

var generateParenthesis = function(n) {

const res = []; // 输出的结果数组

const generate = (str, left, right) => {

if (str.length == 2 * n) { // 字符串构建完成

res.push(str); // 将字符串加入res

return; // 结束当前递归(结束当前搜索分支)

}

if (left > 0) { // 只要左括号有剩,可以选它,继续递归做选择

generate(str + '(', left - 1, right);

}

if (right > left) { // 右括号的保有数量大于左括号的保有数量,才能选右括号

generate(str + ')', left, right - 1);

}

};
  
generate('', n, n); // 递归的入口,初始字符串是空字符串,初始括号数量都是n

return res;


};

单词搜索

给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false 。

单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。

示例 1:

**输入:**board = [[“A”,“B”,“C”,“E”],[“S”,“F”,“C”,“S”],[“A”,“D”,“E”,“E”]], word = “ABCCED”
**输出:**true

示例 2:

**输入:**board = [[“A”,“B”,“C”,“E”],[“S”,“F”,“C”,“S”],[“A”,“D”,“E”,“E”]], word = “SEE”
**输出:**true

示例 3:

**输入:**board = [[“A”,“B”,“C”,“E”],[“S”,“F”,“C”,“S”],[“A”,“D”,“E”,“E”]], word = “ABCB”
**输出:**false

var exist = function (board, word) {

let m = board.length;

let n = board[0].length;

//越界处理

// board[-1] = []; // 这里处理比较比较巧妙,利用了js的特性

// board.push([]);

  

//寻找首个字母

for (let x = 0; x < m; x++) {

for (let y = 0; y < n; y++) {

if (word[0] === board[x][y]) {

if (dfs(word, board, x, y, 0)) {

return true;

}

}

}

}

return false;

};

let dfs = function (word, board, x, y, index) {

let m = board.length;

let n = board[0].length;

if (index + 1 === word.length) return true;

  

var tmp = board[x][y];

// 标记该元素已使用

board[x][y] = false

if (y+1 < n && board[x][y + 1] === word[index + 1] && dfs(word, board, x, y + 1, index + 1)) return true;

if (y - 1 >= 0 && board[x][y - 1] === word[index + 1] && dfs(word, board, x, y - 1, index + 1)) return true;

if (x + 1 < m && board[x + 1][y] === word[index + 1] && dfs(word, board, x + 1, y, index + 1)) return true;

if (x - 1 >= 0 && board[x - 1][y] === word[index + 1] && dfs(word, board, x - 1, y, index + 1)) return true;

// 回溯

board[x][y] = tmp;

}

分割回文串

给你一个字符串 s,请你将 s 分割成一些子串,使每个子串都是

回文串

。返回 s 所有可能的分割方案。

示例 1:

**输入:**s = “aab”
输出:[[“a”,“a”,“b”],[“aa”,“b”]]

示例 2:

**输入:**s = “a”
输出:[[“a”]]

var partition = function(s) {
    //判断回文
    const isPal = function(s, l ,r) {
        while(l < r) {
            if(s[l] !== s[r]) {
                return false;
            }
            l++;
            r--;
        }
        return true;
    }
    let res = [];
    let path = [];
    const bt = function(startIndex) {
        //如果已经切割到最后就结束
        if(startIndex === s.length) {
            res.push([...path]);
            return;
        } 
        for(let i = startIndex; i < s.length; i++) {
            // 是回文子串
            if(isPal(s, startIndex, i)) {
                path.push(s.slice(startIndex, i + 1));  //slice是右开,所以得加1
                bt(i + 1);  
                path.pop(); //回溯
            } else {
                continue;
            }
        }
    }
    bt(0);
    return res;
};

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

JavaSE 实战五子棋中国象棋(单机简易版)

介绍 JavaSE实践五子棋和中国象棋游戏&#xff0c;棋盘&#xff0c;棋子绘制&#xff0c;输赢判定重置棋盘&#xff0c;单机博弈。 五子棋棋盘 中国象棋棋盘 使用说明 启动类 Main.java&#xff0c; 面板类 Panel.java绘制棋盘和玩法&#xff0c;实体类 ChessPiecesNode.jav…

工具-金舟投屏软件: 手机如何投屏到电脑上 / Wi-Fi / USB

金舟安卓/iOS苹果投屏-正版软件下载中心 方法一、金舟投屏软件-wifi 1.1、准备工作 确保苹果手机和Windows电脑都连接到同一个Wi-Fi网络。 在Windows电脑上安装并打开金舟投屏软件。 1.2、操作步骤 在金舟投屏软件上选择“苹果手机投屏”功能。 在苹果手机上下滑屏幕&am…

动手学深度学习29 残差网络ResNet

动手学深度学习29 残差网络ResNet ResNet代码ReLU的两种调用1. 使用 torch.nn.ReLU 模块2. 使用 torch.nn.functional.relu 函数总结 QA29.2 ResNet 为什么能训练处1000层的模型ResNet的梯度计算怎么处理梯度消失的 QA ResNet 更复杂模型包含小模型&#xff0c;不一定改进&…

公司刚来的00后真卷,上班还没2年,跳到我们公司起薪20k。。。

前言 现在都说要躺平了&#xff0c;但该说不说的&#xff0c;一样都在卷&#xff0c;你信了就输了。 前段时间我们公司来了个卷王&#xff0c;工作2年左右吧&#xff0c;跳槽到我们公司起薪20K&#xff0c;真的比我还牛。后来才知道人家是真的卷啊&#xff01;都不当人了&…

初识C++ · 模板进阶

目录 前言&#xff1a; 1 非类型模板参数 2 按需实例化 3 模板特化 4 模板的分离编译 前言&#xff1a; 前面模板我们会了简单的使用&#xff0c;这里带来模板的进阶&#xff0c;当然&#xff0c;也就那么几个知识点&#xff0c;并不太难。 1 非类型模板参数 先来看这样…

【Framework系列】Excel转Json,配置表、导表工具介绍

今天来介绍一下Framework系列的配置部分&#xff0c;这一部分归属于Framework-Design之中。读过《Framework系列介绍》的小伙伴应该了解整个Framework框架是由多个工程项目组成&#xff0c;没看过的小伙伴可以点击链接了解一下。 Framework-Design设计的初衷是给策划同学用的&a…

谁懂啊!第一次用AI绘画做表情包,居然直接爆收入了!

大家好&#xff0c;我是设计师阿威 我的第一套表情包上周六上午11点终于在微信的表情商店上架啦&#xff01; 为什么说“终于”&#xff1f; 那是因为背后是无数次的努力–>被退回–>反复修改–>再提交–>再被退回–>再精心修改–>终于通过啦&#xff01;…

Python实现调用并执行Linux系统命令

&#x1f60e; 作者介绍&#xff1a;我是程序员洲洲&#xff0c;一个热爱写作的非著名程序员。CSDN全栈优质领域创作者、华为云博客社区云享专家、阿里云博客社区专家博主。 &#x1f913; 同时欢迎大家关注其他专栏&#xff0c;我将分享Web前后端开发、人工智能、机器学习、深…

Pyramid Vision Transformer, PVT(ICCV 2021)原理与代码解读

paper&#xff1a;Pyramid Vision Transformer: A Versatile Backbone for Dense Prediction without Convolutions official implementation&#xff1a;GitHub - whai362/PVT: Official implementation of PVT series 存在的问题 现有的 Vision Transformer (ViT) 主要设计…

豆包引领AI大模型PC端新潮流,预示行业薪资待遇与就业前景的广阔前景

前言 在AI大模型技术迅速发展的浪潮中&#xff0c;豆包AI助手凭借其独特的PC端布局&#xff0c;成为了行业的先行者。这一举措不仅体现了对市场需求和用户习惯的深度洞察&#xff0c;更预示着AI大模型领域薪资待遇和就业前景的广阔空间。 豆包AI助手通过推出PC客户端&#x…

tomcat-valve通过servlet处理请求

上一节说到请求url定位servlet的过程&#xff0c;tomcat会把请求url和容器的映射关系保存到MappingData中&#xff0c;org.apache.catalina.connector.Request类实现了HttpServletRequest&#xff0c;其中定义了属性mappingDataprotected final MappingData mappingData new M…

国产Sora免费体验-快手旗下可灵大模型发布

自从OpenAI公布了Sora后&#xff0c;震爆了全世界&#xff0c;但由于其技术的不成熟和应用的局限性&#xff0c;未能大规模推广&#xff0c;只有零零散散的几个公布出来的一些视频。昨日&#xff0c;快手成立13周年&#xff0c;可灵&#xff08;Kling&#xff09;大模型发布&am…

【vue3|第7期】 toRefs 与 toRef 的深入剖析

日期&#xff1a;2024年6月6日 作者&#xff1a;Commas 签名&#xff1a;(ง •_•)ง 积跬步以致千里,积小流以成江海…… 注释&#xff1a;如果您觉得有所帮助&#xff0c;帮忙点个赞&#xff0c;也可以关注我&#xff0c;我们一起成长&#xff1b;如果有不对的地方&#xff…

vs2017中C2440错误:“初始化”:无法从const char[6]转换为char*问题解决

本文摘要&#xff1a;本文已解决 Python FileNotFoundError 的相关报错问题&#xff0c;并总结提出了几种可用解决方案。同时结合人工智能GPT排除可能得隐患及错误。 &#x1f60e; 作者介绍&#xff1a;我是程序员洲洲&#xff0c;一个热爱写作的非著名程序员。CSDN全栈优质领…

LLM系列: LLama2

推理流程 从输入文本&#xff0c;到推理输出文本&#xff0c;LLama2模型处理流程如下&#xff1a; step1 Tokenization 输入数据&#xff1a;一个句子或一段话。通常表示成单词或字符序列。 Tokenization即对文本按单词或字符序列切分&#xff0c;形成Token序列。Token序列再…

【Vue2源码学习分析】

# 文件结构 源码目录 # 调试环境搭建 安装依赖: npm i安装rollup: npm i -g rollup修改dev脚本&#xff0c;添加sourcemap&#xff0c;package.json "dev": "rollup -w -c scripts/config.js --sourcemap --environment TARGET:web- full-dev",运行开发命令…

LabVIEW阀性能试验台测控系统

本项目开发的阀性能试验台测控系统是为满足国家和企业相关标准而设计的&#xff0c;主要用于汽车气压制动系统控制装置和调节装置等产品的综合性能测试。系统采用工控机控制&#xff0c;配置电器控制柜&#xff0c;实现运动控制、开关量控制及传感器信号采集&#xff0c;具备数…

后端进阶-分库分表

文章目录 为什么需要分库为什么需要分表 什么时候需要分库分表只需要分库只需要分表 分库分表解决方案垂直分库水平分库垂直分表水平分表 分库分表常用算法范围算法hash分片查表分片 分库分表模式客户端模式代理模式 今天跟着训练营学习了分库分表&#xff0c;整理了学习笔记。…

Spring系统学习 -Spring IOC 的XML管理Bean之bean的获取、依赖注入值的方式

在Spring框架中&#xff0c;XML配置是最传统和最常见的方式之一&#xff0c;用于管理Bean的创建、依赖注入和生命周期等。这个在Spring中我们使用算是常用的&#xff0c;我们需要根据Spring的基于XML管理Bean了解相关Spring中常用的获取bean的方式、依赖注入值的几种方式等等。…

C++ Thread多线程并发记录(8)生产者-消费者模型与信号量(条件变量)

一.生产者-消费者模型 生产者-消费者模型是一个十分经典的多线程并发协作模式。所谓的生产者-消费者&#xff0c;实际上包含了两类线程&#xff0c;一种是生产者线程用于生产数据&#xff0c;另一种是消费者线程用于消费数据&#xff0c;为了解耦生产者和消费者的关系&#xff…