代码随想录算法训练营第二十四天|● 理论基础 ● 77. 组合(JS写法)

news2024/11/18 7:27:31

回溯理论基础

在这里插入图片描述
回溯法解决的问题都可以抽象为树形结构,因为回溯法解决的都是在集合中递归查找子集,集合的大小就构成了树的宽度,递归的深度,都构成的树的深度。递归就要有终止条件,所以必然是一棵高度有限的树(N叉树)。

回溯三部曲

1、回溯函数模板返回值以及参数
在回溯算法中,我的习惯是函数起名字为backtracking,这个起名大家随意。回溯算法中函数返回值一般为void。
再来看一下参数,因为回溯算法需要的参数可不像二叉树递归的时候那么容易一次性确定下来,所以一般是先写逻辑,然后需要什么参数,就填什么参数。但后面的回溯题目的讲解中,为了方便大家理解,我在一开始就帮大家把参数确定下来。
回溯函数伪代码如下:

void backtracking(参数)

2、回溯函数终止条件
既然是树形结构,那么我们在讲解二叉树的递归 (opens new window)的时候,就知道遍历树形结构一定要有终止条件。所以回溯也有要终止条件。什么时候达到了终止条件,树中就可以看出,一般来说搜到叶子节点了,也就找到了满足条件的一条答案,把这个答案存放起来,并结束本层递归。所以回溯函数终止条件伪代码如下:

if (终止条件) {
    存放结果;
    return;
}

3、回溯搜索的遍历过程
在上面我们提到了,回溯法一般是在集合中递归搜索,集合的大小构成了树的宽度,递归的深度构成的树的深度。
如图:
在这里插入图片描述

回溯算法模板

void backtracking(参数) {
    if (终止条件) {
        存放结果;
        return;
    }

    for (选择:本层集合中元素(树中节点孩子的数量就是集合的大小)) {
        处理节点;
        backtracking(路径,选择列表); // 递归
        回溯,撤销处理结果
    }
}

77 组合

题目链接/文章讲解:https://programmercarl.com/0077.%E7%BB%84%E5%90%88.html
视频讲解:https://www.bilibili.com/video/BV1ti4y1L7cv
剪枝操作:https://www.bilibili.com/video/BV1wi4y157er
在这里插入图片描述

思路:将回溯问题理解成树,重点理解每次还要pop出来

理论上这道题如果k=2可以用两层for循环嵌套,但是如果k=50就要嵌套50层for循环,因此这时候就需要用到回溯了。(k不确定,可能很大也可能很小)
在这里插入图片描述

/**
 * @param {number} n
 * @param {number} k
 * @return {number[][]}
 */
var combine = function(n, k) {
    let result = [];
    let path = [];
    //确定回溯的参数
    const backTracking = (n,k,start) => {
    	//终止条件
        if(path.length === k){
            //[...path]
            result.push(path.slice());
            return;
        }
        //单层循环
        for(let i = start;i<=n;i++){
            path.push(i);
            backTracking(n,k,i+1);
            path.pop();
        }
    }
    backTracking(n,k,1);
    return result;

};

使用 result.push(path.slice()) 而不是 result.push(path) 的主要原因是,JavaScript 中的数组是引用类型,如果直接使用 result.push(path),会将 path 的引用放入 result 数组中。
由于 backtracking 过程中 path 数组不断变化(不断添加和移除元素),如果直接将 path 引用放入 result 数组中,由于 backtracking 过程中 path 数组会不断更改,最终 result 数组中的所有元素都会指向相同的 path 引用,导致 result 数组中的元素都是一样的,而不是不同的组合。
因此,为了确保在 result 数组中存储不同的组合,需要使用 path.slice() 来创建 path 的副本,将副本推入 result 数组中。这样每个组合都是不同的,不会相互影响。
所以,采用 result.push(path.slice()) 会确保在 result 数组中存储不同的组合,而不是相同的引用。

剪枝

在这里插入图片描述
图中每一个节点(图中为矩形),就代表本层的一个for循环,那么每一层的for循环从第二个数开始遍历的话,都没有意义,都是无效遍历。

所以,可以剪枝的地方就在递归中每一层的for循环所选择的起始位置。

如果for循环选择的起始位置之后的元素个数 已经不足 我们需要的元素个数了,那么就没有必要搜索了。

注意代码中i,就是for循环里选择的起始位置。

1、已经选择的元素个数:path.size();

2、还需要的元素个数为: k - path.size();

3、在集合n中至多要从该起始位置 : n - (k - path.size()) + 1,开始遍历

