首页 > 其他分享 >剑指 Offer 58 - I. 翻转单词顺序

剑指 Offer 58 - I. 翻转单词顺序

时间:2023-05-25 12:03:44浏览次数:42  
标签:空格 58 idx Offer 单词 start str 字符串 翻转

剑指 Offer 58 - I. 翻转单词顺序

</br></br>

题目:

输入一个英文句子,翻转句子中单词的顺序,但单词内字符的顺序不变。为简单起见,标点符号和普通字母一样处理。例如输入字符串"I am a student. ",则输出"student. a am I"。

示例1:

输入: "the sky is blue"
输出: "blue is sky the"

示例2:

输入: "  hello world!  "
输出: "world! hello"
解释: 输入字符串可以在前面或者后面包含多余的空格,但是反转后的字符不能包括。

示例3:

输入: "a good   example"
输出: "example good a"
解释: 如果两个单词间有多余的空格,将反转后单词间的空格减少到只含一个。

说明:

  • 无空格字符构成一个单词。

  • 输入字符串可以在前面或者后面包含多余的空格,但是反转后的字符不能包括。

  • 如果两个单词间有多余的空格,将反转后单词间的空格减少到只含一个。

</br></br>

思路一:

逆序双指针

1.用n记录当前字符串长度,再开辟一个新的字符串str用来存放逆序遍历到的单词;

2.逆序遍历,当字符不为空格时,使用right记录下当前i的位置,然后i--向前查找下一个空格,当s[i] == ' '时,可以通过right - i得到当前单词的长度,i + 1得到单词的首字母,通过substr函数将该单词放到新的字符串str中;

3.当我们逆序遍历完成之后,得到新的字符串,此时str已经是原来字符串翻转后形成的,但是要注意的是,使用str += s.substr(i + 1, right - i) + " "str中追加最后一个单词时,空格也被放到了里面,所以要单独对最后一个空格进行处理;

  • 可以使用substr函数进行处理即return str.substr(0,str.size() - 1)

  • 也可以使用erase函数删除最后一个空格,但是此时要判断str是否为空字符串,避免erase时数组越界;

  • 还可以使用pop_back函数直接尾删掉最后一个字符。

我们以字符串we are family为例,头部两个空格,arefamily中间三个空格,尾部三个空格。具体过程可参考下图:

image-20230525101542982

代码如下:

class Solution {
public:
    string reverseWords(string s) {
        int n = s.size(); 
        string str;//string类默认值为空
        //从结尾开始向前遍历,这样的话不用翻转,单词顺序直接就是翻转后的
        for(int i = n - 1; i >= 0; i--)
        {
            //当s[i]不为空时,追加到新字符串
            if(s[i] != ' ')
            {
                int right = i;//记录此时i的位置
                while( i >= 0 && s[i] != ' ' ) //要注意这里条件的先后顺序
                {
                    i--;
                }
                //right - i 计算的是字符长度
                //s[i]此时为空格,i+1就是单词的首个字符
                str += s.substr(i + 1, right - i) + " "; 
            }
        }
        //最后这里的str字符串最后一个元素为空格
        // 1.  return str.substr(0,str.size() - 1);
        
        //3. str.pop_back();
        //	return str;
        
        //2.
        if(str == "") //还要考虑当字符串为空的情况
            return str;
        str.erase(str.size() - 1, 1);
        return str;
    }
};

时间复杂度:O(N)

空间复杂度:O(N)

</br></br>

思路二:

通过三个指针对原子符串进行修改从而实现翻转单词顺序。

1.先将整个字符串翻转;

2.设置一个变量idx用来将单词从头开始填入字符串,设置变量start从头开始找,当s[start] != ' '时,说明此时为单词的头部,向后遍历,当s[end] != ' '时找到单词结尾,通过reverse(s.begin() + idx - (end -start), s.begin() + idx);对单词进行翻转;

3.start = end;更新start,并找下一个单词……当idx != 0时说明已经插入了单词需要添加空格s[idx++] = ' '

4.当字符串中单词找完,即循环结束之后,s.erase(s.begin() + idx,s.end());删除idx开始的往后的字符,因为原字符串中的单词已经通过循环放到了前面。

我们以字符串we are family为例,头部两个空格,arefamily中间三个空格,尾部三个空格。具体过程可参考下图:

image-20230525112304216

代码如下:

