突破编程_C++_字符串算法(检查一个字符串是否是某个字符串的排列)

本文讲解了如何通过C++实现字符串排列判断,利用哈希表统计字符频率并进行排序对比。涉及时间复杂度、空间复杂度及实际代码示例。
摘要由CSDN通过智能技术生成

1 算法题 :检查一个字符串是否是某个字符串的排列

1.1 题目含义

检查一个字符串是否是某个字符串的排列,需要判断两个字符串是否由相同的字符组成,且每个字符出现的次数也相同,但是字符的顺序可以不同。简而言之,如果能够通过对一个字符串中的字符进行重新排列,使其与另一个字符串完全相同,那么这两个字符串就是彼此的排列。

1.2 示例

示例 1:
输入:

  • 字符串1:“anagram”
  • 字符串2:“nagaram”

输出:

  • true

解释:

  • 字符串 1 和字符串 2 都由字符’a’、‘n’、‘a’、‘g’、'r’和’m’组成,并且每个字符出现的次数也相同。虽然字符的顺序不同,但它们仍然是彼此的排列。

示例 2:
输入:

  • 字符串1:“listen”
  • 字符串2:“silent”

输出:

  • true

解释:

  • 字符串 1 和字符串 2 都由字符’l’、‘i’、‘s’、‘t’和’e’、'n’组成(注意’n’和’e’的顺序在两个字符串中是不同的),并且每个字符出现的次数也相同。因此,它们是彼此的排列。

示例 3:
输入:

  • 字符串1:“hello”
  • 字符串2:“world”

输出:

  • false

解释:

  • 字符串 1 由字符’h’、‘e’、‘l’、‘l’和’o’组成,而字符串 2 由字符’w’、‘o’、‘r’、‘l’和’d’组成。尽管两个字符串都包含字符’l’和’o’,但它们包含的其他字符和字符的总数不同,因此它们不是彼此的排列。

2 解题思路

解题思路如下:

(1)初始化: 首先,需要两个字符串作为输入,将其称之为 str1 和 str2。

(2)长度检查: 首先检查两个字符串的长度是否相等。如果长度不等,那么它们不可能是彼此的排列,因为排列意味着字符的种类和数量都必须相同。

(3)字符计数: 使用一个数据结构(如数组或哈希表)来统计 str1 中每个字符的出现次数。数组的大小通常是 26(针对小写英文字母)或 52(针对小写和大写英文字母),哈希表则没有这样的限制。

(4)比较字符计数: 接下来,遍历 str2 中的每个字符,并在字符计数数据结构中减少对应字符的计数。如果任何时候某个字符的计数降到 0 以下,或者某个字符在 str2 中不存在但在 str1 中存在(即计数不为 0),那么这两个字符串不是彼此的排列。

(5)检查结果: 如果上述过程没有提前返回 false,那么在遍历完 str2 之后,可以得出结论,两个字符串是彼此的排列,因为它们的字符种类和数量都相同。

(6)返回结果: 根据检查结果,返回 true 或 false。

这个算法的时间复杂度是 O(n),其中 n 是字符串的长度,因为只需要遍历每个字符串一次。空间复杂度取决于使用的数据结构,如果使用固定大小的数组,则空间复杂度为 O(1)(对于固定大小的字母表);如果使用哈希表,则空间复杂度为 O(m),其中 m 是 str1 中不同字符的数量。

3 算法实现代码

3.1 使用哈希表

如下为算法实现代码:

#include <iostream>  
#include <string>  
#include <unordered_map>  

class Solution
{
public:
	bool isPermutation(const std::string& str1, const std::string& str2)
	{
		if (str1.length() != str2.length()) {
			return false; // 如果长度不同,则它们不可能是排列  
		}

		// 使用哈希表来统计字符出现次数  
		std::unordered_map<char, int> charCount;

		// 填充哈希表,统计str1中每个字符的出现次数  
		for (char c : str1) {
			charCount[c]++;
		}

		// 遍历str2,并在哈希表中减少对应字符的计数  
		for (char c : str2) {
			if (charCount[c] == 0) {
				return false; // 如果字符在str2中存在但在str1中不存在,返回false  
			}
			charCount[c]--;
		}

		// 检查哈希表中是否还有计数不为0的字符  
		for (const auto& pair : charCount) {
			if (pair.second != 0) {
				return false; // 如果还有计数不为0的字符,则它们不是排列  
			}
		}

		return true; // 所有检查都通过,它们是排列  
	}
};

上面代码首先检查两个字符串的长度是否相等,如果不等,则它们不可能是排列。接着,使用 std::unordered_map(哈希表)来统计 str1 中每个字符的出现次数。然后,遍历 str2,并在哈希表中相应减少字符的计数。如果在遍历 str2 的过程中发现某个字符的计数已经为 0,或者某个字符在 str1 中存在但在 str2 中不存在,则返回 false。最后,检查哈希表中是否还有任何非零的计数,如果有,则返回 false,否则返回 true,表示两个字符串是排列。

