算法 64式 16、字符串算法整理

1算法思想

 

2 字符串系列

类别-编号

题目

来源

1

替换空格

请事先一个函数,把字符串中的每个空格替换成"%20"。例如

例如

输入:

We are happy.

输出:

We%20are%20happy.

 

 

剑指offer

https://blog.csdn.net/qingyuanluofeng/article/details/39092165

关键:

1 第一次遍历字符串统计空格数,计算新的字符串长度

2 采用p1指向原来结尾,p2直线新结尾,然后不遇见空格时,依次复制,

  遇见空格,p1不动,p2连减三次,每次减的时候直接赋值

  最终p1与p2会相等

3 #define MAXSIZE 500000//注意别用太小,否则内存溢出

 

 

#define MAXSIZE 500000//注意别用太小,否则内存溢出

 

char* replaceBlank(char* str,int len)

{

       if(!str || len <= 0)

       {

              return NULL;

       }

       int iBlankNum = 0;

       int iOriginLen = 0;

       for(int i = 0 ; '\0' != str[i]; i++)//统计空格数

       {

              if(' ' == str[i])

              {

                     iBlankNum++;

              }

              iOriginLen++;

       }

       int iNewLen = iOriginLen + 2 * iBlankNum;

       if(iNewLen > len)

       {

              return NULL;

       }

       int iOriginIndex = iOriginLen;

       int iNewIndex = iNewLen;

       //while(iOriginIndex >= 0 && iNewIndex >= iOriginIndex)//开始逆序遍历,拷贝和替换字符

       while(iOriginIndex >= 0)

       {

              if(' ' != str[iOriginIndex])

              {

                     str[iNewIndex--] = str[iOriginIndex];

              }

              else

              {

                     str[iNewIndex--] = '0';

                     str[iNewIndex--] = '2';

                     str[iNewIndex--] = '%';

              }

              iOriginIndex--;

       }

       return str;

}

 

void process()

{

       char str[MAXSIZE];

       while(NULL != gets(str))//对于用空格分开的字符串必须用gets来接受

       {

       printf("%s\n",replaceBlank(str,MAXSIZE));

       }

}

2

第一个只出现一次的字符

在字符串中找出第一个只出现一次的字符。如输入"abaccdeff",则输出'b'

 

题目描述:

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

输入:

输入有多组数据

每一组输入一个字符串。

输出:

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

样例输入:

ABACCDEFF

AA

样例输出:

1

-1

剑指offer

https://blog.csdn.net/qingyuanluofeng/article/details/39187793

分析:

直接对每个字符统计次数,用哈希做遍历,应该时间复杂度为O(n)。

寻找第一次出现的次数为1的字符时,我们按照字符顺序来遍历

 

关键:

1 for(int i = 0 ; str[i] != '\0' ; i++)//注意,在寻找第一次出现的次数为1的字符时,我们通过字符串来遍历

 

const int MAXSIZE = 257;//char 是1个字节,256个字符,故选取哈希表的大小为256

 

int firstAppear1Times(char* str)

{

 int iHash[MAXSIZE];

 memset(iHash,0,sizeof(iHash));

 for(int i = 0 ; str[i] != '\0' ; i++)

 {

  iHash[(int)str[i]]++;

 }

 for(int i = 0 ; str[i] != '\0' ; i++)//注意,在寻找第一次出现的次数为1的字符时,我们通过字符串来遍历

 {

  if(iHash[(int)str[i]] == 1)

  {

   return i;

  }

 }

 return -1;

}

 

void process()

{

 char str[10001];

 while(EOF != scanf("%s",str))

 {

  printf("%d\n",firstAppear1Times(str));

 }

}

 

3

反转单词顺序:

输入一个英文句子,反转句子中单词的顺序,但单词内字符的顺序不变,为了简单起见,标点符号和普通字母

一样处理。例如输入字符串"I am a student.",则输出"student. a am I"。

 

输入:

每个测试案例为一行,表示一句英文句子。

我们保证一个句子的单词数不会超过600,每个单词的长度也不会超过30。但是需要注意的是Fish是个不拘小节的人,有时候两个单词中间可能会有很多空格。为了方便起见,你可以认为一行的字符总数不会超过50000个,标点符号可以和普通字母一样处理。

输出:

对应每个测试案例,把翻转后的正确的句子单独输出一行。

样例输入:

student. a am I

I'm a Freshman and I like JOBDU!

样例输出:

I am a student.

JOBDU! like I and Freshman a I'm

剑指offer

https://blog.csdn.net/qingyuanluofeng/article/details/39188019

 

思路:

首先将整个字符串完全反转,然后对单个单词利用空格做切分后反转

 

关键:

1 首先将整个字符串完全反转,然后对单个单词利用空格做切分后反转

2  while(*pEnd != '\0')

 {

  pEnd++;

 }

 --pEnd;//注意这里必须要用pEnd指向最后一个字符,因此需要减减

3 pBeg = pEnd = str;//注意,这里用给pBeg和pEnd重新赋值,否则沿用上次计算的值就会出错

4 if(*pBeg == ' ')//如果遇到空格,就令起点指针和末尾指针,均开始累加

  {

   pBeg++;

   pEnd++;

  }

