力扣-排列组合问题(递归回溯)——77. 组合、46. 全排列、47. 全排列 II

一、组合

1. 问题描述

给定两个整数 n 和 k,返回范围 [1, n] 中所有可能的 k 个数的组合。

你可以按 任何顺序 返回答案。

示例 1:

输入:n = 4, k = 2
输出:
[[2,4],[3,4],[2,3],[1,2],[1,3],[1,4],
]

示例 2:

输入:n = 1, k = 1
输出:[[1]]

2. 代码实现

(1)c++实现代码

class Solution {
private:vector<vector<int>> result; // 存放符合条件结果的集合int stack[999], top = -1; // 用来存放符合条件结果void backtracking(int n, int k, int startIndex) {// 当结果的长度符合时,将结果存放到result结果集合中if (top+1 == k) {vector<int> ans;for(int i=0;i<=top;i++){ans.push_back(stack[i]);}result.push_back(ans);return;}for (int i = startIndex; i <= n; i++) {stack[++top] = i;backtracking(n, k, i + 1); // 递归top--;// 回溯,撤销处理的节点}}public:vector<vector<int>> combine(int n, int k) {result.clear();backtracking(n, k, 1);return result;}
};

 (2)c语言实现代码

struct Combination {// 嵌套数组结果int **result;// 中间数组int *path;// 中间数组的长度int pathSize;// 结果数组的总数int returnSize;
};void backtrack(struct Combination *com, int n, int k, int startIndex) {// 当组合的大小达到k时,将其添加到结果中if (com->pathSize == k) {// 在result的数组returnSize(也就是第几个结果集的位置)的位置提前申请一个空间com->result[com->returnSize] = (int *)malloc(k * sizeof(int));// 将中间数组存入result数组中for (int i = 0; i < k; i++) {com->result[com->returnSize][i] = com->path[i];}// 将结果集+1com->returnSize++;return;}// 横向遍历(加入了剪枝操作,即最后组成的数无法到要求直接剪掉即可)for (int i = startIndex; i <= n - (k - com->pathSize) + 1; i++) {// 处理当前节点com->path[com->pathSize] = i; // 中间数组长度+1com->pathSize++;// 纵向遍历(选择之后不能继续再选,即i+1)backtrack(com, n, k, i + 1);// 回溯,撤销处理的节点com->pathSize--; }
}int** combine(int n, int k, int* returnSize, int** returnColumnSizes) {// 定义暂存结构体struct Combination com;com.returnSize = 0;com.pathSize = 0;// 初始条件是否符号条件if (n <= 0 || k <= 0 || k > n) {return NULL;}// 计算组合的总数int totalCombinations = 1;for (int i = 1; i <= k; i++) {totalCombinations *= (n - i + 1);totalCombinations /= i;}// 分配结果数组的空间com.result = (int **)malloc(totalCombinations * sizeof(int *));com.path = (int *)malloc(k * sizeof(int));// 使用回溯法生成组合backtrack(&com, n, k, 1);// 返回每一个子数组的大小*returnColumnSizes = (int *)malloc(com.returnSize * sizeof(int));for (int i = 0; i < com.returnSize; i++) {(*returnColumnSizes)[i] = k;}// 返回结果数组的大小*returnSize = com.returnSize;return com.result;
}

二、全排列

1. 问题描述

给定一个不含重复数字的数组 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]]

2. 代码实现

 c++代码实现

class Solution {
private:vector<vector<int>> result;int stack[999], top=-1;void backtracking (vector<int>& nums, vector<bool>& used) {// 此时说明找到了一组if (top+1 == nums.size()) {vector<int> ans;for(int i=0;i<=top;i++){ans.push_back(stack[i]);}result.push_back(ans);return;}for (int i = 0; i < nums.size(); i++) {// 已经使用过直接跳过即可if(used[i] == true){continue;}// used[i - 1] == true,说明同一树枝nums[i - 1]使用过// used[i - 1] == false,说明同一树层nums[i - 1]使用过 // 如果同一树层nums[i - 1]使用过则直接跳过if (i > 0 && nums[i] == nums[i - 1] && used[i - 1] == false) {continue;}used[i] = true;stack[++top] = nums[i];backtracking(nums, used);top--;used[i] = false;}}
public:vector<vector<int>> permute(vector<int>& nums) {result.clear();sort(nums.begin(), nums.end()); // 排序vector<bool> used(nums.size(), false);backtracking(nums, used);return result;}
};

c语言实现

struct Combination{// 结果数组int **result;int resultSize;// 中间数组int *path;int pathSize;
};void backtrace(struct Combination *com, int nums[], int n, int used[])
{// 当组合的大小达到k时,将其添加到结果中if(com->pathSize == n){com->result[com->resultSize] = (int*)malloc(n*sizeof(int));for(int i=0;i<n;i++){com->result[com->resultSize][i] = com->path[i];}com->resultSize++;return;}// 横向遍历for(int i=0; i<n; i++){// 如果已经使用过就不再次使用if(used[i] == 1){continue;}used[i] = 1;com->path[com->pathSize] = nums[i];com->pathSize++;// 纵向遍历backtrace(com, nums, n, used);com->pathSize--;used[i] = 0;}
}int** permute(int* nums, int numsSize, int* returnSize, int** returnColumnSizes){struct Combination com;com.resultSize = 0;com.pathSize = 0;// 结果集总数int total = 1;for(int i=1;i<=numsSize;i++){total *= i;}// malloc申请空间com.result = (int**)malloc(total*sizeof(int*));   // 嵌套数组com.path = (int*)malloc(numsSize*sizeof(int));  // 数组// 状态数组int used[numsSize];for(int i=0;i<numsSize;i++){used[i] = 0;}// 开始回溯backtrace(&com, nums, numsSize, used);// 返回每一个子数组的大小*returnColumnSizes = (int *)malloc(com.resultSize * sizeof(int));for (int i = 0; i < com.resultSize; i++) {(*returnColumnSizes)[i] = numsSize;}// 返回结果数组的大小*returnSize = com.resultSize;return com.result;
}

三、 全排列 II

1. 问题描述

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

示例 1:

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

示例 2:

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

2. 代码实现

c++代码实现 

class Solution {
private:vector<vector<int>> result;int stack[999], top=-1;void backtracking (vector<int>& nums, vector<bool>& used) {// 此时说明找到了一组if (top+1 == nums.size()) {vector<int> ans;for(int i=0;i<=top;i++){ans.push_back(stack[i]);}result.push_back(ans);return;}for (int i = 0; i < nums.size(); i++) {// 已经使用过直接跳过即可if(used[i] == true){continue;}// used[i - 1] == true,说明同一树枝nums[i - 1]使用过// used[i - 1] == false,说明同一树层nums[i - 1]使用过 // 如果同一树层nums[i - 1]使用过则直接跳过if (i > 0 && nums[i] == nums[i - 1] && used[i - 1] == false) {continue;}used[i] = true;stack[++top] = nums[i];backtracking(nums, used);top--;used[i] = false;}}
public:vector<vector<int>> permuteUnique(vector<int>& nums) {result.clear();sort(nums.begin(), nums.end()); // 排序vector<bool> used(nums.size(), false);backtracking(nums, used);return result;}
};

        从上面三个题目的代码可以看到其实这三个题目出自同一个模板,稍微总结一下就可以得出,也可以从上面三个题目很好的学习回溯的方法

        上面两个组合和全排列都给出来C++和C语言的代码,C++主要借助vector容器的实现,而C则要复杂一些,我选择使用的是结构的方法实现。 

        解题思路和代码模板均来自代码随想录 - 力扣(LeetCode)

 

77. 组合

​​​​​​46. 全排列

47. 全排列 II

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

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

相关文章

Java 使用mybatis的BaseTypeHandler实现数据自动AES加密解密,通过Hutool工具类自定义注解实现数据脱【附有完整步骤和代码】

一、AES加密 1 加密工具类 使用KeyGenerator生成AES算法生成器 public class AESUtil {/*** 密钥长度: 128, 192 or 256*/private static final int KEY_SIZE 256;/*** 加密/解密算法名称*/private static final String ALGORITHM "AES";/*** 随机数生成器&#…

【CDP】CDP 集群通过Knox 访问Yarn Web UI,无法跳转到Flink Web UI 问题解决

一、前言 记录下在CDP 环境中&#xff0c;通过Knox 访问Yarn Web UI&#xff0c;无法跳转到Flink Web UI 的BUG 解决方法。 二、问题复现 登录 Knox Web UI 找到任一 Flink 任务 点击 ApplicationMaster 跳转 Flink WEB UI 出问题 内容空白&#xff0c;无法正常跳转到…

JS基本语法

JS基本语法 变量数据类型原始数据类型 函数定义第一种方式第二种方式 JS 对象ArrayStringJavaScript 自定义对象JSONDOMBOM JS 事件事件监听事件绑定常见事件 变量 数据类型 原始数据类型 函数定义 第一种方式 第二种方式 JS 对象 Array String JavaScript 自定义对象 JSON …

力扣221. 最大正方形

动态规划 思路&#xff1a; 假设 dp[i][j] 是第 i 行&#xff0c;第 j 列为右底点最大正方形边长&#xff1b;则对应的状态转移方程 s[i][j] 0, dp[i][j] 0s[i][j] 1 时&#xff0c; 如果是第1行或者第一列&#xff0c;dp[i][j] 1&#xff1b;其余情况下&#xff0c;dp[i]…

向华为学习:基于BLM模型的战略规划研讨会实操的详细说明,含研讨表单(一)

前面&#xff0c;华研荟用了三篇文章介绍华为战略规划的时候使用的其中一个工具&#xff1a;五看三定。一句话来说&#xff0c;五看三定是通过“五看”来知己知彼&#xff0c;然后设计业务&#xff0c;在选定的业务领域&#xff08;方向&#xff09;确定战略控制点&#xff0c;…

STM32_HAL库—IWDG看门狗

一、CubeMX设置 1、晶振配置&#xff08;72M&#xff09; 2、数据配置 超时时间 Tout prv / LSI * rlv (s) 其中prv是预分频器寄存器的值&#xff0c;rlv是重装载寄存器的值&#xff0c;而LSI值默认是40kHz&#xff0c;如下所示。 3、代码实现 int main(){while(1){HAL_IW…

【c++】stl_priority_queue优先级队列

目录 一、priority_queue的介绍 二、 priority_queue的本质 三、priority_queue的使用 四、priority_queue的模拟实现 总结 一、priority_queue的介绍 首先让我们通过阅读优先级队列的官方文档 简单翻译一下 1. 优先队列是一种容器适配器&#xff0c;根据严格的弱排序标准…

MySQL数据库遇到不规范建表问题解决方案

简介&#xff1a; 需要建立的关联表如上图所示。 问题发现&#xff1a; 好&#xff0c;问题来了&#xff0c;大伙儿请看&#xff1a;我们的organizations表中的Industry字段居然存储了两个IndustryName&#xff0c;这就很恶心了&#xff0c;就需要我们进行拆分和去重后放到In…

【vtkWidgetRepresentation】第十二期 vtkBalloonRepresentation

很高兴在雪易的CSDN遇见你 VTK技术爱好者 QQ:870202403 前言 本文分享vtkBalloonRepresentation,用于标注文字或图片,希望对各位小伙伴有所帮助! 感谢各位小伙伴的点赞+关注,小易会继续努力分享,一起进步! 你的点赞就是我的动力(^U^)ノ~YO 1. vtkBalloonRepre…

竞赛保研 opencv 图像识别 指纹识别 - python

0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 基于机器视觉的指纹识别系统 &#x1f947;学长这里给一个题目综合评分(每项满分5分) 难度系数&#xff1a;3分工作量&#xff1a;3分创新点&#xff1a;4分 该项目较为新颖&#xff0c;适…

标书设计:目录的必要性与优化建议

标书&#xff0c;作为商务文件的一种&#xff0c;旨在展示公司实力、产品优势和服务水平&#xff0c;是企业开展商业活动的一项重要工具。在进行标书制作时&#xff0c;有人认为是否需要目录&#xff0c;成为了一个值得讨论的问题。 目录作为标书的导航&#xff0c;是否必要呢&…

Excel实现字母+数字拖拉自动递增,步长可更改

目录 1、带有字母的数字序列自增加&#xff08;步长可变&#xff09; 2、仅字母自增加 3、字母数字同时自增 1、带有字母的数字序列自增加&#xff08;步长可变&#xff09; 使用Excel通常可以直接通过拖拉的方式&#xff0c;实现自增数字&#xf…

Java报错-Non-terminating decimal expansion; no exact representable decimal result

1. 背景 在使用 BigDecimal 的 divide() 对两个数相除时&#xff0c;报了如题的错误。 public class Test {public static void main(String[] args) {BigDecimal b1 new BigDecimal(1);BigDecimal b2 new BigDecimal(3);System.out.println(b1.divide(b2)); // Sys…

单口千兆以太网物理层芯片

一、基本介绍 YT8521S是一款单口千兆以太网物理层芯片&#xff0c;YT8521S是一款高度集成的以太网收发器&#xff0c;符合10BASE-Te、100BASE-TX和1000BASE-T IEEE 802.3标准。它提供了传输和接收所需的所有物理层功能通过CAT.5E UTP电缆的以太网数据包。 YT8521S采用最先进的…

(洛谷)P8835 [传智杯 #3 决赛] 子串

[传智杯 #3 决赛] 子串 题目背景 disangan233 喜欢字符串&#xff0c;于是 disangan333 想让你找一些 disangan233 喜欢的串。 题目描述 在传智的开发课堂上&#xff0c;希望您开发一款文档处理软件。 给定 T T T 组询问&#xff0c;每次给定 2 2 2 个长度为 n , m n,m…

【Unity动画】综合案例完结-控制角色动作播放+声音配套

这个案例实现的动作并不复杂&#xff0c;主要包含一个 跳跃动作、攻击动作、还有一个包含三个动画状态的动画混合树。然后设置三个参数来控制切换。 状态机结构如下&#xff1a; 完整代码 using System.Collections; using System.Collections.Generic; using UnityEngine;pu…

字符设备驱动模块的编译

一. 简介 本文继上一篇文章的学习&#xff0c;上一篇文章学习了字符设备驱动框架的初步编写。文章地址如下&#xff1a; 字符设备驱动框架的编写-CSDN博客 本文对上一篇编写的驱动模块初步框架进行编译。 二. 字符设备驱动模块的编译 上一篇文章&#xff0c;编写了字符设备…

10、神秘的“位移主题”

神秘的“位移主题” 1、什么是位移主题2、位移主题的消息格式3、位移主题是怎么被创建的4、什么地方会用到位移主题5、位移主题的删除机制 本章主题是&#xff1a;Kafka 中的内部主题&#xff08;Internal Topic&#xff09;__consumer_offsets。 __consumer_offsets 在 Kafka …

[GESP样题 三级] 逛商场

题目名字 逛商场 题目链接 题意 给一定的零花钱&#xff0c;每个物品和剩余的零钱依次比较&#xff0c;只要能买就一定买&#xff0c;如果不能买就跳过&#xff0c;计算能买多少个物品&#xff1b; 思路 设置if循环来判断所剩零钱是否大于等于这个物品设置一个sum&#xff0c…