如何在用户输入的字符串中找到第一个重复的字符?

时间:2018-07-30 14:40:04

标签: c

如何找到字符串中的第一个重复字符? 如果输入为“ abcdexyzbwqpoolj,则输入 输出应为b

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
    int i,j;
char str[1000];

scanf("%s",str);//input the string
for( i=0;i<strlen(str);i++)
{
    for(j=i+1;j<strlen(str);j++)
    {
        if(str[i]==str[j])//compare
        {
            printf("%c",str[i]);
        }
    }
}
}

这将打印所有重复字符,但我只想打印第一个字符。请更正此代码。

4 个答案:

答案 0 :(得分:1)

如果要退出您所在的函数(包括它是main函数),则只需执行return

if(str[i]==str[j])//compare
{
    printf("%c",str[i]);
    return 0;
}

如果您在循环后的代码中需要执行同一函数,则此方法将无效。您可以使用goto退出嵌套循环。打破嵌套循环是goto的几种可接受用法之一:

for( i=0;i<strlen(str);i++)
{
    for(j=i+1;j<strlen(str);j++)
    {
        if(str[i]==str[j])//compare
        {
            printf("%c",str[i]);
            goto done;
        }
    }
}
done:
    ;

如果这是非嵌套循环,请使用break

答案 1 :(得分:1)

一个简单的解决方案是在找到第一个重复字符后立即返回:

#include <stdio.h>

int main()
{
  int i,j;
  char str[1000];

  scanf("%s",str); // input the string
  for (i = 0; str[i] != '\0'; i++)
  {
    for (j = i + 1; str[j] != '\0'; j++)
    {
      if (str[i] == str[j]) // compare
      {
        printf("%c", str[i]);
        return 0;
      }
    }
  }
}

答案 2 :(得分:1)

可以使用另一个数组对出现的字符进行计数。匹配是计数不再为零时。在abcdedcba中,它将报告d是第一个匹配的字符。

#include <stdio.h>

int main ( void) {
    char all[256] = { 0};
    char text[1000] = { 0};
    int comp = 0;
    if ( fgets ( text, sizeof text, stdin)) {
        for ( comp = 0; text[comp]; ++comp) {
            if ( all[(unsigned char)text[comp]]) {
                printf ( "matched \'%c\'\n", text[comp]);
                break;
            }
            all[(unsigned char)text[comp]]++;
        }
    }
    else {
        fprintf ( stderr, "fgets EOF\n");
    }
    if ( !text[comp]) {
        printf ( "no matched characters\n");
    }
    return 0;
}

答案 3 :(得分:1)

简单的代码解决方案

以下是基于commented首先Eugene Sh.的提示的线性时间答案(不差于此):

#include <limits.h>
#include <stdio.h>

int main(void)
{
    char str[1000];
    char map[UCHAR_MAX + 1] = { 0 };

    if (scanf("%999s", str) == 1)
    {
        for (int i = 0; str[i] != '\0'; i++)
        {
            int n = (unsigned char)str[i];
            if (map[n]++ != 0)
            {
                printf("first duplicate: %c\n", str[i]);
                break;
            }
        }
    }
    return 0;
}

这将记录map数组中已经看到的每个字节的记录,并在找到重复的字符(不仅仅是字母)时中断循环。这有很多优点,包括:

  • 线性(O(N))执行时间
  • 不中断嵌套循环(因为没有嵌套)
  • 如果开头有重复项,则不扫描整个输入
  • 在循环条件中不使用strlen()(如果优化程序没有检测到strlen()只能被调用一次,这可能会使原始代码比O(N²)更复杂)

它的主要缺点是,如果找不到重复项,它什么也不会说。如果那是不可接受的,则添加一个标志,该标志最初为false,在执行break时设置为true,并在循环后进行测试。或者,代码可以使用break代替return 0;,在打印完重复项后退出程序,并可以打印“无重复项”消息并最终失败退出。

O(N)线性vs O(1)恒定搜索时间

由于总搜索空间为255字节(因为不将空字节计为可重复字符),因此我们有理由认为,线性时间不是O(N),而是O(1)恒定时间。如果输入仅是小写的非字母,则如果输入中有27个字符,则必须重复。如果输入不是很受限制,那么在前256个字节中将有一个重复项(由于scanf()%s在第一个空白处停止读取,因此该重复数要少一些,因此不能可以重复的任何空白字符)。 Big-O表示渐近运行时,并且27和256都不大,因此可以认为运行时为O(1)。