5 else if(*pEnd == ' ' || *pEnd == '\0')//如果末尾指针走到下一个空白处或者字符末尾,那么,就可以反转单词了

  {

   reverseStr(pBeg,--pEnd);//牛逼,这里注意将pEnd向前遍历,确保是单词的最后一个字符

   pBeg = ++pEnd;//牛逼,这里实际上让pBeg和pEnd同步了,并且都指向空白字符处

6   else//其余普通情况,只需要累加末尾指针

  {

   pEnd++;

  }

 

 

代码

const int MAXSIZE = 1e4 + 1;

 

void reverseStr(char* sBeg,char* sEnd)

{

 if(!sBeg || !sEnd)

 {

  return;

 }

 char ch;

 while(sBeg < sEnd)//交换两个字符,注意这里是sBeg < sEnd,而不是sBeg != sEnd

 {

  ch = *sBeg;

  *sBeg = *sEnd;

  *sEnd = ch;

  sBeg++;

  sEnd--;

 }

}

 

char* reverseSentence(char* str)

{

 char* pBeg = str,*pEnd = str;

 int iIndex = 0 ;

 while(*pEnd != '\0')

 {

  pEnd++;

 }

 --pEnd;//注意这里必须要用pEnd指向最后一个字符,因此需要减减

 //反转整个句子

 reverseStr(pBeg,pEnd);

 pBeg = pEnd = str;//注意,这里用给pBeg和pEnd重新赋值,否则沿用上次计算的值就会出错

 //printf("%s\n",str);

 while(*pBeg != '\0')//开始对每个句子中的每个单词进行反转

 {

  if(*pBeg == ' ')//如果遇到空格,就令起点指针和末尾指针,均开始累加

  {

   pBeg++;

   pEnd++;

  }

  else if(*pEnd == ' ' || *pEnd == '\0')//如果末尾指针走到下一个空白处或者字符末尾,那么,就可以反转单词了

  {

   reverseStr(pBeg,--pEnd);//牛逼,这里注意将pEnd向前遍历,确保是单词的最后一个字符

   pBeg = ++pEnd;//牛逼,这里实际上让pBeg和pEnd同步了,并且都指向空白字符处

  }

  else//其余普通情况,只需要累加末尾指针

  {

   pEnd++;

  }

 }

 return str;

}

 

//注意:反转整个句子,我们的思路是找到当前空白字符的下一个字符,以及下一个空白字符的前一个字符,然后

//把这段进行反转

void process()

{

 char str[MAXSIZE];

 while(NULL != gets(str))

 {

  printf("%s\n",reverseSentence(str));

 }

}

4

把字符串转换成整数

输入:

输入可能包含多个测试样例。

对于每个测试案例,输入为一个合法或者非法的字符串,代表一个整数n(1<= n<=10000000)。

输出:

对应每个测试案例,

若输入为一个合法的字符串(即代表一个整数),则输出这个整数。

若输入为一个非法的字符串,则输出“My God”。

样例输入:

5

-5

+8

样例输出:

5

-5

8

剑指offer

https://blog.csdn.net/qingyuanluofeng/article/details/39188209

关键:

1   if(g_status == Valid)//关键我们通过全局变量来判定输入是否合法

2 g_status = Invalid;//注意设置全局变量

3   if(*str == '+')//加号容易遗漏

  {

   str++;

  }

4   if(*str != '\0')//注意,凡是看到字符指针累加,就必须判结束

5 if(*str <= '9' && *str >= '0')//判断是不是合法输入

6  if(*str == '\0')//能够走到末尾,说明是正确的

 {

  g_status = Valid;

 }

7 long long atoi_core(const char* str,bool isNegative)//注意这里返回值为long long

 

代码

#define MININT 0xffffffff

#define MAXSIZE 1024

 

enum Status{Valid = 0,Invalid};

int g_status = Valid;

 

long long atoi_core(const char* str,bool isNegative)//注意这里返回值为long long

{

 long long lNum = 0;

 while(*str != '\0')

 {

  if(*str <= '9' && *str >= '0')//判断是不是合法输入

  {

   int iFlag = isNegative ? -1 : 1;

   lNum = lNum*10 + iFlag*(*str - '0');

   if( (!isNegative && lNum > 0x7fffffff) ||(isNegative &&  lNum < (signed int)0x80000000 ) )//判断溢出

   {

    lNum = 0;

    break;

   }

   str++;

  }

  else

  {

   lNum = 0;

   break;

  }

 }

 if(*str == '\0')//能够走到末尾,说明是正确的

 {

  g_status = Valid;

 }

 return lNum;

}

 

int m_atoi(const char* str)

{

 g_status = Invalid;//注意设置全局变量

 long long lNum = 0;

 bool isNegative = false;

 if(str && *str != '\0')

 {

  if(*str == '+')//加号容易遗漏

  {

   str++;

  }

  else if(*str == '-')

  {

   str++;

   isNegative = true;

  }

  if(*str != '\0')//注意,凡是看到字符指针累加,就必须判结束

  {

   lNum = atoi_core(str,isNegative);

  }

 }

 return (int)lNum;

}

5

字符串移位包含的问题:

给定两个字符串s1和s2,要求判定s2是否能够被s1做循环移位得到的字符串包含,例如给定s1 = AABCD和s2 = CDAA,返回true;给定s1 = ABCD,s2 = ACBD,返回false

 

输入:

AABCD CDAA

ABCD ACBD

输出:

Yes

No

编程之美

https://blog.csdn.net/qingyuanluofeng/article/details/47187523

分析与解法:

解法1:

最直接的方法是对s1进行循环移位,再进行字符串包含的判断,从而遍历其所有的可能性

解法2:

对循环移位之后的结果进行分析:

s1 = ABCD,先对s1进行循环移位之后结果如下所示:

ABCD->BCDA->CDAB->DABC->ABCD

假设我们呢把前面移走的数据进行保留,发现下面的规律:

ABCD->ABCDA->ABCDAB->ABCDABC->ABCDABCD

可以看出对s1做循环移位所得到的字符串都将是字符串s1s1的子字符串。如果s2可以由s1循环移位得到,那么s2一定在s1s1上,我们只需要一次strstr函数得到结果

string.h

char* strstr()const char* str1,const char* str2):指向字符串str2首次出现在str1中的位置,如果没有返回NULL

