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

pta题目:字符串的全排列

题目描述

给定一个全由小写字母构成的字符串,求它的全排列,按照字典序从小到大输出。

输入格式:
一行,一个字符串,长度不大于8。

输出格式:
输出所有全排列,每行一种排列形式,字典序从小到大。

输入样例:
在这里给出一组输入。例如:

abc

输出样例:
在这里给出相应的输出。例如:

abc
acb
bac
bca
cab
cba

分治法解决步骤

  • 分解问题:将字符串分解为一个字符和剩下的部分。对于每个字符,将它放在当前排列的开头位置,然后对剩下的字符进行递归全排列。
  • 递归求解:在每次递归中,将剩下的字符分解并排列,直到字符串长度为1。
  • 合并结果:在递归层级返回时,汇总每一层的结果,从而得到所有排列组合。
  • 去重和排序:为确保字典序输出,在进入递归之前将字符排序,并跳过重复字符。

代码

  1. 使用set存储结果
#include <iostream>
#include <string>
#include <algorithm>
#include <set>using namespace std;void permute(string& str, int start, set<string>& result){// 递归结束条件if (start == str.size()){ // 处理完所有字符result.insert(str);return;}for(int i = start; i < str.size(); ++i){swap(str[start], str[i]);  // 交换当前i位置要固定的字符,使该位置的所有可能字符取到permute(str, start + 1, result); // 固定当前字符,递归处理后面部分swap(str[start], str[i]);  // 恢复位置}
}int main() {string input;cin >> input;// 使用set存储,可以避免对重复元素的处理set<string> result;permute(input, 0, result);for(const auto &elem: result){cout << elem << endl;}return 0;
}
  1. 使用vector存储结果
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>using namespace std;void permute(string &s, int start, vector<string> &result) {// 基本情况:如果起始位置到字符串结尾,表示找到一个排列if (start == s.size()) {result.push_back(s);return;}// 使用集合来跳过重复字符for (int i = start; i < s.size(); ++i) {// 跳过重复字符if (i != start && s[i] == s[start]) continue;swap(s[start], s[i]);         // 交换当前i位置要固定的字符,使该位置的所有可能字符取到permute(s, start + 1, result); // 递归求解后续字符的排列swap(s[start], s[i]);         // 还原字符位置}
}int main() {string s;cin >> s;vector<string> result;sort(s.begin(), s.end()); // 确保字符串按字典序排列permute(s, 0, result);for (const auto &elem : result) {cout << elem<< endl;}return 0;
}

使用两种容器的性能分析

使用 std::set 来保存元素会有一些额外的性能开销,相比于 std::vector 或其他顺序容器,主要体现在以下几个方面:

1. 存储结构
  • std::set:底层通常实现为红黑树(或其他平衡树),每次插入、删除和查找操作的时间复杂度为 (O(\log n))。插入时,元素会自动按照顺序排列。
  • std::vector:底层实现为动态数组,插入、删除操作的时间复杂度为 (O(n))(在最坏情况下),但查找操作在平均情况下是 (O(1)),适合随机访问。
2. 插入和查找的性能
  • 当你插入元素到 std::set 时,容器会根据元素的值保持排序状态。因此,每次插入的开销相对较高,特别是对于大量元素。
  • 而在 std::vector 中,插入元素的开销较低,尤其是在末尾插入的情况下,因为只需简单地增加大小和复制元素。但在插入时要维护顺序(例如排序)时,就需要额外的开销。
3. 内存使用
  • std::set 的内存开销通常比 std::vector 大,因为它需要存储额外的指针来维护树的结构。
  • std::vector 的内存使用更加紧凑,适合存储大量相同类型的元素。
4. 访问性能
  • std::set 只能通过迭代器访问元素,不能像 std::vector 一样通过索引随机访问。这意味着访问特定元素时会更加耗时。
总结

如果你的主要需求是存储元素并自动保持它们的有序状态,且你不在意额外的性能开销,那么使用 std::set 是一个不错的选择。但如果你的应用需要频繁地进行随机访问或对大量元素进行插入/删除操作,使用 std::vector 可能会更有效率。

在很多情况下,如果不需要保持元素的唯一性和自动排序,而只是需要一个动态数组的特性,std::vector 通常会是更好的选择。你可以在使用 std::vector 后对其进行排序,虽然排序的时间复杂度是 (O(n \log n)),但在某些情况下这仍然会比使用 std::set 更高效。


http://www.mrgr.cn/news/64685.html

相关文章:

  • Machine Learning
  • 基于SSM+小程序的高校寻物平台管理系统(失物1)
  • Python小游戏19——滑雪小游戏
  • Eureka与 Zookeeper 在服务注册与发现中的差异解析
  • Java 文件操作与IO流
  • 将一个文件夹存放到 GitHub 已有仓库
  • 计算机性能分析的三个模型
  • 树(入门)
  • 自杀一句话木马(访问后自动删除)
  • MySQL——事务
  • Redis安装与使用 + Springboot整合Redis
  • wpf中行为
  • 502 Bad Gateway 错误详解:从表现推测原因,逐步排查直至解决
  • IDEA2024下安装kubernetes插件并配置进行使用
  • 代理IP地址和端口是什么?怎么进行设置?
  • 达人探店和好友关注功能(feed流的使用,滚动分页查询)
  • Python 有哪些优雅的代码实现让自己的代码更pythonic?
  • 串口接收,不定长数据接收
  • 00 递推和递归的核心讲解
  • LeetCode27:移除元素
  • JavaEE进阶---第一个SprintBoot项目创建过程我的感受
  • 1.kubernetes作用及组件
  • (五)PostgreSQL数据库操作示例
  • 如何使用Python WebDriver爬取ChatGPT内容(完整教程)
  • 我为何要用wordpress搭建一个自己的独立博客
  • Linux基础 文件与目录