面试题 01.02. 判定是否互为字符重排
01.02. 判定是否互为字符重排 简单
给定两个字符串 s1
和 s2
,请编写一个程序,确定其中一个字符串的字符重新排列后,能否变成另一个字符串。
示例 1:
输入: s1 = "abc", s2 = "bca"
输出: true
示例 2:
输入: s1 = "abc", s2 = "bad"
输出: false
说明:
0 <= len(s1) <= 100
0 <= len(s2) <= 100
提示:
- 描述两个字符串是否互为字符重排的含义。现在,看看你提供的定义,你能否根据这个定义检查字符串
- 有一种解法需要O(NlogN)的时间。另一种解法需要使用一些.空间,但需要运行时间为O(N)
- 散列表有用吗
- 两个重排的字符串应该具有相同的字符,但顺序不同。你可以让它们的顺序一样吗?
解答
“重新排列后,变成另一个字符串” 根据题干提供的信息,得知
- s1 和 s2 应该长度相同
- s1 和 s2 中出现的字符的数量和类型应该相同
解法一: 自己写的,仅供参考;两次循环,标记符号,没有出现过的直接返回
public bool CheckPermutation(string s1, string s2) {
if(s1.Length!=s2.Length) // 长度不同返回false
return false;
bool isExist; // 标记字符是否在第二个字符串出现过
byte[] flags = new byte[s2.Length]; // 存储s1 在 s2中出现时的标记
foreach(char ch in s1){ // 循环s1中的字符,在s2中出现位置后标记其位置
isExist = false;
for(int i=0;i<s2.Length;i++){
if(ch==s2[i] && flags[i]==0) // 相等时且对应的标记位置为0 时,标记对应位置为 1,跳出当前循环
{
isExist=true;
flags[i] = 1;
break;
}
}
if(!isExist)
return false;
}
return true;
/*
bool[] flags = new bool[s2.Length]; // 存储s1 在 s2中出现时的标记
foreach(char ch in s1){ // 循环s1中的字符,在s2中出现位置后标记其位置
for(int i=0;i<s2.Length;i++){
if(ch==s2[i] && !flags[i]){
flags[i] = true;
break;
}
}
}
foreach(bool isExist in flags){
if(!isExist)
return false;
}
return true;
*/
}
解法2: 来自大家的结合,统计字符数,最后保证所有的字符都是 0
public bool CheckPermutationV2(string s1, string s2)
{
if (s1.Length != s2.Length)
return false;
byte[] flags = new byte[128];
for (int i = 0; i < s1.Length; i++)
{
flags[s1[i]]++;
flags[s2[i]]--;
}
for (int i = 0; i < flags.Length; i++)
{
if (flags[i] != 0)
return false;
}
return true;
}
解法三:
public bool CheckPermutationV3(string s1, string s2)
{
if (s1.Length != s2.Length)
return false;
Dictionary<char, byte> countDict = new Dictionary<char, byte>(s1.Length);
for (int i = 0; i < s1.Length; i++)
{
if (countDict.ContainsKey(s1[i]))
countDict[s1[i]]++;
else
countDict.Add(s1[i], 1);
}
for (int i = 0; i < s2.Length; i++)
{
if (countDict.ContainsKey(s2[i]))
countDict[s2[i]]--;
else
return false;
}
foreach (char curChar in countDict.Keys){
if(countDict[curChar] != 0)
return false;
}
return true;
}
总结
第二种是我目前觉得比较完善的,但是具体的需求还得看具体的分析啦。
C# 类型/关键字 | 范围 | 大小 | .NET 类型 |
---|---|---|---|
sbyte | -128 到 127 | 8 位带符号整数 | System.SByte |
byte | 0 到 255 | 无符号的 8 位整数 | System.Byte |
short | -32,768 到 32,767 | 有符号 16 位整数 | System.Int16 |
ushort | 0 到 65,535 | 无符号 16 位整数 | System.UInt16 |
int | -2,147,483,648 到 2,147,483,647 | 带符号的 32 位整数 | System.Int32 |
uint | 0 到 4,294,967,295 | 无符号的 32 位整数 | System.UInt32 |
long | -9,223,372,036,854,775,808 到 9,223,372,036,854,775,807 | 64 位带符号整数 | System.Int64 |
ulong | 0 到 18,446,744,073,709,551,615 | 无符号 64 位整数 | System.UInt64 |
nint | 取决于平台 | 带符号的 32 位或 64 位整数 | System.IntPtr |
nuint | 取决于平台 | 无符号的 32 位或 64 位整数 | System.UIntPtr |