调用上面的算法,并得到输出:

int main() 
{
	Solution ss;

	std::string str1, str2;

	// 测试用例1  
	str1 = "abc";
	str2 = "abc";
	std::cout << "Is \"" << str1 << "\" a permutation of \"" << str2 << "\"? "
		<< (ss.isPermutation(str1, str2) ? "Yes" : "No") << std::endl;

	// 测试用例2  
	str1 = "abc";
	str2 = "cab";
	std::cout << "Is \"" << str1 << "\" a permutation of \"" << str2 << "\"? "
		<< (ss.isPermutation(str1, str2) ? "Yes" : "No") << std::endl;

	// 测试用例3  
	str1 = "";
	str2 = "";
	std::cout << "Is \"" << str1 << "\" a permutation of \"" << str2 << "\"? "
		<< (ss.isPermutation(str1, str2) ? "Yes" : "No") << std::endl;

	// 测试用例4  
	str1 = "abcdefg";
	str2 = "abc";
	std::cout << "Is \"" << str1 << "\" a permutation of \"" << str2 << "\"? "
		<< (ss.isPermutation(str1, str2) ? "Yes" : "No") << std::endl;

	// 测试用例5  
	str1 = "abc, 12&def";
	str2 = "c,12 &abdef";
	std::cout << "Is \"" << str1 << "\" a permutation of \"" << str2 << "\"? "
		<< (ss.isPermutation(str1, str2) ? "Yes" : "No") << std::endl;

	// 测试用例6  
	str1 = "abcabcabc";
	str2 = "abcabcabc";
	std::cout << "Is \"" << str1 << "\" a permutation of \"" << str2 << "\"? "
		<< (ss.isPermutation(str1, str2) ? "Yes" : "No") << std::endl;

	return 0;
}

上面代码的输出为:

Is "abc" a permutation of "abc"? Yes
Is "abc" a permutation of "cab"? Yes
Is "" a permutation of ""? Yes
Is "abcdefg" a permutation of "abc"? No
Is "abc, 12&def" a permutation of "c,12 &abdef"? Yes
Is "abcabcabc" a permutation of "abcabcabc"? Yes

3.2 使用排序算法

可以使用排序算法来检查两个字符串是否是彼此的排列。如果两个字符串是彼此的排列,那么它们包含相同的字符(不考虑顺序),因此,如果将它们排序,排序后的字符串应该是相同的。

如下为算法实现代码:

#include <iostream>  
#include <string>  
#include <algorithm> // 为了使用sort函数 

class Solution
{
public:
	bool isPermutation(const std::string& str1, const std::string& str2)
	{
		if (str1.length() != str2.length()) {
			return false; // 长度不同的字符串不可能是排列  
		}

		// 创建两个字符串的副本,以便排序它们而不改变原始字符串  
		std::string sortedStr1 = str1;
		std::string sortedStr2 = str2;

		// 对两个字符串进行排序  
		std::sort(sortedStr1.begin(), sortedStr1.end());
		std::sort(sortedStr2.begin(), sortedStr2.end());

		// 比较排序后的字符串是否相同  
		return sortedStr1 == sortedStr2;
	}
};

在这个实现中,首先检查两个字符串的长度是否相等。如果不等,则它们不可能是排列。然后创建两个字符串的副本并对它们进行排序。最后比较排序后的字符串是否相同。如果相同,则原始字符串是彼此的排列。

这个算法的时间复杂度主要由排序算法决定,通常是 O(n log n),其中 n 是字符串的长度。空间复杂度是 O(log n)(对于比较排序算法如快速排序或归并排序)或 O(n)(对于原地排序算法如堆排序)。

4 测试用例

以下是针对上面算法的测试用例,确保覆盖各种情况:

(1)两个长度相同且字符种类和数量都相同的字符串:

  • 字符串1:“abc”
  • 字符串2:“abc”
  • 预期输出:true

(2)两个长度相同但字符顺序不同的字符串:

  • 字符串1:abc
  • 字符串2:cab
  • 预期输出:true

(3)两个空字符串:

  • 字符串1:(空字符串)
  • 字符串2:(空字符串)
  • 预期输出:true

(4)一个长字符串和一个短字符串:

  • 字符串1:abcdefg
  • 字符串2:abc
  • 预期输出:false

(5)包含特殊字符的字符串:

  • 字符串1:abc, 12&def
  • 字符串2:c,12 &abdef
  • 预期输出:true

(6)包含重复字符的字符串:

  • 文本串:abcabcabc
  • 子串:aaabbbccc
  • 预期输出:true
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值