【九章斩题录】Leetcode:判定字符是否唯一(C/C++)

     精品题解  《九章斩题录》   猛戳订阅


面试题 01.01. 判定字符是否唯一

【九章斩题录】Leetcode:判定字符是否唯一(C/C++)_第1张图片

✅ 模板:C语言

class Solution {
public:
    bool isUnique(string astr) {

    }
};

思考:《程序员面试金典》里的题,这题和剑指Offer的 "数组中重复的数字" 几乎一模一样啊,只是重复的数字变成了重复的字符,判断 "重复" 和判断 "是否唯一" 在这里实际上是一样的。


「 法一 」暴力大法

思路:用两个 for 暴力,外层 for 依次选定一个锚点,然后内层 for 从锚点下一个位置开始找。找到相同的就说明不是唯一的,我们返回 false。如果循环结束仍然没找到,那就说明字符都是唯一的,返回 true。优点就是简单,但时间复杂度是 O(n^2)

【九章斩题录】Leetcode:判定字符是否唯一(C/C++)_第2张图片

代码演示:

class Solution {
public:
    bool isUnique(string astr) {
        for (int i = 0; i < astr.size(); i++) {
            for (int j = i + 1; j < astr.size(); j++) {
                if (astr[i] == astr[j]) {
                    return false;
                }
            }
        }
        return true;
    }
};

运行结果如下:

【九章斩题录】Leetcode:判定字符是否唯一(C/C++)_第3张图片

「 法二 」哈希无序集

思路:既然要找是否唯一,很容易想到用哈希,这里可以利用 unordered_set。既然要找重复的元素,本质上就是看是否 unique (唯一),这让我们想到了数学中的集合,可以利用 "集合元素是唯一的" 的特点。拿题目中的例子来说,如果我们以集合的方式存储一遍该字符串,那么如果在存储过程中出现重复,那么不就找到我们想要的 target 了吗?

我们知道,set 的底层是红黑树,时间复杂度为 ,而 unordered_set 的期望复杂度能够达到 。所以这里我们选择使用 unordered_set。

unordered_set 我们仍然是用 count 来检查是否在 hash 表内,用 insert 来插入。

代码演示:

class Solution {
public:
    bool isUnique(string astr) {
        unordered_set u_set;
        for (int i = 0; i < astr.size(); i++) {
            if (u_set.count(astr[i]) == 0) {
                u_set.insert(astr[i]);
            }
            else {
                return false;
            }
        }
        return true;
    }
};

运行结果如下:

【九章斩题录】Leetcode:判定字符是否唯一(C/C++)_第4张图片

「 法三 」排序 + 遍历

思路:我们可以尝试 "排序 + 遍历" 的方法,先对字符串进行排序,因为排序后,相同的字符肯定是紧挨着的,如此一来,我们只需要一层循环遍历一遍排序完的字符串即可。遍历时将下标  设置从 1 开始,依次和  下标的元素做对比即可。排序可以直接调 sort。

代码演示:

class Solution {
public:
    bool isUnique(string astr) {
        sort(astr.begin(), astr.end());
        for (int i = 1; i < astr.size(); i++) {
            if (astr[i - 1] == astr[i]) {
                return false;
            }
        }
        return true;
    }
};

「 法四 」st 数组

思路:在遍历字符串时,使用 st 数组记录当前字符,如果该字符存在则说明该字符不是唯一。

class Solution {
public:
    bool isUnique(string astr) {
        bool st[10000] = { 0 };   // 初始化为0
        for (int i = 0; i < astr.size(); i++) {
            if (st[ astr[i] ] != 0) {   // 如果不为0
                return false;
            }
            st[ astr[i] ] = 1;    // 设置为1
        }
        return true;
    }
};

「 法五 」位运算

思路:题目说不使用额外数据结构加大分,好好好。

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

 [ 笔者 ]   王亦优
 [ 更新 ]   2023.
❌ [ 勘误 ]   /* 暂无 */
 [ 声明 ]   由于作者水平有限,本文有错误和不准确之处在所难免,
              本人也很想知道这些错误,恳望读者批评指正!

参考资料 

C++reference[EB/OL]. []. http://www.cplusplus.com/reference/.

Microsoft. MSDN(Microsoft Developer Network)[EB/OL]. []. .

百度百科[EB/OL]. []. https://baike.baidu.com/.

牛客网. 剑指offer 题解 [EB/OL]. []. https://www.nowcoder.com/exam/oj/ta?tpId=13.

你可能感兴趣的:(九章斩题录,哈希算法,算法)