前后重组字符串
2014-09-30 16:32
239 查看
距离上次写博客已经快一个月了,最近这个月都一直在忙着找工作,现在暂时有了一个offer,刚好昨天去网易笔试了一下,就将里面的题目拿出来做做。
题目是这样子的:输入一个字符串src,从这个字符串去除头或者尾一个字符,并将这个字符加到另外一个字符串result的尾端,删除了src的所有字符后,要求得到最后的字符串result最小(即要求字符串是生成的字符串是按字符字典最小的字符串),例如输入 src="acdebcb",输出为result="abcbcde"。
其实题目的意思就是前后不断地取src字符串的字符元素,小的那个先取。题目不是很难,关键步骤是看怎么去处理当前后字符相等时的情况。(刚开始以为自己的思路是正确的,结果在写这篇博客分析的时候,却发现逻辑有点不对,于是又重新想了下,看来写博客也有这方面的好处啊)
我的思路是这样子的,先设置两个下标变量front和把back分别指向字符串的头和尾,如下图所示:
看src[front]和src[back]哪个小,小的那个就将其加到result中,并且下标变量更新。
如果相等,就再设置两个临时变量left和right,分别指向相等的前后两个元素,并调用函数去判断是从字符串的左边还是右边去取数。一开始以为要用递归去判断多重相等的情况,所以就写成函数的形式,后面调试的时候发现是不用递归的,结果后面还是保留了函数的形式,不过这样子看也不错,能把逻辑分开来,好懂一些。
函数 findIndex 是个逻辑判断函数,首先是处理下标left和right,front和back 的越界情况,然后是多个判断情况。
1.判断下两个元素,即left和right对应的元素是不是比前面的元素都大,是的话,就返回左边或者右边都可以,这里是返回左边,记得要将left值要减一。
2.判断如果src[left]不等于src[right]且有一个小于它对应的前一位的值,那么就返回小的值的那一端。
3.判断如果src[left]等于src[right]且它们小于它的前一位值,那么就循环更新left和right的值。当循环结束时,要考虑是哪个条件导致了循环结束,于是又分为了下面几种情况:
(1)如果是下标条件越界的,就就随便返回一边,这里是返回左边,记得将left减一,因为之前是越界了。
(2)这里说明没有越界,然后判断左右是不是相等,如果有小的一端,那么就返回小的那个方向,如果没有小的一端,说明这两个元素相等而且大于前面的元素,那么情况就和前面的情况1是一样的,直接返回一边即可(下标要处理)。
到这里好像就讨论完了,其实还要处理最后一个当left等于right的时候,那么也要将最后一个元素加到字符串的后面去,那么现在就是真正的结束了。
下面是代码,代码里面有注释,对应了上面的的分析。可以参照着代码和分析一起看,这样可能容易懂一些。测试了多个用例,感觉是对的,但不保证完全没有错误。另外,这是网易笔试题第一道编程题,感觉是不是应该有更简单的分析方法呢,如果大家有的话欢迎来交流。
题目是这样子的:输入一个字符串src,从这个字符串去除头或者尾一个字符,并将这个字符加到另外一个字符串result的尾端,删除了src的所有字符后,要求得到最后的字符串result最小(即要求字符串是生成的字符串是按字符字典最小的字符串),例如输入 src="acdebcb",输出为result="abcbcde"。
其实题目的意思就是前后不断地取src字符串的字符元素,小的那个先取。题目不是很难,关键步骤是看怎么去处理当前后字符相等时的情况。(刚开始以为自己的思路是正确的,结果在写这篇博客分析的时候,却发现逻辑有点不对,于是又重新想了下,看来写博客也有这方面的好处啊)
我的思路是这样子的,先设置两个下标变量front和把back分别指向字符串的头和尾,如下图所示:
看src[front]和src[back]哪个小,小的那个就将其加到result中,并且下标变量更新。
如果相等,就再设置两个临时变量left和right,分别指向相等的前后两个元素,并调用函数去判断是从字符串的左边还是右边去取数。一开始以为要用递归去判断多重相等的情况,所以就写成函数的形式,后面调试的时候发现是不用递归的,结果后面还是保留了函数的形式,不过这样子看也不错,能把逻辑分开来,好懂一些。
函数 findIndex 是个逻辑判断函数,首先是处理下标left和right,front和back 的越界情况,然后是多个判断情况。
1.判断下两个元素,即left和right对应的元素是不是比前面的元素都大,是的话,就返回左边或者右边都可以,这里是返回左边,记得要将left值要减一。
2.判断如果src[left]不等于src[right]且有一个小于它对应的前一位的值,那么就返回小的值的那一端。
3.判断如果src[left]等于src[right]且它们小于它的前一位值,那么就循环更新left和right的值。当循环结束时,要考虑是哪个条件导致了循环结束,于是又分为了下面几种情况:
(1)如果是下标条件越界的,就就随便返回一边,这里是返回左边,记得将left减一,因为之前是越界了。
(2)这里说明没有越界,然后判断左右是不是相等,如果有小的一端,那么就返回小的那个方向,如果没有小的一端,说明这两个元素相等而且大于前面的元素,那么情况就和前面的情况1是一样的,直接返回一边即可(下标要处理)。
到这里好像就讨论完了,其实还要处理最后一个当left等于right的时候,那么也要将最后一个元素加到字符串的后面去,那么现在就是真正的结束了。
下面是代码,代码里面有注释,对应了上面的的分析。可以参照着代码和分析一起看,这样可能容易懂一些。测试了多个用例,感觉是对的,但不保证完全没有错误。另外,这是网易笔试题第一道编程题,感觉是不是应该有更简单的分析方法呢,如果大家有的话欢迎来交流。
//返回值 0代表左边,1代表右边 int findIndex(const std::string& src,int& front,int& back,int& left,int& right) { if (front > back || left > right) { return 0; } //如果下两个元素都比前面的元素大,那么前面的两个元素加到目标字符串的尾部 if (left < right && src[left] > src[front] && src[right] > src[back]) { left--; return 0; } //如果left和right不相等,而且有一个小于front的元素,那么就将小的那一端的两个元素加到目标字符串尾部 if (left < right && (src[left] < src[front] || src[right] < src[back]) && src[left] != src[right]) { if (src[left] < src[right]) { return 0; } else if (src[left] > src[right]) { return 1; } } //如果left和right一直相等而且都是小于前一个数的话,就一直循环,直到下标结束条件或者left和right对应的元素值大于前一个值 while(left < right && src[left] == src[right] && src[left] < src[left-1]) { left++; right--; } //判断是不是下标条件结束的 if (left >= right) { left--; return 0; } else { //判断左右是不是还相等 if (src[left] < src[right]) { return 0; } else if(src[left] > src[right]) { return 1; } else { //左右还相等的话,到这里,就说明 src[left] >= src[left-1] && src[left] == src[right], //那么就递归求值 /*left++; right--; return findIndex(src,front,back,left,right);*/ //不用递归,直接返回之前的下标即可 left--; return 0; } } } std::string ResortString(const std::string src) { string result; int len = src.length(); if (len < 1) { return result; } else if (1 == len) { result = src; return result; } int front = 0,back = len-1; //两个下标分别标记字符串的头部和尾部 while (front < back) { //小的那个字符加到结果字符串中 if (src[front] < src[back]) { result += src[front++]; } else if (src[front] > src[back]) { result += src[back--]; } else { //如果两个元素相等,则另外设两个标志下标 int left = front +1; int right = back -1; //调用函数去判断是从左边还是右边取数 int direct = findIndex(src,front,back,left,right); if (!direct) { //左边取数 while(front <= left) { result += src[front++]; } } else { //右边取数 while(back >= right) { result += src[back--]; } } } } //考虑下标相等的情况 if (front == back) { result += src[front]; } return result; } // int main() { string str = "acdebcb"; //acbdegfadbcb aedcezecdea baezeab acbdadbcb cout<<ResortString(str)<<endl; cout<<"end"<<endl; }
相关文章推荐
- 去除字符串前后的逗号;验证特殊字符
- 【HDU5651 BestCoder Round 77 (div1) A】【简单组合数】xiaoxin juju needs help 字符串位置重组构成回文串个数
- js 去掉字符串前后空格5种方法
- js去除字符串前后空格
- javascript:去除字符串的前后空格
- 用正则表达式将前后空格用空字符串替代:replace(/(^\s*)|(\s*$)/g, "")
- (原創) 如何将字符串前后的空白去除? (C/C++) (STL)
- 将字符串前后的*都去掉
- js 去掉字符串前后空格实现代码集合
- 关于处理字符串里姓名中间、前后有空格的问题
- JS 去掉字符串前后/左/右 空格
- String清除字符串前后空格,包括全角空格
- Javascript 去掉字符串前后空格的五种方法
- javascript中去掉字符串的前后多余空格
- Java中过滤字符串前后的空格
- JS去除字符串前后空格及有输入法逗号
- 去掉一段字符串前后空格得五种方法
- C语言除去字符串前后的空格
- java(例子005)删除字符串前后空格