class Solution {
public:
    string reverseWords(string s) {
        //直接翻转整个字符串
        reverse(s.begin(),s.end());

        int n = s.size();
        int idx = 0; //用来记录单词和给空格
        for(int start = 0; start < n; start++)
        {
            //当s[start]不等于空格时记录单词
            if(s[start] != ' ')
            {
                //当idx不等于0时,说明此时字符串已经完成了一个单词的写入,所以要加上空格
                if(idx != 0) 
                    s[idx++] = ' ';
                
                //开始向后遍历,找到单词的结尾
                int end = start;
                while(end < n && s[end] != ' ')
                    s[idx++] = s[end++];
                
                //单词写入之后对这个单词进行翻转
                reverse(s.begin() + idx - (end -start), s.begin() + idx);

                //再更新start,找下一个单词
                start = end;
            }
        }
        //将从idx开始的往后的字符全部删除
        s.erase(s.begin() + idx,s.end());
        return s;
    }
};

时间复杂度:O(N)

空间复杂度:O(1)

标签:空格,58,idx,Offer,单词,start,str,字符串,翻转
From: https://blog.51cto.com/u_15562309/6346384

相关文章

  • IEC 60958 && IEC 61937
    IEC60958&&IEC61937IEC60958IEC60958是一种传递数字音频的接口规范,相比I2S,IEC60958通过一根线同时传递时钟信号和数据信号。IEC60958用来传递两channel,16/20/24bits采样深度的PCM数据。IEC60958在传输数据时使用双相符号编码(BiphaseMarkCode),简称BMC,属于一种相位......
  • 剑指 Offer 56 - II. 数组中数字出现的次数 II
    题目描述:在一个数组 nums 中除一个数字只出现一次之外,其他数字都出现了三次。请找出那个只出现一次的数字。   int[]counts=newint[32];for(inti=0;i<nums.length;i++){for(intj=0;j<32;j++){counts[j]+=nums[i]&1;//更新......
  • 剑指 Offer 56 - I. 数组中数字出现的次数
    题目描述:一个整型数组 nums 里除两个数字之外,其他数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度是O(1)。  设 nums=[3,3,4,4,1] ,以上计算流程如下图所示。 本题难点: 数组 nums 有 两个 只出现一次的数字,因此无法通......
  • 58个分类背单词英语词典ACCESS\EXCEL数据库
    英语词典、背单词类的数据已经发了很多很多了,打算今天这一个将是最后一个了,后续没有颠覆性的好的话就不再发这类数据了,今天这一份的背单词数据库好处是有58个分类,之前发过有27个分类的《1万6千多最好的背单词SQLITE数据库》。单词表:36238条记录,可以看一下word_root_id字段的作用......
  • 剑指 Offer II 018(Java). 有效的回文(简单)
    题目:给定一个字符串s,验证s 是否是 回文串 ,只考虑字母和数字字符,可以忽略字母的大小写。本题中,将空字符串定义为有效的 回文串 。 示例1:输入:s="Aman,aplan,acanal:Panama"输出:true解释:"amanaplanacanalpanama"是回文串示例2:输入:s="raceacar"......
  • 【剑指offer】-栈的压入、弹出序列-20/67
    1.题目描述输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:这两个序列的......
  • 【剑指offer】-把二叉树打印成多行-43/67
    1.题目描述从上到下按层打印二叉树,同一层结点从左至右输出。每一层输出一行。2.题目分析非常经典的一道二叉树的题目,做这道题之前需要掌握二叉树的思想和BFS(广度优先搜索、队列思想)我们可以回顾一下最基本的层次遍历,我们是用一个队列来进行存储初始root结点,然后依次放入root的......
  • 【剑指offer】- 求1+2+3+...+n -47/67
    1.题目描述求1+2+3+…+n,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)。2.题目分析对于这种求1+2+3+…+n的题,我们可以采取3中方法第一种:直接利用等差数列的思想来进行求和return(1+n)*n/2;第二种:利用迭代的思想进行求和intres=......
  • 【剑指offer】- 数组中重复的数字 -48/67
    1.题目描述在一个长度为n的数组nums里的所有数字都在0~n-1的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。示例1:输入:[2,3,1,0,2,5,3]输出:2或32.题目分析此题考查的是面试者的沟通能力,......
  • 图解LeetCode——剑指 Offer 34. 二叉树中和为某一值的路径
    一、题目给你二叉树的根节点root和一个整数目标和targetSum,找出所有从根节点到叶子节点路径总和等于给定目标和的路径。叶子节点是指没有子节点的节点。二、示例2.1>示例1:【输入】root=[5,4,8,11,null,13,4,7,2,null,null,5,1],targetSum=22【输出】[[5,4,11,2],[5,......