但是这种方法会有一个bug,例如:s1:"A",s2:"AA",因此需要判断两个字符串的长度

 

关键:

1 strcat(strDouble,str);//形成str1str1的形式

2 if(strstr(strDouble,strSub))//char* strstr()const char* str1,const char* str2):指向字符串str2首次出现在str1中的位置,如果没有返回NULL

3 假设我们呢把前面移走的数据进行保留,发现下面的规律:

ABCD->ABCDA->ABCDAB->ABCDABC->ABCDABCD

可以看出对s1做循环移位所得到的字符串都将是字符串s1s1的子字符串。如果s2可以由s1循环移位得到,那么s2一定在s1s1上,我们只需要一次strstr函数得到结果

 

代码

const int MAXSIZE = 10000;

 

int length(char* str)

{

       int iLen = 0 ;

       while( *str != '\0')

       {

              iLen++;

              str++;

       }

       return iLen;

}

 

void process()

{

       char str[MAXSIZE],strSub[MAXSIZE];

       char strDouble[2*MAXSIZE];

       while(EOF != scanf("%s %s",str,strSub))

       {

              if(length(str) < length(strSub))

              {

                     printf("No\n");

                     continue;

              }

              strcpy(strDouble,str);

              strcat(strDouble,str);//形成str1str1的形式

              if(strstr(strDouble,strSub))//char* strstr()const char* str1,const char* str2):指向字符串str2首次出现在str1中的位置,如果没有返回NULL

              {

                     printf("Yes\n");

              }

              else

              {

                     printf("No\n");

              }

       }

}

6

最短摘要的生成

输入一些关键词之后,搜索引擎会返回许多结果,每个结果都包含一段概括网页内容的还要。标题和URL之间的内容就是我们所说的摘要

假设给定的已经是网页分词之后的结果,词语序列数组为W。其中W[0],W[1],...,W[N]为一些已经分好的词语。

假设用户输入的搜索关键词为数组Q,其中Q[0],Q[1],...,Q[m]为所有输入的搜索关键词。

这样,生成的最短摘要实际上就是一串相互联系的分词序列。比如从W[i]到W[j],其中,0

“微软亚洲研究院成立于1998年,我们的使命”包含了所有的关键字 --- “微软亚洲研究院 使命”

 

输入:

马超,字孟起,扶风茂陵人,生于三国末年。马超一生,勇冠三军,三国中家喻户晓的名将。(网页内容)

2(表示关键词的个数)

马超 三国

输出:

born in FufengMaoling

输入:

MaChao called mengqi lived in SanGuo. All of MaChao life, always win, famous in SanGuo.

2

MaChao SanGuo.

输出:

SanGuo. All of MaChao

编程之美

https://blog.csdn.net/qingyuanluofeng/article/details/47187613

分析:

“微软/亚洲/研究院。。。”,这就是我们期望的W数组序列。

w0,w1,w2,w3,q0,w4,w5,q1,w6,w7,w8,q0,w9,q1

1从W数组的第一个位置开始查找出一段包含所有关键词数组的Q的序列。计算当前的最短长度,并更新Seq数组。

2对目标数组W进行遍历,从第二个位置开始,重新查找包含所有关键词数组Q的序列,同样计算出其最短长度,以及更新包含所有关键词的序列Seq,然后求出最短距离

3依次操作下去,一直到遍历至目标数组W的最后一个位置为止。

要遍历所有其他的关键词(M),对于每个关键词,要遍历整个网页的词(N),而每个关键词在整个网页中的每一次出现,要遍历所有的Seq,以更新这个关键词与所有其他

关键词的最小距离。

时间复杂度O(N^2*M)

解法2:

进行查找的时候,总是重复地循环,效率不高。

问题在于如果一次把所有的关键词都扫面到,而且不遗漏。如何把两次扫面的结果联系起来?

第一次扫描的时候,假设需要包含所有的关键词,将得到如下结果:

w0,w1,w2,w3,q0,w4,w5,q1,w6,w7,w8,q0,w9,q1

#                       #

那么下次搜索应该怎么办?显然,可以把第一个被扫描的位置挪动q0处。如果把第一个被扫描的位置继续往后面移动一格,这样包含的序列中将减少了关键词q0.

w0,w1,w2,w3,q0,w4,w5,q1,w6,w7,w8,q0,w9,q1

            #           #

那么,如果我们把第二个扫面位置往后移,这样就可以找到下一个包含所有关键词的序列:

如下

w0,w1,w2,w3,q0,w4,w5,q1,w6,w7,w8,q0,w9,q1

               #                    #

这样问题就和第一次扫描碰到的情况一样了。依次扫描下去,在w中找出所有包含q的序列,并且找出其中的最小值,就可以得到最终结果

关键:

1 //最短摘要的主要算法:如果没有找到包含所有关键词的摘要,那么向后移动指针;一旦找到,那么判断当前找到的这段摘要长度是否小于已经记录的最短长度;若小于

//那么就更新最短长度,并且设定最终返回的摘要的起止指针。然后继续向后移动起始指针,通过这个方法,来缩短距离。

2           while(!isConcluded(strPage,iBeg,iEnd,strKeyWord,iWordNum) && iEnd < iLen)//如果没有包含所有关键词,就向后移动结束指针

              {

                     iEnd++;

              }

3           while(isConcluded(strPage,iBeg,iEnd,strKeyWord,iWordNum))// 如果包含了,那么进行更新操作

              {

                     if(iEnd - iBeg < iPageLen)//如果当前全部包含关键词摘要的长度比最短长度要小,就更新

                     {

                            iPageLen = iEnd - iBeg;

                            iAbsBeg = iBeg;

                            iAbsEnd = iEnd;

                     }

                     iBeg++;//最精彩的一步,将起点指针不断后移,来使包含全部关键字摘要的长度减少

 

代码

const int MAXSIZE = 100;

const int INF = 0x7fffffff;

 

//判断如何包含,所采用的方法是用strstr函数来判断

bool isConcluded(char* strPage,int iBeg,int iEnd,char strKeyWord[][MAXSIZE],int iWordNum)

{

       if(!strPage || !strKeyWord || iBeg < 0 || iEnd < 0 || iBeg > iEnd || iWordNum <= 0)

       {

              return false;

       }

       char strNewPage[MAXSIZE];//生成一个新的字符串

       for(int i = iBeg ; i <= iEnd ; i++)

       {

              strNewPage[i-iBeg] = strPage[i];

       }

       strNewPage[iEnd+1] = '\n';

       for(int i = 0 ; i < iWordNum ; i++)

       {

              if(!strstr(strNewPage,strKeyWord[i]))

              {

                     return false;

              }

       }

       return true;

}

//最短摘要的主要算法:如果没有找到包含所有关键词的摘要,那么向后移动指针;一旦找到,那么判断当前找到的这段摘要长度是否小于已经记录的最短长度;若小于

//那么就更新最短长度,并且设定最终返回的摘要的起止指针。然后继续向后移动起始指针,通过这个方法,来缩短距离。

pair shortestAbstract(char* strPage,int iLen,char strKeyWord[][MAXSIZE],int iWordNum)

{

       int iPageLen = INF;

       int iBeg = 0,iEnd = 0;

       int iAbsBeg = 0,iAbsEnd = 0;

       while(true)

       {

              while(!isConcluded(strPage,iBeg,iEnd,strKeyWord,iWordNum) && iEnd < iLen)//如果没有包含所有关键词,就向后移动结束指针

              {

                     iEnd++;

              }

              while(isConcluded(strPage,iBeg,iEnd,strKeyWord,iWordNum))// 如果包含了,那么进行更新操作

              {

                     if(iEnd - iBeg < iPageLen)//如果当前全部包含关键词摘要的长度比最短长度要小,就更新

                     {

                            iPageLen = iEnd - iBeg;

                            iAbsBeg = iBeg;

                            iAbsEnd = iEnd;

                     }

                     iBeg++;//最精彩的一步,将起点指针不断后移,来使包含全部关键字摘要的长度减少

              }

              if(iEnd >= iLen)//判断字符串越界

              {

                     break;

              }

       }

       return make_pair(iAbsBeg,iAbsEnd);

}

 

void process()

{

       int n;

       char strPage[MAXSIZE*MAXSIZE];//被查找网页应该用一个大字符串即可,但是用户输入的关键词,必须要用二维字符指针来保存

       char strKeyWord[MAXSIZE][MAXSIZE];

       while(NULL != gets(strPage))

       {

              scanf("%d",&n);

              for(int i = 0 ; i < n ; i++)

              {

                     scanf("%s",strKeyWord[i]);

              }

              pair pairRes = shortestAbstract(strPage,strlen(strPage),strKeyWord,n);

              printAbstract(strPage,pairRes.first,pairRes.second);

       }

}

7

写翻转字符串函数reverse(char* str)

用C或C++实现void reverse(char* str)函数,即翻转一个null结尾的字符串

 

输入:

chaoma

输出:

amoahc

程序员面试金典

https://blog.csdn.net/qingyuanluofeng/article/details/53759839

关键:

1 本质就是寻找到字符串首尾指针,对于首尾处字符交换,然后向中间逼近

2 注意寻找到尾指针后,需要另last--,因为需使得尾指针在'\0'之前的一个字符

 

void reverse(char* str)

{

       char* last = str;

 

       //如果还没有到达末尾

       while( (*last) != '\0' )

       {

              last++;

       }

 

       //最后一个字符串是结尾符,需要去除

       last--;

       char* begin = str;

 

       //只要前面小于后面,就交换

       while(begin < last)

       {

              char temp = * begin;

              //先*后++

              *(begin++) = *last;

              *(last--) = temp;

       }

}

 

int main(int argc, char* argv[])

{

       char str[MAXSIZE];

       while(cin >> str)

       {

              reverse(str);

              cout << str << endl;

       }

       system("pause");

       return 0;

}

8

判断一个字符串字符重新排列后是否可变成另一个字符串

给定两个字符串,请编写程序,确定其中一个字符串的字符重新排列后,能否变成另一个字符串

 

输入:

cao chao

mach cahm

输出:

no

yes

程序员面试金典

https://blog.csdn.net/qingyuanluofeng/article/details/53760249

分析:字符串排列后的能否变成另一个字符串=对两个字符串排序,排序后比较若相同,则说明经过排列后

      其中一个字符串可以变成另一个字符串

         如果两个字符串不等,肯定不可以

 

关键:

1 利用排列后是否可以变成另一个字符串,说明两个字符串所组成的字符相同,即可根据对字符串排序后是否相等来做

 

bool isCanChange(string& str1 , string& str2)

{

       if(str1.length() != str2.length())

       {

              return false;

       }

       sort(str1.begin() , str1.end());

       sort(str2.begin() , str2.end());

       if( str1 == str2)

       {

              return true;

       }

       else

       {

              return false;

       }

}

9

字符串中空格全部替换为"%20"

编写一个方法,将字符串中的空格全部替换为“%20”。

假定该字符串尾部留有足够的空间存放新增字符,并且知道字符串的真实长度

程序员面试金典

https://blog.csdn.net/qingyuanluofeng/article/details/53760941

与剑指offer题目相同,参见: 题目1 替换空格

10

字符串压缩

利用字符重复出现的次数,编写一个方法,实现基本的字符串压缩功能。

比如,字符串aabcccccaaa会变为a2b1c5a3.若“压缩”后的字符串没有变短,则返回原先的字符串。

 

输入:

aabcccccaaa

m

ma

mm

输出:

a2b1c5a3

m

ma

mm

程序员面试金典

https://blog.csdn.net/qingyuanluofeng/article/details/53761493

分析:本质上就是寻找相邻相同字母的问题。当相邻两个字符不同时,开始重新计数

      从后向前,

         暴力破解来做

 

关键:

1 本质前后寻找一段连续相同字母的首标和末标,注意对最后一段相同字母处理

 

代码:

 

string stringCompress(const string& str)

{

       if(str.empty())

       {

              return str;

       }

       int length = str.length();

       stringstream sResult;

       //只有一个字符,直接返回该字符串

       if(length == 1)

       {

              return str;

       }

       int begin = 0;

       int end = begin + 1;

       while(end < length)

       {

              //如果前后相邻部分相同,继续寻找下标

              if( str[begin] == str[end] )

              {

                     end++;

                     continue;

              }

 

              //如果前后相邻部分不同,则需要,设定当前字符的截止下标为end-1,并重新设置下一处字符起始下标为end

              else

              {

                     end = end - 1;

                     int iLen = end - begin + 1;

                     sResult << str[begin] << iLen;

                     begin = end + 1;

                     end = begin + 1;

              }

       }

 

       //对最后一个end进行处理

       end = end - 1;

       int iLen = end - begin + 1;

       sResult << str[begin] << iLen;

       if(sResult.str().length() < str.length())

       {

              return sResult.str();

       }

       else

       {

              return str;

       }

}

11

判断两个字符串中一个字符串是否由另一个字符串旋转而成

假定有一个方法isSubstring,可以检查一个单词是否为其他字符串的子串。给定两个字符串s1和s2.请编写代码检查s2是否为s1旋转而成,要求只能调用一次isSubstring。(比如,waterbottle是erbottlewat旋转后的字符串)

程序员面试金典

https://blog.csdn.net/qingyuanluofeng/article/details/53765484

与编程之美中的题目相同,参见: 题目5字符串移位包含的问题

12

Implement strStr()

Returns the index of the first occurrence of needle in haystack, or -1 if needle is not part of haystack.

分析:

needle:针

haystack:干草堆

应该是返回字符串在另一个字符串首次出现的位置,如果没有返回-1.

Leecode

https://blog.csdn.net/qingyuanluofeng/article/details/54849509

13

Count and Say

The count-and-say sequence is the sequence of integers beginning as follows:

1, 11, 21, 1211, 111221, ...

1 is read off as "one 1" or 11.

11 is read off as "two 1s" or 21.

21 is read off as "one 2, then one 1" or 1211.

Given an integer n, generate the nth sequence.

Note: The sequence of integers will be represented as a string.

分析:此题本质就是按照顺序数出每个数的出现次数,然后翻译层字符串。

1211:One 1,  One 2, Two 1,得到 111221

111221:Three 1,Two 2,One 1,

31,22,11得到: 312211

312211:One 3,Two 2,Two 1

13,22,21得到132221

Leecode

https://blog.csdn.net/qingyuanluofeng/article/details/54933869

14

Wildcard Matching

Implement wildcard pattern matching with support for '?' and '*'.

 

'?' Matches any single character.

'*' Matches any sequence of characters (including the empty sequence).

 

The matching should cover the entire input string (not partial).

 

The function prototype should be:

bool isMatch(const char *s, const char *p)

 

Some examples:

isMatch("aa","a") → false

isMatch("aa","aa") → true

isMatch("aaa","aa") → false

isMatch("aa", "*") → true

isMatch("aa", "a*") → true

isMatch("ab", "?*") → true

isMatch("aab", "c*a*b") → false

分析:

wildcard:通配符.?可以匹配任意单一字符,*匹配任意字符串(包括空字符串)

Leecode

https://blog.csdn.net/qingyuanluofeng/article/details/54947823

15

Group Anagrams

Total Accepted: 114812

Total Submissions: 355832

Difficulty: Medium

Contributors: Admin

Given an array of strings, group anagrams together.

For example, given: ["eat", "tea", "tan", "ate", "nat", "bat"],

Return:

[

  ["ate", "eat","tea"],

  ["nat","tan"],

  ["bat"]

]

Note: All inputs will be in lower-case.

分析:

anagrams:颠倒字母顺序构成的字

Leecode

https://blog.csdn.net/qingyuanluofeng/article/details/54968963

16

Length of Last Word

Given a string s consists of upper/lower-case alphabets and empty space characters ' ', return the length of last word in the string.

If the last word does not exist, return 0.

Note: A word is defined as a character sequence consists of non-space characters only.

For example,

Given s = "Hello World",

return 5.

分析:题目的意思是找到最后一个单词的长度。

Leecode

https://blog.csdn.net/qingyuanluofeng/article/details/54973906

17

Text Justification

Given an array of words and a length L, format the text such that each line has exactly L characters and is fully (left and right) justified.

You should pack your words in a greedy approach; that is, pack as many words as you can in each line. Pad extra spaces ' ' when necessary so that each line has exactly L characters.

Extra spaces between words should be distributed as evenly as possible. If the number of spaces on a line do not divide evenly between words, the empty slots on the left will be assigned more spaces than the slots on the right.

For the last line of text, it should be left justified and no extra space is inserted between words.

For example,

words: ["This", "is", "an", "example", "of", "text", "justification."]

L: 16.

Return the formatted lines as:

[

   "This    is    an",

   "example  of text",

   "justification.  "

]

Note: Each word is guaranteed not to exceed L in length.

分析:justified:合理的,pad:填塞

这是一个格式化输出的问题。本质上给定一个字符串数组和一个长度L,

1】需要摆放后每一行的长度都是L,如果不足L,需要填充空字符。

2】需要在一行中尽可能多的填充单词。

3】填充的空格需要尽可能左右两边相等,如果填充的空格部分不等,左边

   的空格可以比右边的多一些。

4】最后一行需要全部放置在左边,并且不能有额外的空格在单词之间。

这是否意味着最后一行只能放一个单词?然后不足的部分全部在右侧填充空格

理解错了,最后一行左对齐,并且单词之间不需要空格。说明是可以存放多个

单词的。

Leecode

https://blog.csdn.net/qingyuanluofeng/article/details/54985995

18

Given an absolute path for a file (Unix-style), simplify it.

For example,

path = "/home/", => "/home"

path = "/a/./b/../../c/", => "/c"

click to show corner cases.

 

Corner Cases:

Did you consider the case where path = "/../"?

In this case, you should return "/".

Another corner case is the path might contain multiple slashes '/' together, such as "/home//foo/".

In this case, you should ignore redundant slashes and return "/home/foo".

分析:给定unix下的绝对路径,来简化路径。

Leecode

https://blog.csdn.net/qingyuanluofeng/article/details/54988619

19

Minimum Window Substring

Given a string S and a string T, find the minimum window in S which will contain all the characters in T in complexity O(n).

For example,

S = "ADOBECODEBANC"

T = "ABC"

Minimum window is "BANC".

Note:

If there is no such window in S that covers all characters in T, return the empty string "".

If there are multiple such windows, you are guaranteed that there will always be only one unique minimum window in S.

分析:这个是编程之美中,最短摘要生成问题的变体。

Leecode

https://blog.csdn.net/qingyuanluofeng/article/details/55001068

20

Restore IP Addresses

Given a string containing only digits, restore it by returning all possible valid IP address combinations.

For example:

Given "25525511135",

return ["255.255.11.135", "255.255.111.35"]. (Order does not matter)

分析:对给定的字符串通过添加"."号,使其变成有效的ip,返回有效ip的所有结果。

Leecode

https://blog.csdn.net/qingyuanluofeng/article/details/55062972

21

Valid Palindrome

Given a string, determine if it is a palindrome, considering only alphanumeric characters and ignoring cases.

For example,

"A man, a plan, a canal: Panama" is a palindrome.

"race a car" is not a palindrome.

Note:

Have you consider that the string might be empty? This is a good question to ask during an interview.

For the purpose of this problem, we define empty string as valid palindrome.

分析:此题实际是判断一个字符串是否是回文字符串,不考虑大小写,比较的时候只比较字母和数字,对于其他字符默认忽略。

Leecode

https://blog.csdn.net/qingyuanluofeng/article/details/55260008

22

Reverse Words in a String

Given an input string, reverse the string word by word.

For example,

Given s = "the sky is blue",

return "blue is sky the".

Update (2015-02-12):

For C programmers: Try to solve it in-place in O(1) space.

Clarification:

What constitutes a word?

A sequence of non-space characters constitutes a word.

Could the input string contain leading or trailing spaces?

Yes. However, your reversed string should not contain leading or trailing spaces.

How about multiple spaces between two words?

Reduce them to a single space in the reversed string.

分析:trailing space尾部空格

将给定字符串中的单词逆置,注意只是逆置单词的位置,单词本身并不会逆置。

Leecode

https://blog.csdn.net/qingyuanluofeng/article/details/56016939

23

Compare Version Numbers

Compare two version numbers version1 and version2.

If version1 > version2 return 1, if version1 < version2 return -1, otherwise return 0.

You may assume that the version strings are non-empty and contain only digits and the . character.

The . character does not represent a decimal point and is used to separate number sequences.

For instance, 2.5 is not "two and a half" or "half way to version three", it is the fifth second-level revision of the second first-level revision.

Here is an example of version numbers ordering:

0.1 < 1.1 < 1.2 < 13.37

分析:"."不是代表数值中的点,而是表示修订版本的序号,"."号前面部分的数字表示的是第几个版本,"."修订版本

Leecode

https://blog.csdn.net/qingyuanluofeng/article/details/56056127

24

Largest Number

Given a list of non negative integers, arrange them such that they form the largest number.

For example, given [3, 30, 34, 5, 9], the largest formed number is 9534330.

Note: The result may be very large, so you need to return a string instead of an integer.

分析:给定一个非负整数数组,将他们以一定次序排放,使其变成最大的数字。

Leecode

https://blog.csdn.net/qingyuanluofeng/article/details/56284010

25

Repeated DNA Sequences

All DNA is composed of a series of nucleotides abbreviated as A, C, G, and T, for example: "ACGAATTCCG". When studying DNA,

it is sometimes useful to identify repeated sequences within the DNA.

Write a function to find all the 10-letter-long sequences (substrings) that occur more than once in a DNA molecule.

For example,

Given s = "AAAAACCCCCAAAAACCCCCCAAAAAGGGTTT",

Return:

["AAAAACCCCC", "CCCCCAAAAA"].

分析:nucleotides:核苷酸,abbreviated:简短的.

此题需要寻找出长度为10的重复出现的子串。

Leecode

https://blog.csdn.net/qingyuanluofeng/article/details/56288369

26

Isomorphic Strings

Given two strings s and t, determine if they are isomorphic.

Two strings are isomorphic if the characters in s can be replaced to get t.

All occurrences of a character must be replaced with another character while preserving the order of characters. No two characters may map to the same character but a character may map to itself.

For example,

Given "egg", "add", return true.

Given "foo", "bar", return false.

Given "paper", "title", return true.

Note:

You may assume both s and t have the same length.

分析:判断两个字符串是否具有相同的结构,用同一个字符对应替换看是否能够将替换后的结果和给出的结果一致,

如果得到的结果不一致,说明不等。

Leecode

https://blog.csdn.net/qingyuanluofeng/article/details/56348267

27

Valid Anagram

Given two strings s and t, write a function to determine if t is an anagram of s.

For example,

s = "anagram", t = "nagaram", return true.

s = "rat", t = "car", return false.

Note:

You may assume the string contains only lowercase alphabets.

Follow up:

What if the inputs contain unicode characters? How would you adapt your solution to such case?

分析:其实就是判断一个单词是不是另一个单词的变位词。

Leecode

https://blog.csdn.net/qingyuanluofeng/article/details/56885719

28

Word Pattern

Given a pattern and a string str, find if str follows the same pattern.

Here follow means a full match, such that there is a bijection between a letter in pattern and a non-empty word in str.

Examples:

pattern = "abba", str = "dog cat cat dog" should return true.

pattern = "abba", str = "dog cat cat fish" should return false.

pattern = "aaaa", str = "dog cat cat dog" should return false.

pattern = "abba", str = "dog dog dog dog" should return false.

Notes:

You may assume pattern contains only lowercase letters, and str contains lowercase letters separated by a single space.

分析:bijection,双射

给定了模式,然后判断字符串是否符合该模式

Leecode

https://blog.csdn.net/qingyuanluofeng/article/details/57415226

29

Bulls and Cows

You are playing the following Bulls and Cows game with your friend: You write down a number and ask your friend to guess what the number is. Each time your friend makes a guess, you provide a hint that indicates how many digits in said guess match your secret number exactly in both digit and position (called "bulls") and how many digits match the secret number but locate in the wrong position (called "cows"). Your friend will use successive guesses and hints to eventually derive the secret number.

For example:

Secret number:  "1807"

Friend's guess: "7810"

Hint: 1 bull and 3 cows. (The bull is 8, the cows are 0, 1 and 7.)

Write a function to return a hint according to the secret number and friend's guess, use A to indicate the bulls and B to indicate the cows.

In the above example, your function should return "1A3B".

Please note that both secret number and friend's guess may contain duplicate digits, for example:

Secret number:  "1123"

Friend's guess: "0111"

In this case, the 1st 1 in friend's guess is a bull, the 2nd or 3rd 1 is a cow, and your function should return "1A1B".

You may assume that the secret number and your friend's guess only contain digits, and their lengths are always equal.

分析:

公牛:有多少位是正确的同时位置也是正确的。

母牛:有多少位在所猜的数中,但是位置是错误的

注意:母牛=所有匹配的个数-公牛个数

      公牛=位置上相等的元素个数

         用A表示公牛,B表示母牛,形成

         xxAxxB这种形式作为提示

Leecode

https://blog.csdn.net/qingyuanluofeng/article/details/57417716

30

Reverse String

Write a function that takes a string as input and returns the string reversed.

Example:

Given s = "hello", return "olleh".

分析:逆置一个字符串

Leecode

https://blog.csdn.net/qingyuanluofeng/article/details/58710004

31

Reverse Vowels of a String

Write a function that takes a string as input and reverse only the vowels of a string.

Example 1:

Given s = "hello", return "holle".

Example 2:

Given s = "leetcode", return "leotcede".

Note:

The vowels does not include the letter "y".

分析:题目的意思只是将字符串中的元音字母进行逆置。

Leecode

https://blog.csdn.net/qingyuanluofeng/article/details/59117549

32

Ransom Note

Given an arbitrary ransom note string and another string containing letters from all the magazines, write a function that will return true if the ransom note can be constructed from the magazines ; otherwise, it will return false.

Each letter in the magazine string can only be used once in your ransom note.

Note:

You may assume that both strings contain only lowercase letters.

canConstruct("a", "b") -> false

canConstruct("aa", "ab") -> false

canConstruct("aa", "aab") -> true

分析:题目中信封中的字符串来源于杂志中,且杂志中的每个字符最多使用一次。

请问给定一个杂志字符串,判定信封字符串是否可以构建。

所有字母都是小写的。

Leecode

https://blog.csdn.net/qingyuanluofeng/article/details/60129196

33

如何对字符串进行反转

实现字符串的反转,要求不使用任何系统方法,且时间复杂度最小

Python程序员面试算法宝典

https://blog.csdn.net/qingyuanluofeng/article/details/94301139

34

如何消除字符串内的内嵌括号
给定一个如下格式的字符串:

(1,(2,3),(4,(5,6),7))

括号内的元素可以是数字,也可以是另一个括号,实现一个

算法消除嵌套的括号,例如把上面的表达式变成

(1,2,3,4,5,6,7),

如果表达式有误,那么报错

Python程序员面试算法宝典

https://blog.csdn.net/qingyuanluofeng/article/details/94328484

35

如何判断字符串是否为整数

写一个方法,检查字符串是否是整数,如果是整数,那么返回其整数值。

Python程序员面试算法宝典

https://blog.csdn.net/qingyuanluofeng/article/details/94331216

36

如何实现字符串的匹配

给定主字符串S与模式字符串P,判断P是否是S的子串,如果是,

那么找出P在S中第一次出现的下标

Python程序员面试算法宝典

https://blog.csdn.net/qingyuanluofeng/article/details/94335654

37

如何求字符串里的最长回文子串

回文字符串是指一个字符串从左到右与从右到左遍历得到的序列是相同的。

例如"abcba"就是回文字符串,而"abcab"则不是回文字符串。

Python程序员面试算法宝典

https://blog.csdn.net/qingyuanluofeng/article/details/94428627

38

求一个串中出现的第一个最长重复子串

给定一个字符串,找出这个字符串中最长的重复子串,比如给定字符串"banana",

子字符串"ana"出现2次,因此最长的重复子串为"ana"

Python程序员面试算法宝典

https://blog.csdn.net/qingyuanluofeng/article/details/94971654

39

如何求解字符串中字典序最大的子序列

给定一个字符串,求串中字典序最大的子序列。字典序最大的子序列是这样构造的:

给定字符串a0a1...an-1,首先在字符串a0a1...an-1中找到值最大的字符ai,

然后在剩余字符串ai+1..an-1中找到值最大的字符aj然后在剩余的aj+1...an-1

中找到值最大的字符ak...直到字符串的长度为0,则aiajak...即为答案。

Python程序员面试算法宝典

https://blog.csdn.net/qingyuanluofeng/article/details/94973971

40

如何判断一个字符串是否由另外一个字符串旋转得到

给定一个能判断一个单词是否为另一个单词的子字符串的方法,记为isSubstring。

如何判断s2是否能够通过旋转s1得到(只能使用一次isSubstring方法)。

例如: "waterbottle"可以通过字符串"erbottlewat"旋转得到。

Python程序员面试算法宝典

https://blog.csdn.net/qingyuanluofeng/article/details/95019432

41

如何截取包含中文的字符串

编写一个截取字符串的函数,输入为一个字符串和字节数,输出为按字节数截取的字符串。

但要保证汉字不被截半个,例如"人ABC" 4,应该截为"人AB",

输入"人ABC"而并不是"人ABC+们的半个"

Python程序员面试算法宝典

https://blog.csdn.net/qingyuanluofeng/article/details/95896271

42

如何求相对路径

编写一个函数,根据两个文件的绝对路径计算出其相对路径。

例如

a="/qihoo/app/a/b/c/d/new.c",

b="/qihoo/app/1/2/test.c"

那么b相对于a的;就是

"../../../../1/2/test.c"

Python程序员面试算法宝典

https://blog.csdn.net/qingyuanluofeng/article/details/95898148

43

回文串

输入一个字符串,求出其中最长的回文串。子串:在原串中连续出现的字符串片段。忽略标点和空格,大小写

输入字符串长度不超过5000,且占据单独一行。若有多个最长回文串,则输出起始位置最靠左的

输入:

Confuciuss say:Madam.I'm Adam.

输出:

Madam,I'm Adam

算法竞赛入门经典

https://blog.csdn.net/qingyuanluofeng/article/details/47416919

44

周期串

如果一个字符串可以由某个长度为k的字符串重复多次得到,我们说该串以k为周期。例如,abcabcabcabc是以3为周期(注意,它也以6和12为周期)。输入一个长度不

超过80的串,输出它的最小周期

输入:

HoHoHo

输出:2

算法竞赛入门经典

https://blog.csdn.net/qingyuanluofeng/article/details/47417255

45

寻找字符串中的最长重复子串

编程珠玑

https://blog.csdn.net/qingyuanluofeng/article/details/54647445

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

参考:
[1]计算机考研--机试指南,王道论坛 组编
[2]剑指offer
[3]算法设计与分析
[4]编程之美
[5]程序员面试金典
[6]leecode
[7]Python
程序员面试算法宝典
[8]刘汝佳算法竞赛入门经典
[9]算法导论
[10]编程珠玑

 

 

 

 

 

你可能感兴趣的:(算法,64式)