当前位置: 首页 > news >正文

面试经典算法1:DFS

一、前言

1、题目描述和代码仅供参考,如果有问题欢迎指出
2、解题代码采用acm模式(自己处理输入输出),不采用核心代码模式(只编程核心函数)
3、解题代码采用C++语言(ai一键翻译任意语言,或者cpp转Java等任意语言)

二、题目说明

题目:
给你一个整数集合 nums ,按任意顺序 返回它所有不重复的全排列
举例:
输入:nums = [1,2,3]
输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]

三、DFS回溯法(递归编程实现)

解题思路:
定义一个f()函数求可行的全排列解,如果到叶子节点时该路径可行就记录,否则回溯求解;
f(123) = 1 + f(23),
f(23)= 2 + f(3),
f(3)= 3

解题代码:

#include <iostream>
#include <vector>using namespace std;// end参数可以用nums.size()代替,但是这里为了方便理解所以加上
void permute(vector<int>& nums, int start, int end, vector<vector<int>>& result) {if (start == end) {result.push_back(nums);//到达叶子节点,记录结果return;}for (int i = start; i <= end; i++) {swap(nums[start], nums[i]);// 将第i个元素和第start个元素交换位置,固定第start个元素permute(nums, start + 1, end, result);// 递归调用,固定[start+1, end]这个区间的元素swap(nums[start], nums[i]); // 回溯恢复原来的数组顺序,用于下一次循环}
}int main() {vector<int> nums = { 1, 2, 3 };vector<vector<int>> result;permute(nums, 0, nums.size() - 1, result);for (auto& v : result) {for (int num : v) {cout << num << " ";}cout << endl;}return 0;
}

四、有重复元素时的解法:STL库函数实现

题目说明:
当 nums有重复元素时,如果采用回溯法 ,nums有重复元素就用hash记录被选择的数字,如果已经被选择过就跳过,这当然可以解决问题,不过我们有更优雅的解法,那就是STL中的库函数,这里写出来是因为面试官可能不让你直接调库函数;

解题思路:
两个函数next_permutation和prev_permutation,分别用于生成下一个排列和上一个排列。

next_permutation函数的工作原理是找到从右到左第一个升序对(即nums[i] < nums[i+1]),然后找到这个升序对右边第一个大于它的元素(即nums[j] > nums[i]),交换这两个元素的位置,最后将升序对右边的元素反转。这样就得到了下一个排列。

prev_permutation函数的工作原理类似,只是它是找升序对,然后找到这个升序对左边第一个小于它的元素,交换这两个元素的位置,最后将升序对左边的元素反转。这样就得到了上一个排列。

在main函数中,首先调用prev_permutation函数生成所有的上一个排列,然后调用next_permutation函数生成所有的下一个排列。这样就可以得到所有的排列,而且由于next_permutation函数会跳过所有重复的排列,所以可以避免重复。

原理很详细的一篇文章:https://blog.csdn.net/myRealization/article/details/104803834

解题代码:

#include <iostream>
#include <vector>
#include <algorithm>using namespace std;bool next_permutation(vector<int>& nums) {int i = nums.size() - 2;while (i >= 0 && nums[i] >= nums[i + 1]) --i;if (i == -1) return false;int j = nums.size() - 1;while (nums[j] <= nums[i]) --j;swap(nums[i], nums[j]);reverse(nums.begin() + i + 1, nums.end());return true;
}bool prev_permutation(vector<int>& nums) {int i = 0;while (i < nums.size() - 1 && nums[i] <= nums[i + 1]) ++i;if (i == nums.size() - 1) return false;int j = nums.size() - 1;while (nums[j] >= nums[i]) --j;swap(nums[i], nums[j]);reverse(nums.begin(), nums.begin() + i + 1);return true;
}int main() {vector<int> nums = {1, 2, 3};vector<vector<int>> result;while (prev_permutation(nums)){};//O(n)时间复杂度,而sort是nlog n do {result.push_back(nums);} while (next_permutation(nums));for(auto i: result){for(auto j : i)cout << j << " ";cout << endl;}return 0;
}

如此时间复杂度就是O(n),空间复杂度O(1),如果这样面试还是过不了的话,那就不是你的问题了…

迭代器版本实现

