面试题 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 |