题目一:在字符串中找出第一个
只出现一次
的字符。例如,字符串avbdabkd
,第一次出现的只有一个的字符为v
。
解题思路:
- 方法一:
常规思路O(n*n)的解法。
从字符串的第一个字符开始,那出来一个字符和字符串的后边的字符比较,如果存在相同的则不是出现一次的字符,如果不存在,则找到返回。效率太低,面试官肯定不会满意。
代码实现:
char firstonechar_R(char *str)
{
if (str == NULL)
return '\0';
char *cur = str;
while (*cur != '\0')
{
char* tmp = cur + 1;
while (*tmp != '\0')
{
if (*tmp != *cur)
tmp++;
else
break;
}
if (*tmp == '\0')
return *cur;
cur++;
}
return '\0';
}
- 方法二:
哈希表。
由于字符串中的每个元素都是char类型的,char类型的元素只有256中取值,我们可以开辟一个256大小的数组,把每个字符的值映射到哈希表上(把每个字符的ASCII码值当做数组下标),首先把数组初始化0,遍历字符串,遇到一个字符在相应的位置加1(实现一个计数器)。最后,只要在遍历一遍字符串查看相对应位置等于1的即可。
代码实现:
char FirstOneChar(const char *str)
{
assert(str);
//1.初始化哈希表为0
int hashtable[tablesize];//char是1个字节,有256中可能取值
for (int i = 0; i < tablesize; i++)
{
hashtable[i] = 0;
}
//2.遍历字符串,统计次数
const char* cur = str;
while (*cur != '\0')
{
hashtable[*cur]++;
cur++;
}
//3.遍历字符串,查找第一个出现1次的字符
cur = str;
while (*cur != '\0')
{
if (hashtable[*cur] == 1)
return *cur;
cur++;
}
return '\0';
}
以下为本题的扩展题目:
题目二:定义一个函数,删除第一个字符串出现在第二个字符串中的所有字符。例如str="i am stu"
,str2="am "
,则输出结果为istu
。
解题思路:
- 1.和上题思路一样,将str2映射到哈希表中(存在将那个位置置为1,不用计数)
- 2.遍历一遍str1,在哈希表中查找(O(1)),查找到既删除
- 3.如果不用考虑删除,时间复杂度为O(n)。
参考代码:
/*******************************************/
//扩展:删除第一个字符串在第二个字符串中的所有字符
//删除一个字符串指定位置的字符(pos为要删除字符的指针)
void Remove(char str[], char *pos)
{
if (str == NULL || pos == NULL)
return;
int index = pos - str;
int len = strlen(str);
for (int i = index; i < len; i++)
{
*(str + i) = *(str + i + 1);
}
}
//删除第一个字符串在第二个字符串中的所有字符
void EraseFisrtStrInSencond(char str1[], const char *str2)
{
if (str1 == NULL || str2 == NULL)
return;
//1.初始化哈希表
unsigned int hashtable[tablesize];
for (int i = 0; i < tablesize; i++)
{
hashtable[i] = 0;
}
//2.将str2放入哈希表中
char *cur = str2;
while (*cur != '\0')
{
hashtable[*cur] = 1;
cur++;
}
//遍历str1,如果存在哈希表中,则删除
cur = str1;
while (*cur != '\0')
{
//删除了一个字符之后,必须先将cur向前移动一位
if (hashtable[*cur] == 1)
{
Remove(str1, cur);
cur--;
}
cur++;
}
}
题目三:定义一个函数,删除一个字符串中所有重复的字符。例如:hansaon
,输出结果为hanso
解题思路:
- 1.依旧根据哈希表解决这个问题。
- 2.首先将哈希表中的所有元素设置为0(不存在)
- 3.遍历字符串,如果字符存在与哈希表,则删除;不存在,则把对于的位置设置为存在。
代码实现:
//删除一个字符串指定位置的字符(pos为要删除字符的指针)
void Remove(char str[], char *pos)
{
if (str == NULL || pos == NULL)
return;
int index = pos - str;
int len = strlen(str);
for (int i = index; i < len; i++)
{
*(str + i) = *(str + i + 1);
}
}
//删除字符串中重复的字符(hansaon-->hanso)
void RemoveReChar(char str[])
{
if (str == NULL)
return;
//1.初始化哈希表
unsigned int hashtable[tablesize];
for (int i = 0; i < tablesize; i++)
{
hashtable[i] = 0;
}
//2.遍历一遍字符串,如果存在与哈希表,则删除,
//不存在,则把对于的位置设置为存在
char *cur = str;
while (*cur != '\0')
{
if (hashtable[*cur] == 0)
hashtable[*cur] = 1;
else
Remove(str, cur);
cur++;
}
}
题目四:在英语中,如果两个单词出现的字母相同,并且每个字母出现的次数也相同,那么称这两个词为变位词。例如,单词evil
和单词live
、silent
和listen
都互为变位词。
解题思路:
- 1.将哈希表初始化为0
- 2.扫描一遍第一个字符串,对每个出现的字符串进行计数
- 3.扫描第二个字符串,如果在哈希表中存在,对应位置减去1;如果不存在,则直接不是变位词
- 4.判断哈希表每一位是否为0,为0说明是变位词,不为0,则不是。
代码实现:
//判断两个单词是否为变位词(是返回1,不是返回0)
int IsAlertWord(const char* word1,const char *word2)
{
if (word1 == NULL || word2 == NULL)
return 0;
//1.初始化哈希表
unsigned int hashtable[tablesize];
int i = 0;
for (; i < tablesize; i++)
{
hashtable[i] = 0;
}
//2.将word2放入哈希表中,并计数
const char* cur = word2;
while (*cur != '\0')
{
hashtable[*cur]++;
cur++;
}
//3.扫描word1,在对应位置减去出现的次数
cur = word1;
while (*cur != '\0')
{
//对应位置等于0,说明两个单词的字母都不相同
if (hashtable[*cur] == 0)
return 0;
//对应位置大于0,减去在word1中出现的次数
else if (hashtable[*cur] > 0)
hashtable[*cur]--;
cur++;
}
//4.判断哈希表的每一位是否为0
for (i = 0; i < tablesize; i++)
{
if (hashtable[i] != 0)
{
return 0;
}
}
return 1;
}
上述几个题目都是基于哈希表的操作,如果对哈希表的各个操作和概念不清楚的朋友可以看我的另几篇博客: