力扣第46题“全排列”

news/2024/11/12 16:52:53/

题目描述

给定一个没有重复数字的整数数组 nums,返回其所有可能的排列。

示例:

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

解题思路

  1. 回溯法:通过递归构建排列,每次选择一个未使用的数字添加到当前排列中。
  2. 使用数组标记已选数字:使用一个布尔数组 used 来标记某个元素是否已被使用。
  3. 递归和回溯:每次添加一个新的数字到排列中,递归地继续添加直到形成完整排列,再回溯到上一状态尝试其他可能性。

代码实现

下面是详细的代码实现。

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>typedef struct {int** data;       // 存储所有排列结果int* columnSizes; // 每个排列的长度int size;         // 当前排列的数量int capacity;     // 容量
} ResultArray;// 初始化结果数组
ResultArray* createResultArray(int capacity) {ResultArray* result = (ResultArray*)malloc(sizeof(ResultArray));result->data = (int**)malloc(capacity * sizeof(int*));result->columnSizes = (int*)malloc(capacity * sizeof(int));result->size = 0;result->capacity = capacity;return result;
}// 添加排列到结果数组
void addResult(ResultArray* result, int* permutation, int length) {if (result->size >= result->capacity) {result->capacity *= 2;result->data = (int**)realloc(result->data, result->capacity * sizeof(int*));result->columnSizes = (int*)realloc(result->columnSizes, result->capacity * sizeof(int));}result->data[result->size] = (int*)malloc(length * sizeof(int));for (int i = 0; i < length; i++) {result->data[result->size][i] = permutation[i];}result->columnSizes[result->size] = length;result->size++;
}// 递归函数生成排列
void backtrack(int* nums, int numsSize, int* permutation, int level, bool* used, ResultArray* result) {if (level == numsSize) {  // 生成完整排列addResult(result, permutation, numsSize);return;}for (int i = 0; i < numsSize; i++) {if (!used[i]) {  // 选择一个未使用的数字used[i] = true;permutation[level] = nums[i];backtrack(nums, numsSize, permutation, level + 1, used, result);  // 递归used[i] = false;  // 回溯}}
}// 主函数
int** permute(int* nums, int numsSize, int* returnSize, int** returnColumnSizes) {ResultArray* result = createResultArray(100); // 初始化结果数组int* permutation = (int*)malloc(numsSize * sizeof(int));bool* used = (bool*)calloc(numsSize, sizeof(bool));backtrack(nums, numsSize, permutation, 0, used, result);*returnSize = result->size;*returnColumnSizes = result->columnSizes;free(permutation);free(used);return result->data;
}// 测试代码
int main() {int nums[] = {1, 2, 3};int numsSize = sizeof(nums) / sizeof(nums[0]);int returnSize;int* returnColumnSizes;int** result = permute(nums, numsSize, &returnSize, &returnColumnSizes);printf("所有排列结果:\n");for (int i = 0; i < returnSize; i++) {printf("[");for (int j = 0; j < returnColumnSizes[i]; j++) {printf("%d", result[i][j]);if (j < returnColumnSizes[i] - 1) printf(", ");}printf("]\n");free(result[i]);}free(result);free(returnColumnSizes);return 0;
}

代码解析

  1. 定义结果数组结构体

    • ResultArray 结构体用于存储所有排列及其相关信息,包含每个排列的长度和排列结果的指针。
  2. 初始化结果数组

    ResultArray* createResultArray(int capacity)
    

    用于初始化 ResultArray 结构体,分配初始容量为 100 的空间。

  3. 添加排列到结果数组

    void addResult(ResultArray* result, int* permutation, int length)
    

    将生成的排列添加到 ResultArray 中,当数组满时进行扩容。

  4. 回溯函数 backtrack

    void backtrack(int* nums, int numsSize, int* permutation, int level, bool* used, ResultArray* result)
    
    • 使用 level 表示当前排列的层级。
    • used 数组用于标记哪些数字已被使用,避免重复。
    • 每次递归生成完整排列时,调用 addResult 保存结果。
  5. 主函数 permute

    int** permute(int* nums, int numsSize, int* returnSize, int** returnColumnSizes)
    
    • 初始化 ResultArray 结构体,调用 backtrack 函数生成排列。
    • 设置 returnSizereturnColumnSizes,用于返回结果。

复杂度分析

  • 时间复杂度O(n * n!),其中 n 为数组长度。生成的排列数量为 n!,每个排列的生成需要 O(n) 的时间。
  • 空间复杂度O(n * n!),存储所有排列结果的空间复杂度。

http://www.ppmy.cn/news/1545926.html

相关文章

《数据结构》--二叉树【上】

&#x1f333;树的基础内容 树的定义&#xff1a; 树是一种数据结构&#xff0c;它是由n(n>1)个有限节点组成的一个具有层次关系的集合。把它叫做"树"是因为它看起来像一颗倒挂着的树&#xff0c;也就是说它是根在上&#xff0c;叶在下的。 树的特点&#xff1a…

openresty入门教程:init_by_lua_block

init_by_lua_block 是 Nginx 配置中用于在 Nginx 启动时执行 Lua 脚本的一个指令。这个指令通常用于初始化全局变量、设置共享内存&#xff0c;或者执行一些需要在服务器启动时完成的准备工作。 以下是一个简单的 init_by_lua_block 使用示例&#xff1a; 1. 安装 Nginx 和 L…

从0开始学习机器学习--Day20--优化算法的思路

确定执行的优先级(Prioritizing what to work on : Spam classification example) 在建立学习系统前&#xff0c;我们不仅要梳理框架&#xff0c;更重要的是我们要弄清楚有哪些事情是要优先做的&#xff0c;这可以帮我们节约大量的时间。 以垃圾邮件为例&#xff0c;按照之前…

实时计算 Flash – 兼容 Flink 的新一代向量化流计算引擎

摘要&#xff1a;本文整理自阿里云智能集团研究员、开源大数据平台负责人王峰&#xff08;莫问&#xff09;老师在云栖大会的开源大数据专场上的分享。主要有以下几个内容&#xff1a; 1. Apache Flink 已经成为业界流计算事实标准 2. Flash 向量化流计算引擎核心技术解读 3. F…

24.11.6 PySimpleGUI库和pymsql 库以及人脸识别小项目

PySimpleGUI 库 PySimpleGUI 是一个用于简化 GUI 编程的 Python 包&#xff0c;它封装了多种底层 GUI 框架&#xff08;如 tkinter、Qt、WxPython 等&#xff09;&#xff0c;提供了简单易用的 API。PySimpleGUI 包含了大量的控件&#xff08;也称为小部件或组件&#xff09;&…

Kafka中如何做到数据唯一,即数据去重?

数据传递语义 至少一次&#xff08;At Least Once&#xff09; ACK级别设置为-1 分区副本大于等于2 ISR里应答的最小副本数量大于等于2 可以保障数据可靠 • 最多一次&#xff08;At Most Once&#xff09; ACK级别设置为0 • 总结&#xff1a; At Least Once可以保证数据不…

Linux---进程间通信之共享内存

前言 我们前面学习了管道&#xff0c;今天我们学习另一种进程间通信方式--->共享内存。管道通信本质是基于文件系统的&#xff0c;并不关操作系统什么事&#xff0c;而system V IPC是操作系统特地设计的一种通信方式。但他们的目的都是一样的&#xff0c;就是让不同的进程看…

分布式数据库技术深度解析与代码实践

分布式数据库技术深度解析与代码实践 随着大数据和云计算的快速发展,分布式数据库作为一种高性能、高可用性和可扩展性的数据存储解决方案,被广泛应用于各种业务场景中。本文将深入探讨分布式数据库的核心技术、架构设计及其实践应用,并通过具体代码示例展示如何在实际项目…