template<typename Iterator>
bool myNextPermutation(Iterator start, Iterator end) { //[start,end)Iterator cur = end - 1, pre = cur - 1; //pre指向partitionNumber while (cur > start && *pre >= *cur) --cur, --pre; //从右到左进行扫描,发现第一个违背非递减趋势的数字if (cur <= start) return false; //整个排列逆序, 不存在更大的排列 //从右到左进行扫描,发现第一个比partitionNumber大的数for (cur = end - 1; *cur <= *pre; --cur); //cur指向changeNumber  std::iter_swap(pre, cur);std::reverse(pre + 1, end); //将尾部的逆序变成正序 return true; 
}template<typename Iterator>
bool myPrevPermutation(Iterator start, Iterator end) { //[start,end)Iterator cur = end - 1, pre = cur - 1; //pre指向partitionNumber while (cur > start && *pre <= *cur) --cur, --pre; //从右到左进行扫描,发现第一个违背非递增趋势的数字if (cur <= start) return false; //整个排列逆序, 不存在更小的排列 //从右到左进行扫描,发现第一个比partitionNumber小的数for (cur = end - 1; *cur >= *pre; --cur); //cur指向changeNumber  std::iter_swap(pre, cur);std::reverse(pre + 1, end); //将尾部的逆序变成正序 return true; 
}

1 2 3
从小到大排序的是最小的排列,从大到小排序是最大的排列。

求f(123)的排列,实际上是确定了第1个数以后求len-1个数的排列即 1 + f(23),依次类推毫无疑问这会想到dfs;

然而还有更好的解法
举例 1 3 2,求增长幅度最小下一个排列,
32为逆序不可能减小,所以要换1,1和其右侧第一个大于1的数互换
互换之后此时后半部分是逆序,倒序交换数字的右侧以后就是最小的排列

精简步骤就是
next
1、从右到左找升序对的位置
2、右侧找第一个大于升序对的位置
3、交换,并倒序升序对右侧

prev
1、从左到右找降序对的位置
2、左侧找第一个小于降序对的位置
3、交换,并倒序降序对左侧

为什么不会有重复序列?
因为next_permutation()函数可以生成给定序列的下一个字典序排列。它通过在序列中查找第一个违反字典序排列的元素,并将其交换到序列末尾来实现这一点。
然后,它将序列中剩余的元素重新排序,以生成下一个字典序排列。

由于next_permutation()函数是基于字典序排列的,因此它不会生成重复的序列。这是因为每个元素都只能出现在其原始位置或者在其后面的某个位置上,而
不会出现在其前面的位置上。

举个例子,假设我们有一个序列 [1, 2, 3],它的下一个字典序排列是 [1, 3, 2]。如果我们再次调用next_permutation()函数,它会找到下一个字典序排列,
即 [2, 1, 3]。这个过程会一直持续下去,直到我们回到原始序列为止。

因此,next_permutation()函数可以确保生成的排列是唯一的,不会有重复的序列。

相关文章:

面试经典算法1:DFS

一、前言 1、题目描述和代码仅供参考&#xff0c;如果有问题欢迎指出 2、解题代码采用acm模式&#xff08;自己处理输入输出&#xff09;&#xff0c;不采用核心代码模式&#xff08;只编程核心函数&#xff09; 3、解题代码采用C语言&#xff08;ai一键翻译任意语言&#xff…...

Windows系统利用cpolar内网穿透搭建Zblog博客网站并实现公网访问内网!

文章目录 1. 前言2. Z-blog网站搭建2.1 XAMPP环境设置2.2 Z-blog安装2.3 Z-blog网页测试2.4 Cpolar安装和注册 3. 本地网页发布3.1. Cpolar云端设置3.2 Cpolar本地设置 4. 公网访问测试5. 结语 1. 前言 想要成为一个合格的技术宅或程序员&#xff0c;自己搭建网站制作网页是绕…...

SmartCode ViewerX VNC 3.11 Crack

SmartCode ViewerX VNC 查看器 ActiveX 轻松地将 VNC 查看器功能添加到您的应用程序中 SmartCode ViewerX VNC Viewer ActiveX 使开发人员可以使用一组直观的 ActiveX 属性和方法完全访问 VNC 查看器功能。借助ViewerX控件&#xff0c;开发人员可以轻松地为其应用程序提供屏幕共…...

傻瓜式Java操作MySQL数据库备份

文章目录 前言存储数据库存储数据表 前言 数据库备份是开发工作中经常要做的事情&#xff0c;好处是mysql提供了一个非常好的命令 mysqldump&#xff0c;直接调用它就可以将数据以sql文件的形式备份出来。但是直接写命令非常不方便&#xff0c;遇到定时备份或者指定备份那么就需…...

