首页 > 编程语言 >【DFS深度优先算法】全排列、组合总和

【DFS深度优先算法】全排列、组合总和

时间:2023-11-29 13:11:46浏览次数:30  
标签:std target retvec DFS 算法 vector candidates vec 总和

全排列

题目描述:给定一个没有重复数字的序列,返回其所有可能的全排列。

题目链接:46. 全排列

输入描述:
输入:[1,2,3]
输出描述:
输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]

思路:依次从前往后把所有数字,固定在第0个位置,此时再从前往后把剩余数字依次固定在第1个位置,如此递归,直到把倒数第二个数字固定,此时最后一个数字只剩一种可能,把整个序列放到结果中。

void DFS(std::vector<std::vector<int> >& retvec, std::vector<int>& vec, int fix)
{
	if (fix == vec.size() - 1)
	{
		retvec.emplace_back(vec);
		return;
	}


	for (int i = fix; i < vec.size(); ++i)
	{
		//每一位,都有N个可能
		std::swap(vec[i], vec[fix]);
		DFS(retvec, vec, fix + 1);
		std::swap(vec[i], vec[fix]);
	}
}

vector<vector<int>> permute(vector<int>& nums) {
	std::vector<std::vector<int> > retvec;
	DFS(retvec, nums, 0);
	return retvec;
}

全排列II

题目描述:给定一个可包含重复数字的序列 nums ,按任意顺序 返回所有不重复的全排列。

题目链接:47. 全排列 II

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

思路:依次从前往后把所有数字,固定在第0个位置,如果这个数字已经在这个位置出现过,则跳过这个数字,此时再从前往后把剩余数字依次固定在第1个位置,如此递归,直到把倒数第二个数字固定,此时最后一个数字只剩一种可能,把整个序列放到结果中。

void DFS(std::vector<std::vector<int> >& retvec, std::vector<int>& vec, int fix)
{
	if (fix == vec.size() - 1)
	{
		retvec.emplace_back(vec);
		return;
	}

	std::set<int> fixset;//这个位置不能出现两次同一个数
	for (int i = fix; i < vec.size(); ++i)
	{
		if (fixset.count(vec[i]))
			continue;
		fixset.insert(vec[i]);
		//每一位,都有N个可能
		std::swap(vec[i], vec[fix]);
		DFS(retvec, vec, fix + 1);
		std::swap(vec[i], vec[fix]);
	}
}

vector<vector<int>> permuteUnique(vector<int>& nums) {
	std::vector<std::vector<int> > retvec;
	DFS(retvec, nums, 0);
	return retvec;
}

组合总和

题目描述:给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target ,找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 ,并以列表形式返回。你可以按 任意顺序 返回这些组合。
candidates 中的 同一个 数字可以 无限制重复被选取 。如果至少一个数字的被选数量不同,则两种组合是不同的。
对于给定的输入,保证和为 target 的不同组合数少于 150 个。

题目链接:39. 组合总和

示例 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
输出: []

思路:依次从前往后把所有数字放到当前的集合中并更新当前集合的和,此时又从前往后把所有数字(因为每个数字可以重复取,所以这里不是剩余数字)依次放入当前集合并更新当前集合的和,如此递归,直到当前集合的和等于target则将当前集合放入结果集合,如果集合的和大于target直接返回即可。

优化思路:这里会出现很多重复数据,比如candidates = [2,3], target = 5,会输出[[2,3],[3,2]],这是因为在把3放入集合首位时,但是其实集合里有2、3和集合里有3、2的集合肯定是一样的集合。如果把源数据是进行升序排列,从前往后将数据放入当前集合中时,放2之后肯定会放3,那么当我放入3后,不用考虑放2,因为2比3小,之前放2的时候肯定放过3了,而且数据是升序的,如果把当前数据放入集合后,当前集合的和已经大于target了,由于后续所有的数字都不比当前数字小,就没必要继续放后面的数了,可以直接break

void DFS(const std::vector<int>& candidates, std::vector<std::vector<int> >& retvec,
	std::vector<int>& curvec, int target, int fix)
{
	if (target == 0)
	{
		retvec.emplace_back(curvec);
		return;
	}

	for (int i = fix; i < candidates.size(); ++i)
	{
		if (target - candidates[i] < 0)
			break;
		curvec.emplace_back(candidates[i]);
		DFS(candidates, retvec, curvec, target - candidates[i], i);
		curvec.pop_back();
	}
}

vector<vector<int>> combinationSum(vector<int>& candidates, int target)
{
	std::vector<int> curvec;
	std::vector<std::vector<int> > retvec;
	std::sort(candidates.begin(), candidates.end());
	DFS(candidates, retvec, curvec, target, 0);
	return retvec;
}

标签:std,target,retvec,DFS,算法,vector,candidates,vec,总和
From: https://www.cnblogs.com/zhonglimo/p/17864585.html

相关文章

  • 算法实验报告1
    算法实验报告1发布地址(方便阅读):https://cmd.dayi.ink/3VqGmm4dRamR85T2ptXCsQhttps://blog.dayi.ink/?p=91<>P183习题-T1题目描述给定一个数字n和子集1,2,3,...,n-1,请用数组输出所有不同的划分方式。4有四种划分方式:1+1+1+11+1+2.1+3.2+2.5有六种划分方式:1+1+1+1+1.1+1+1+2,1+1+3,1+2+2,1+4,3+2......
  • 强化学习:AC算法中为什么不使用Q函数来表示优势函数
      《High-DimensionalContinuousControlUsingGeneralizedAdvantageEstimation》      ====================== 原论文: ......
  • C/C++ 常用的四种查找算法
    在计算机科学中,搜索算法是一种用于在数据集合中查找特定元素的算法。C语言作为一种强大的编程语言,提供了多种搜索算法的实现方式。本文将介绍C语言中的四种常见搜索算法其中包括(线性查找,二分法查找,树结构查找,分块查找),并提供每种算法的简单实现示例。常见的查找算法主要有以下几种......
  • 二、HDFS的读写流程
    一、写数据(宏观)  写数据就是将客户端上的数据上传到HDFS 1.客户端向HDFS发送写数据请求 hdfsdfs-putstudents.txt/shujia/ 2.Filesystem通过rpc调用namenode的put方法 a.nn首先检查是否有足够的空间权限等条件创建这个文件,或者这个路径是否已经存在,权限......
  • Hadoop三大组件(HDFS,MapReduce,Yarn)
    1、HDFSHDFS是Hadoop分布式文件系统。一个HDFS集群是由一个NameNode和若干个DataNode组成的。其中NameNode作为主服务器,管理文件系统的命名空间和客户端对文件的访问操作;集群中的DataNode管理存储的数据。2、MapReduceMapReduce是一个软件框架,基于该框架能够容易地编写应用......
  • XML数字签名-Signature语法和签名算法[转]
    XML数字签名-Signature语法和签名算法 一段Demo:<ds:Signaturexmlns:ds="http://www.w3.org/2000/09/xmldsig#"><ds:SignedInfo><!--规范化的算法--><ds:CanonicalizationMethodAlgorithm="http://www.w3.org/TR/2001/RE......
  • r语言有限正态混合模型EM算法的分层聚类、分类和密度估计及可视化|附代码数据
    原文链接:http://tecdat.cn/?p=23825最近我们被客户要求撰写关于有限正态混合模型EM算法的研究报告,包括一些图形和统计输出。简介本文介绍了基于有限正态混合模型在r软件中的实现,用于基于模型的聚类、分类和密度估计。提供了通过EM算法对具有各种协方差结构的正态混合模型进行参......
  • 算法笔记
    图的算法Dijkstra算法:(净化被黑暗能量污染的城市)求图的单源最短距离,给出图G(V,E)(精灵城市图)和起点城市O(Origin),设置一个存放已经被光明之力净化的城市集合S,现在要从起点O出发,开放所有与起点O相连的road,以最短路径去往各城市进行净化,每次从V-S集合(未被净化的城市)中选出一个......
  • 有向图求强连通分量的几种算法
    概要本文介绍了kosaraju,tarjan算法求强连通分量概念有一个有向图G,有几个概念强连通若图中有两个点u和v,他们能互相到达,则称他们强连通强连通图若是G中任意2个点都可以互相到达,则称G是一个强连通图强连通分量有向非强连通图的极大强连通子图(可以有很多个)完全......
  • 国标GB28181安防监控平台EasyCVR周界入侵AI算法检测方案
    在城市管理和公共安全领域,安全视频监控的重要性日益凸显。AI视频智能分析平台基于深度学习和计算机视觉技术,利用AI入侵算法,能够实时、精准地监测周界入侵行为。TSINGSEE青犀在视频监控及AI视频智能分析领域拥有深厚的技术积累和丰富的实践经验。其中,AI视频智能分析系统/AI算法中......