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

一、题目描述

原题连接:面试题 01.01. 判定字符是否唯一 - 力扣(LeetCode)

题目描述:

实现一个算法,确定一个字符串 s 的所有字符是否全都不同。

示例 1:

输入: s = "leetcode"
输出: false 
示例 2:

输入: s = "abc"
输出: true

二、解题

方法1:暴力解法

思路分析:

  如果不追求时间复杂度,几乎任何题都可以靠枚举解决。这里直接两层for循环就可以解决了,思路很简单,这里就不赘述了。

时间复杂度O(N^2)

方法2:位运算

思路分析:

这道题是面试题,如果只是写出暴力解法的话,可能在面试官眼里就只有五十分左右的水平,这显然不是面试想要考察的主要内容。

这里已经明确了字母是'a'到'z',而且不使用额外的数据结构会更加分,所以我们就排除了首先想到的哈希表以及数组等。既然不能使用额外数据结构,那么往往都是位运算的操作了。

‘a’到‘z’有26个字母,而int是32个bit位,所以我们可以用一个int去表示‘a’到‘z’26个字母。

将a表示为00...001,b表示为00...010,c表示为00...100,以此类推。

题目要求的是不能有重复字母,否则返回false。所以我们先要定义一个sum统计目标字母之和,还有一个move——表示1往左移 目标字符与'a'之差 个位。如果有重复字符的话,那么sum&move就会不等于0,我们就返回false,不然sum就加上move,继续查看下一位。

我们以"abca"为例子讲解一下

首先sum为0,move为0001<<0,sum&move不为0,sum+=move,sum为0001

sum为0001,move为0001<<1==0010,sum&move不为0,sum+=move,sum为0011

sum为0011,move为0001<<1==0100,sum&move不为0,sum+=move,sum为0111

sum为0111,move为0001<<1==1000,sum&move为0,有重复字符,返回true。

代码实现

bool isUnique(char* astr){
    int sum=0;
    int move=0;
    while(*astr)
    {
         move=(1<<( (int)(*astr-'a') ) );
        if((sum&move)!=0)
        return false;

        sum+=move;
        astr++;
    }
    return true;
}

时间复杂度O(N)

三、总结

 把字符串中每个字符转化为一个二进制数,转化方法为1向左N位的位运算,N为这个字符和字符‘a'的距离;

例如 Na = 0,Nb=1,Nc = 2...a = 1<<0 = 1 ,b = 1<<1 = 10, c = 1<<2 = 100..;

所以,每个字符串对应位置为1;

这种情况下,如果当前字符如果曾经出现过,也就是其中某一位对应位数的值为1,就意味着曾经出现,返回False;

否则,如果没有出现过,那么通过|或运算,把这一位的值改写为1;

例如 'abca' : a= 1,b=10,c=100,前三次结果mark为111,最后一次111与001有相同符合条件,返回False

虽然不算很难得题目,但是这道题带给我们的启发也是很多的,希望大家都能有所收获!

希望大家三连一下,我也会继续努力更新下去!

你可能感兴趣的:(LeetCode刷题之路,leetcode,算法,c++,c语言,数据结构)