redis常用操作命令

日升时奋斗&#xff0c;日落时自省 注&#xff1a;命令区分有点细&#xff0c;择取自己需要的即可 目录 1、单机架构 2、数据库和应用分离 3、分布式基本概念 3.1、应用&#xff08;Application&#xff09;/系统(System) 3.2、模块&#xff08;Module&#xff09;/组件&…...

pytorch gpu安装

cuda https://blog.csdn.net/qq_51570094/article/details/124148671 https://blog.csdn.net/zxdd2018/article/details/127705627 cudnn https://docs.nvidia.com/deeplearning/cudnn/install-guide/index.html#installlinux-tar 更改cudnn 保证文件目录中只有一个解压后…...

uni跳转页面不缓存上一个页面的方法

一、前言 要实现一个需求&#xff0c;从a页面跳转到b页面&#xff0c;从b页面跳转到c页面&#xff0c;然后按返回&#xff0c;从c页面直接返回a页面&#xff08;不返回b页面&#xff09; a->b->c c->a 二、实现方法 前端框架使用的是uni-app&#xff0c;我们修改…...

排序:败者树和置换选择排序(解决外部排序中的优化问题)

1.算法目的&#xff08;败者树&#xff09; 解决多路平衡归并带来的问题。 在外部排序中&#xff0c;使用k路平衡归并策略, 选出一个最小元素需要对比关键字(k-1)次&#xff0c; 导致内部归并所需时间增加。&#xff08;可用“败者树”进行优化&#xff09; 2.败者树的定义 …...

【超分:光谱响应函数】

Spectral Response Function-Guided Deep Optimization-Driven Network for Spectral Super-Resolution &#xff08;光谱响应函数引导的深度优化驱动网络光谱超分辨&#xff09; 高光谱图像&#xff08;HSI&#xff09;是许多研究工作的关键。光谱超分辨率&#xff08;SSR&a…...

IoT 物联网 JavaScript 全栈开发,构建家居环境监控系统实战

智能家居环境监测端到端场景&#xff0c;全栈JavaScript开发&#xff0c;串联Ruff硬件、温湿度和空气质量传感器、阿里云 IoT、Serverless函数计算、百度ECharts可视化、最终以微信小程序形式在微信里实时展示家中实时温度&#xff0c;湿度&#xff0c;PM2.5指数。 01 技术架构…...

jupyter notebook可以打开,但无法打开.ipynb文件,报错500 : Internal Server Error

1、错误信息 2、解决办法 打开Anaconda Promt界面&#xff0c;进入自己的虚拟环境。在命令行输入以下指令&#xff1a; pip install --upgrade nbconvert...

latex图片编号+表格编号

对编号重新自定义 \renewcommand{\thefigure}{数字编号x}重新命名图的编号\renewcommand{\thetable}{数字编号x}重新命名表的编号编号含义 平时看书经常看到“图1.2”这样的编号&#xff0c;含义是第1章的第2幅插图&#xff1b;或者“图1.1.2”&#xff0c;含义是第1章第1节的…...

【1day】用友时空KSOA平台 imagefield接口SQL注入漏洞学习

注:该文章来自作者日常学习笔记,请勿利用文章内的相关技术从事非法测试,如因此产生的一切不良后果与作者无关。 目录...

linux之美

linux系统和window系统区别 Linux和Windows是两个不同的操作系统。Linux是一个开源操作系统&#xff0c;而Windows是一个商业操作系统。 Linux可以访问源代码并根据用户的需求进行修改&#xff0c;而Windows无法访问源代码。 Linux是免费的&#xff0c;而Windows是商业操作系…...

5、超链接标签

5、超链接标签 超链接标签就是我们常说的a标签 <a href"path" target"目标窗口位置">连接文本或图像</a> <!-- href&#xff08;必填项&#xff09;&#xff1a;连接路径 target&#xff1a;连接在哪个窗口打开&#xff1f;是在新页面打开…...

CCF CSP认证历年题目自练 Day15

CCF CSP认证历年题目自练 Day15 题目一 试题编号&#xff1a; 201709-1 试题名称&#xff1a; 打酱油 时间限制&#xff1a; 1.0s 内存限制&#xff1a; 256.0MB 问题描述&#xff1a; 问题描述   小明带着N元钱去买酱油。酱油10块钱一瓶&#xff0c;商家进行促销&#xf…...

APP的收费模式及特点