为什么有个+1呢,因为包括起始位置,我们要是一个左闭的集合。

举个例子,n = 4,k = 3, 目前已经选取的元素为0(path.size为0),n - (k - 0) + 1 即 4 - ( 3 - 0) + 1 = 2。

从2开始搜索都是合理的,可以是组合[2, 3, 4]。

因此,剪枝操作仅需要将i的范围更改即可。

/**
 * @param {number} n
 * @param {number} k
 * @return {number[][]}
 */
var combine = function(n, k) {
    let result = [];
    let path = [];
    const backTracking = (n,k,start) => {
        if(path.length === k){
            //[...path]
            result.push(path.slice());
            return;
        }
        for(let i = start;i <= n - (k - path.length) + 1;i++){
            path.push(i);
            backTracking(n,k,i+1);
            path.pop();
        }
    }
    backTracking(n,k,1);
    return result;

};

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

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

相关文章

一篇搞定ECharts的基本使用,赶快收藏起来学习吧~

准备工作 引入 声明一个有宽高的dDOM元素 echarts.init(DOM) option配置对象 echarts.setOptions(option) 基础配置 option类似于一个容器&#xff0c;那么里面的属性就相当于组件&#xff1a; xAxis&#xff08;直角坐标系 X 轴&#xff09;、yAxis&#xff08;直角坐…

关于udp能跨局域网传输的问题

UDP&#xff08;用户数据报协议&#xff09;以其独特的传输特性在多种应用场景中都有着极其重要的作用。然而&#xff0c;关于UDP是否能跨局域网&#xff08;LAN&#xff09;进行传输&#xff0c;以及这一传输过程中的优缺点&#xff0c;一直是网络技术领域讨论的热点。本文将详…

git基础命令(四)之分支命令

目录 基础概念git branch-r-a-v-vv-avv重命名分支删除分支git branch -h git checkout创建新的分支追踪远程分支同时切换到该分支创建新的分支并切换到该分支撤销对文件的修改&#xff0c;恢复到最近的提交状态&#xff1a;丢弃本地所有修改git checkout -h git merge合并指定分…

Windows系统安装VNC客户端结合内网穿透实现公网远程连接Deepin桌面

文章目录 1. 安装x11vnc2. 本地远程连接测试3. Deepin安装Cpolar4. 配置公网远程地址5. 公网远程连接Deepin桌面6. 固定连接公网地址7. 固定公网地址连接测试 x11vnc是一种在Linux系统中实现远程桌面控制的工具&#xff0c;它的原理是通过X Window系统的协议来实现远程桌面的展…

1688商品详情API接口采集商品上货

阿里巴巴1688平台并没有直接公开商品详情API接口供普通用户或开发者进行商品采集和上货。1688平台主要服务于批发和采购业务&#xff0c;其API服务通常面向的是有深度合作关系的商家或开发者&#xff0c;且需要经过申请和审核流程。 请求示例&#xff0c;API接口接入Anzexi58 …

Python Web开发记录 Day14:Django part8 订单管理

名人说&#xff1a;莫道桑榆晚&#xff0c;为霞尚满天。——刘禹锡&#xff08;刘梦得&#xff0c;诗豪&#xff09; 创作者&#xff1a;Code_流苏(CSDN)&#xff08;一个喜欢古诗词和编程的Coder&#x1f60a;&#xff09; 目录 1、数据库准备2、添加订单3、订单列表4、删除订…

C#集合:从字典到队列——探索数据结构核心

文章目录 C# 中的集合类型C# Dictionary 字典C# Hashtable&#xff1a;哈希表Hashtable 类中的属性Hashtable 类中的方法 C# SortedList&#xff1a;排序列表SortedList 类的中的属性SortedList 类的中的方法 C# Stack&#xff1a;堆栈Stack 类中的属性Stack 类中的方法 C# Que…

产品经理:前端实现网页防篡改,你会怎么做?

公众号&#xff1a;程序员白特&#xff0c;欢迎一起交流学习~ 如果产品经理要求系统中某个页面的输入框做防止篡改处理&#xff0c;你会怎么做呢&#xff1f; 需求梳理 首先&#xff0c;什么是防篡改&#xff1f; 简单来说&#xff0c;就是用户输入input框值&#xff0c;我们…

静态HTML5接入海康websocket视频流|海康ws视频流接入H5页面

引言 海康提供了vue实现插件播放视频的实例&#xff0c;实现取流失败了之后重新获取新的流播放视频&#xff0c;但是在很多情况下需要在静态HTML项目中进行视频的播放&#xff0c;于是引出此文。 海康开放平台SDK下载地址&#xff1a;https://open.hikvision.com/download/5c6…

Python使用 k 均值对遥感图像进行语义分割

本篇文章介绍K-means语义分割来估计 2000 年至 2023 年咸海水面的变化 让我们先看一下本教程中将使用的数据。这是同一地区的两张 RGB 图像,间隔 23 年,但很明显地表特性和大气条件(云、气溶胶等)不同。这就是为什么我决定训练两个独立的 k-Means 模型,每个图像一个。 首…

vue3 element plus 上传下载

文章目录 上传下载 上传 /* html */ <el-upload v-model"fileId" class"avatar-uploader" ref"exampleUploadRef" :file-list"fileList" :show-file-list"false" action"/ys-three-year/ThreeReport/uploadFile&q…

d3dcompiler_47.dll是什么,软件游戏报错d3dcompiler_47.dll缺失怎么修复?

当你在运行某些程序或游戏时出现"找不到d3dcompiler_47.dll"的错误提示时&#xff0c;不要慌张&#xff01;这是一个常见的问题&#xff0c;但有多种有效的解决办法可以帮助你修复这个文件丢失的情况。今天就来教大家d3dcompiler_47.dll文件丢失的多种解决办法。 一.…

旅游管理系统|基于SpringBoot+ Mysql+Java+Tomcat技术的旅游管理系统设计与实现(可运行源码+数据库+设计文档+部署说明+视频演示)

推荐阅读100套最新项目 最新ssmjava项目文档视频演示可运行源码分享 最新jspjava项目文档视频演示可运行源码分享 最新Spring Boot项目文档视频演示可运行源码分享 目录 前台功能效果图 用户功能 管理员功能登录前台功能效果图 系统功能设计 数据库E-R图设计 lunwen参考 …

【LeetCode每日一题】310. 最小高度树

文章目录 [310. 最小高度树](https://leetcode.cn/problems/minimum-height-trees/)思路&#xff1a;拓扑排序代码&#xff1a; 310. 最小高度树 思路&#xff1a;拓扑排序 首先判断节点数量n&#xff0c;如果只有一个节点&#xff0c;则直接返回该节点作为最小高度树的根节点…

【学习心得】Python数据分析的基本思路

一、什么是数据分析&#xff1f; 数据分析是指通过一些方法&#xff0c;对一些数据进行分析&#xff0c;从中提取出有价值的信息并形成结论进行展示。 &#xff08;1&#xff09;一些方法 数学和统计学方法&#xff1a;例如回归分析、聚类分析、主成分分析、时间序列分析等&a…

软件测试面试之支付系统测试

本篇文章主要从支付系统设计入手进行测试&#xff0c;针对界面功能测试容易忽略但是又十分重要的逻辑。关于支付密码、验证码、银行卡绑定等等能从界面入手测试的&#xff0c;下文也不讲述&#xff0c;如果有兴趣可以留言&#xff0c;后面整理。 1、APP支付结果查询是否合理 假…

广州地铁线路规划

使用python实现后端功能&#xff0c;由于地铁图需要进行展示&#xff0c;svg图需要花费比较多的时间&#xff0c;这里使用了 MetroFlow 库构建的地铁地图编辑器&#xff0c;可以在画布上构建矢量图&#xff0c;实现站点路线的创建。 用法&#xff1a; 打包好后完整目录&#x…

物联网数据驾驶舱

在信息化时代&#xff0c;数据已经成为驱动企业发展的核心动力。特别是在物联网领域&#xff0c;海量数据的实时采集、分析和监控&#xff0c;对于企业的运营决策和业务优化具有至关重要的作用。HiWoo Cloud作为领先的物联网云平台&#xff0c;其数据监控功能以“物联网数据驾驶…

2024年,AI赚钱的十大版块优势解析与适合人群

随着科技的飞速发展,AI技术正逐渐渗透到我们生活的方方面面。2024年,将是AI赚钱的黄金时期。那么,如何利用AI技术实现财富增长呢?本文将为您详细解析十大赚钱版块的优势及适合从事的人群,并通过一个实际案例,带您领略AI赚钱的无限魅力。 一、运用AI写作工具提供写作服务…

每日五道java面试题之mybatis篇(四)

目录&#xff1a; 第一题. 映射器#{}和${}的区别第二题. 模糊查询like语句该怎么写?第三题. 在mapper中如何传递多个参数?第四题. Mybatis如何执行批量操作第五题 MyBatis框架适用场景 第一题. 映射器#{}和${}的区别 #{}是占位符&#xff0c;预编译处理&#xff1b;${}是拼接…