0
点赞
收藏
分享

微信扫一扫

【C】翻转单词-刷题

桑二小姐 2022-02-17 阅读 43

目录

前言

一、58剑指offer翻转单词顺序(传送门)

二、151翻转字符串里的单词(传送门)

总结


前言


一、58剑指offer翻转单词顺序(传送门)

char* reverseWords(char* s){
    int len = strlen(s);
    int left = len-1;   // 从右向左开始遍历
    int right = len-1;  // 从右向左开始遍历
    int tmp = 0;        // 目前指针的位置
    int index = 0;      // 索引记录
    char* ret = (char*)malloc(sizeof(char)*(len+1));        //1
    while(left>=0){
        if(s[left] == ' '){
            left--;                                         // 2
        }
        else{                                               // 3
            right = left;                                   // 4
            while(left >= 0 && s[left] != ' '){
                left--;                                     // 5
            }
            tmp = left+1;                                   // 6
            while(tmp <= right){                            // 7
                ret[index++] = s[tmp++];                    // 8
            }
                                                            // 9
            ret[index++] = ' ';                             // 10
        }
    }
    if(index>=1){                                           // 11
        ret[index-1]='\0';                                  // 12
    }
    else{
        ret = "";
    }
    return ret;
}

二、151翻转字符串里的单词(传送门)

char *reverseWords(char *s)
{
    int len = strlen(s);
    char *ans = (char *)malloc(sizeof(char) * (len + 1));
    int start = len - 1; // 从右向左开始遍历
    int end = len - 1;   // 从右向左开始遍历
    int current = 0;     // 目前指针的位置
    int index = 0;       // 索引记录
    // start指针从右向左遍历,最左边为0,最右边为len - 1
    while (start >= 0)
    {
        if (s[start] == ' ')
        {
            start--; // 从右向左遍历,遇到空格指针就继续往左移动一格
        }
        else // 从右向左遍历,遇到非空
        {
            end = start; // end指针赶紧来固定pin单词末尾的非空字母
            while (start >= 0 && s[start] != ' ')
            {
                start--; // start指针继续往前移动到该单词第一个字母之前一格(空格)
            }
            current = start + 1;   // current指针移动到该单词的第一个字母
            while (current <= end) // 开始遍历这个单词
            {
                /* 
                 * 把current到end俩指针区间(含)之间指向的单词从前往后拷贝到新数组ans中
                 * index为数组ans的指针,从0开始往后移动
                 */

                /*
                 * 对于a[i++]和a[++i]:
                 * i++是先使用i现在的值,再给i加1
                 * ++i是先给i加1,再用加1后的值
                 */
                ans[index++] = s[current++];
            }
            // ans[index + 1]出现blueisskyth(?)
            ans[index++] = ' '; // 每个单词加入后再加一个空格' ',然后index指针移动到下一位
        }
    }
   /*
    * 不考虑'\0'就会出现“执行出错”:
    * 在字符串数组的末尾加上'\0'表示字符串结束. 如果没有这个\0,那么在使用系统函数处理这个字符串的时候,函数就不能准确判断字符串在哪里结束.从而导致数组越界
    * 由于s中至少存在一个单词,所以index一定大于0
    */

    /*
     * 在ans[index++]中index已经赋值' '后又加了1,移动到下一位,等待被赋值
     * 替换掉最后的' '为'\0'
     */
    ans[index - 1] = '\0';  // 不是index,是index-1,回退到index上一位
    return ans;
}


总结

        两题差异:     

  • 58比第151题多了标点符号和普通字母一样处理,但标点符号不影响任何代码改变
  • 第151题题目中有这样一句话:s中至少存在一个单词,但是本题中没有,所以index要判断是否大于0,否则测试案例""无法通过(输入"",输出也应该为"",所以根本没进入while循环!)

        那么最后我们就不能像第151题那样写成:

ans[index - 1] = '\0'; 

         而是分支考虑index是否大于0

if (index >= 1)
    ans[index - 1] = '\0'; // 不是index,是index-1,回退到index上一位
else
    ans = "";

        由于第151题一定至少有一个单词,不可能有空字符串"",所以最后写成考虑分支index的代码第151题里也可以AC(空字符串不对其产生影响,其实只有一个分支起作用)


 

举报

相关推荐

0 条评论