九度OJ-题目1283:第一个只出现一次的字符

题目链接地址:

九度OJ-题目1283:第一个只出现一次的字符


题目描述:
在一个字符串(1<=字符串长度<=10000,全部由大写字母组成)中找到第一个只出现一次的字符。

输入:
输入有多组数据
每一组输入一个字符串。

输出:
输出第一个只出现一次的字符下标,没有只出现一次的字符则输出-1。

样例输入:
ABACCDEFF
AA

样例输出:
1
-1


解题思路:

这道题我最开始的想法是排序,然后从头到尾遍历排好序的序列,找出第一个只出现一次的字符,这种算法的时间复杂度为O(logn*n)。后来经赵博指点,其实根本不用排序。因为字符串全部由大写字母组成,所以只要遍历一次字符串,然后记录下每个大写字母出现的次数和该大写字母第一次出现在字符串中的下标即可,这种算法的时间复杂度是O(n)。
举个栗子,对于测试用例:ABACCDEFF
遍历一次该字符串后,可以得到以下信息:
A在字符串中出现了2次,第一次出现的下标是0;
B在字符串中出现了1次,第一次出现的下标是1;
C在字符串中出现了2次,第一次出现的下标是3;
D在字符串中出现了1次,第一次出现的下标是5;
E在字符串中出现了1次,第一次出现的下标是6;
F在字符串中出现了2次,第一次出现的下标是7;
其余大写字母均未在字符串中出现过。
所以可以得知,该字符串第一个只出现一次的字符是B。
AC代码如下:

#include
#include
#define MAX 10000
// 输入的字符串
char inputStrings[MAX];
// 定义的字母结构体
typedef struct Node
{
  int index;         // 字母在字符串第一次出现时所对应的下标
  int times;         // 字母在字符串中出现的次数
}LetterNode;
 
/**
* 初始化字母结点
* @param letterNode[]  用于保存大写字母信息的结构体数组
* @return void
*/
void initLetterNode(LetterNode letterNode[])
{
  int i;
  for(i = 0;i < 26;i++)
  {
      letterNode[i].index = 10001;
      letterNode[i].times = 0;
  }
}
 
/**
* 统计每个字母在字符串中出现的次数和第一次出现的下标
* @param inputString[]  输入的字符串
* @param len  输入字符串的长度
* @param letterNode[]  用于保存每个字母出现次数和第一次出现下标的数组
* @return void
*/
void countTimes(char inputString[],int len,LetterNode letterNode[])
{
  int i = 0;
  int letter;
  while(i < len)
  {
      letter = inputString[i] - 'A';        // 将字符串中的大写字母转换为LetterNode数组对应的下标
      if(0 == letterNode[letter].times)
      {
          letterNode[letter].index = i;     // 记录字母在字符串中第一次出现的下标
      }
      letterNode[letter].times++;
      i++;
  }
}
 
/**
* 寻找字符串中第一个只出现一次的字母
* @param letterNode[]  用于保存每个字母出现次数和第一次出现下标的数组
* @return firstIndex 返回第一个只出现一次的字符下标
*/
int getFirstOnceLetterIndex(LetterNode letterNode[])
{
  int firstIndex = -1;
  int i,j;
  LetterNode tempNode;
  // 对LetterNode数组按照index域的大小从小到大依次进行排序
  for(i = 0;i < 26;i++)
  {
      for(j = i;j < 26;j++)
      {
        if(letterNode[j].index < letterNode[i].index)
        {
           tempNode = letterNode[i];
           letterNode[i] = letterNode[j];
           letterNode[j] = tempNode;
        }
      }
  }
  // 找出第一个只出现一次的字符在字符串中的下标
  for(i = 0;i < 26;i++)
  {
      if(1 == letterNode[i].times)
      {
          firstIndex = letterNode[i].index;
          break;
      }
  }
  return firstIndex;
}
 
int main()
{
    LetterNode letterNode[26];   // 存储26个大写字母的信息
    int len;
    int firstOnceIndex;
    while(EOF != scanf("%s",inputStrings))
    {
       initLetterNode(letterNode);
       len = strlen(inputStrings);
       countTimes(inputStrings,len,letterNode);
       firstOnceIndex = getFirstOnceLetterIndex(letterNode);
       printf("%d\n",firstOnceIndex);
    }
    return 0;
}
 
/**************************************************************
    Problem: 1283
    User: blueshell
    Language: C++
    Result: Accepted
    Time:10 ms
    Memory:1032 kb
****************************************************************/


你可能感兴趣的:(九度OJ-剑指Offer)