移动应用&#xff08;APP&#xff09;的收费模式多种多样&#xff0c;可以根据开发者的需求、目标受众和应用的性质来选择。以下是一些常见的APP收费模式及其特点&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xff0c;欢迎…...

opencv: 解决保存视频失败的问题

摘要&#xff1a;opencv能读取视频&#xff0c;但保存视频时报错。 一、首先要确保已经下载了openh264.dll文件&#xff0c;否则保存的视频无法打开&#xff0c;详细可以浏览这个&#xff1a;opencv&#xff1a;保存视频。 二、保存视频时出现一下问题&#xff1a; OpenCV:…...

源码编译安装zstd

目录 1 下载源码https://github.com/facebook/zstd 2 解压 3 在解压后的目录里输入make 4 sudo make install 安装完毕 5 输入whereis zstd 检查安装结果 1 下载源码https://github.com/facebook/zstd 2 解压 3 在解压后的目录里输入make 4 sudo make install 安装完毕…...

LabVIEW开发实时自动化多物镜云计算全玻片成像装置

LabVIEW开发实时自动化多物镜云计算全玻片成像装置 数字病理学领域正在迅速发展&#xff0c;这主要是由于计算机处理能力、数据传输速度、软件创新和云存储解决方案方面的技术进步。因此&#xff0c;病理科室不仅将数字成像用于图像存档等简单任务&#xff0c;还用于远程病理学…...

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…...

Java 语言特性(面试系列2)

一、SQL 基础 1. 复杂查询 &#xff08;1&#xff09;连接查询&#xff08;JOIN&#xff09; 内连接&#xff08;INNER JOIN&#xff09;&#xff1a;返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...

【HarmonyOS 5.0】DevEco Testing:鸿蒙应用质量保障的终极武器

——全方位测试解决方案与代码实战 一、工具定位与核心能力 DevEco Testing是HarmonyOS官方推出的​​一体化测试平台​​&#xff0c;覆盖应用全生命周期测试需求&#xff0c;主要提供五大核心能力&#xff1a; ​​测试类型​​​​检测目标​​​​关键指标​​功能体验基…...

线程同步:确保多线程程序的安全与高效!

全文目录&#xff1a; 开篇语前序前言第一部分&#xff1a;线程同步的概念与问题1.1 线程同步的概念1.2 线程同步的问题1.3 线程同步的解决方案 第二部分&#xff1a;synchronized关键字的使用2.1 使用 synchronized修饰方法2.2 使用 synchronized修饰代码块 第三部分&#xff…...

全球首个30米分辨率湿地数据集(2000—2022)

数据简介 今天我们分享的数据是全球30米分辨率湿地数据集&#xff0c;包含8种湿地亚类&#xff0c;该数据以0.5X0.5的瓦片存储&#xff0c;我们整理了所有属于中国的瓦片名称与其对应省份&#xff0c;方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...

【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表

1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...

佰力博科技与您探讨热释电测量的几种方法

热释电的测量主要涉及热释电系数的测定&#xff0c;这是表征热释电材料性能的重要参数。热释电系数的测量方法主要包括静态法、动态法和积分电荷法。其中&#xff0c;积分电荷法最为常用&#xff0c;其原理是通过测量在电容器上积累的热释电电荷&#xff0c;从而确定热释电系数…...

【分享】推荐一些办公小工具

1、PDF 在线转换 https://smallpdf.com/cn/pdf-tools 推荐理由&#xff1a;大部分的转换软件需要收费&#xff0c;要么功能不齐全&#xff0c;而开会员又用不了几次浪费钱&#xff0c;借用别人的又不安全。 这个网站它不需要登录或下载安装。而且提供的免费功能就能满足日常…...

vulnyx Blogger writeup

信息收集 arp-scan nmap 获取userFlag 上web看看 一个默认的页面&#xff0c;gobuster扫一下目录 可以看到扫出的目录中得到了一个有价值的目录/wordpress&#xff0c;说明目标所使用的cms是wordpress&#xff0c;访问http://192.168.43.213/wordpress/然后查看源码能看到 这…...

【JVM面试篇】高频八股汇总——类加载和类加载器

目录 1. 讲一下类加载过程&#xff1f; 2. Java创建对象的过程&#xff1f; 3. 对象的生命周期&#xff1f; 4. 类加载器有哪些&#xff1f; 5. 双亲委派模型的作用&#xff08;好处&#xff09;&#xff1f; 6. 讲一下类的加载和双亲委派原则&#xff1f; 7. 双亲委派模…...