程序员面试金典笔记

面试题01.01 判断字符串中字符是否唯一

遇到题目,先想需要考虑的情况:

  1. 字符串是ASCII字符串还是Unicode字符串?假设为ASCII。
  2. 首先得有字符串长度判定,超出长度后直接false。

思路主要是使用位向量的方法。我们可以使用一个int类型的变量(下文用checker表示)来代替长度为26的bool数组。。假设这个变量占26个bit(在多数语言中,这个值一般不止26),那么我们可以把它看成000...00(26个0),这26个bit对应着26个字符,对于一个字符c,检查对应下标的bit值即可判断是否重复。那么难点在于如何检查?这里我们可以通过位运算来完成。。首先计算出字符char离'a'这个字符的距离,即我们要位移的距离,用val表示,那么使用左移运算符1 << val则可以得到对应下标为1,其余下标为0的数,如字符char = 'c',则得到的数为000...00100,将这个数跟checker做与运算,由于这个数只有一个位为1,其他位为0,那么与运算的结果中,其他位肯定是0,而对应的下标位是否0则取决于之前这个字符有没有出现过,若出现过则被标记为1,那么与运算的结果就不为0;若之前没有出现过,则对应位的与运算的结果也是0,那么整个结果也为0。对于没有出现过的字符,我们用或运算checker |= (1 << val)将对应下标位的值置为1。

class Solution {
public:
    bool isUnique(string astr) {
        int record = 0;
        int move;
        for(auto i : astr)
        {
            move = i - 'a';
            if((record & (1 << move)) != 0)
                return false;
            else
            {
                record = record | (1 << move);
            }
        }
        return true;
    }
};

面试题01.02 判定是否互为字符重排

遇到题目,先想需要考虑的情况:

  1. 是否区分大小写?假设区分。
  2. 是否考虑空白字符?假设考虑。
  3. 若两个字符串本身长度就不同,那肯定不行。

再想怎样就满足题意呢?第一个思路肯定就是排序后看是否相同,应该能想到。

class Solution {
public:
    bool CheckPermutation(string s1, string s2) {
        sort(s1.begin(),s1.end());
        sort(s2.begin(),s2.end());
        if(s1 == s2)
            return true;
        return false;
    }
};

第二个思路,就是创建一个数组,效果类似于散列表,将每个字符映射到其出现次数,具体来说就是,第一个字符串进来就加一,第二个进来就减一,若可以重排的话,应该是正好最后为0的。且一旦出现了负值,就直接终止了。

class Solution {
public:
    bool CheckPermutation(string s1, string s2) {
        int asccii[128] = {0};
        int len1 = s1.size();
        int len2 = s2.size();
        if(len1!=len2)
            return false;
        for(int i=0;i<len1;i++) {
            asccii[s1[i]]++;
            asccii[s2[i]]--;
        }
        for(int i=0;i<128;i++)
            if(asccii[i]!=0)
                return false;
        return true;
    }
};

面试题01.03 

面试题01.04 回文排列

这里的回文排列是指把一个字符串的字母进行重新排列后,可以组成回文串。若字符串是奇数个,得有一个字母出现一次,其余的出现两次;若是偶数个,则每个字符都得出现2次。

思路一:使用散列表来统计字符的个数,然后遍历散列表以便确定出现奇数次的字符不超过一个。O(N)。

思路二:直接计数

class Solution {
public:
    bool canPermutePalindrome(string s) 
    {
        int numOfChars[128] = {0};
        for(int i = 0; i < s.size(); ++i)
        {
            numOfChars[s[i]] += 1;
        }
        int oddNum = 0;
        for(int i = 0; i < 128; ++i)
        {
            if(numOfChars[i] % 2 != 0)
            {
                if(oddNum == 0)
                    oddNum += 1;
                else
                    return false;
            }
        }
        return true;
    }
};

思路三:判断一个数是否刚好有一个比特位为1,可以通过将其减1 的结果与该数本身进行与操作,如果其结果为0,则比特位中1 刚好出现一次。

class Solution {
public:
    bool canPermutePalindrome(string s) {
        bitset<128> bits;
        for (char c : s){
            bits.flip(c);    //将第c+1位取反
        }
        return bits.none() || bits.count() == 1;
        //bit.none()返回是否没有1,bit.count()返回1的个数
    }
};

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值