小白视角刷leetcode (344. 反转字符串、541. 反转字符串II、 剑指Offer 05.替换空格、151. 反转字符串中的单词)

344. 反转字符串

编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。
​
不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。
思路:
    使用双指针,一个指向头部一个指向尾部,再定义一个char tmp用来交换
class Solution {
    public void reverseString(char[] s) {
        int l = 0;
        int r = s.length -1;
        while (l < r){
            char tmp = s[r];
            s[r] = s[l];
            s[l] = tmp;
            r--;
            l++;
        }
    }
}

541. 反转字符串II

给定一个字符串 s 和一个整数 k,从字符串开头算起,每计数至 2k 个字符,就反转这 2k 字符中的前 k 个字符。
​
如果剩余字符少于 k 个,则将剩余字符全部反转。
如果剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符,其余字符保持原样。
思路:
    1.对字符串进行操作,首先要把字符串转换成字符数组,用s.toCharArray()
    2.因为涉及到反转操作,因此单独写一个反转的函数,并且函数参数列表除了输入的数组外还要有两个指针,控制反转的边界
    3.因为每次计数都是2k,因此for循环里跳一次的步幅直接是2k
    4.本题核心就是对情况进行分类,不要考虑复杂,只考虑两种情况:
        (1)剩余字符个数小于k
        (2)剩余字符个数大于或等于k(str.length - i >= k,即当前索引遍历位置i+k小于等于str.length)
    5.两种情况的反转索引也不同:
        (1)如果剩余字符大于等于k个,则索引右边界为i+k-1
        (2)如果剩余字符小于k个,则右边界为str.length-1
class Solution {
    public String reverseStr(String s, int k) {
        char[] str = s.toCharArray();
        for(int i = 0 ;i < str.length ; i += 2 * k ){
            if( i + k <= str.length){//等同于 str.length - i >= k
                 reverse(str,i,i+k-1);
                 continue;
            }else{
                reverse(str,i,str.length-1);
            }
        }
        return new String(str);
    }
    public void reverse(char[] c ,int l , int r){
        while(l < r){
        char tmp = c[r];
        c[r] = c[l];
        c[l]=tmp;
        l++;r--;
        }
    }
}

剑指Offer 05.替换空格

请实现一个函数,把字符串 s 中的每个空格替换成"%20"。
​
示例 1: 输入:s = "We are happy."
输出:"We%20are%20happy.
思路:
    1.第一时间两种想法:
        (1)Stringbuilder创建一个数组,遍历字符串s.charAt(i),遇到空格append("%20")
        (2)创建一个当前字符串3倍容量的数组,遍历字符串s,遇到空格后向数组内连续添加三次元素,内容分别为%,2,0 ,但用这种方法时会发现,遍历用的索引一次走一步,但添加内容一次要添加三个元素,所以要单独新建一个索引用来添加元素
    2.对数组更新完后,需要重新新建一个字符串,并输入更新后数组的起始和结束位置,因为旧数组初始化时长度为原字符串长度的三倍,如果输出时不做截断,会把后边的空格一起输出,新建字符串的操作String str = new String(array,0,size),结束后return
class Solution {
    public String replaceSpace(String s) {
        int length = s.length();
        char[] array = new char[length * 3];
        int size = 0;//用size计数,因为在后边数组内添加元素时,索引位置跟i不同,所以要新建一个size充当新数组的索引
        for (int i = 0; i < length; i++) {
 
            if (s.charAt(i) == ' ') {//这里只能用单引号,单引号内装的是字符,双引号是字符串,char类型无法与字符串比对
                array[size++] = '%';
                array[size++] = '2';
                array[size++] = '0';
            } else {
                array[size++] = s.charAt(i);
            }
        }
        String newStr = new String(array,0,size);//后边要加数组的起始位置和结束位置,因为数组初始化时长度为三倍String,如果不用size截断,后边会输出空值
        return newStr;
    }
}

151. 反转字符串中的单词

给你一个字符串 s ,请你反转字符串中 单词 的顺序。
​
单词 是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的 单词 分隔开。
​
返回 单词 顺序颠倒且 单词 之间用单个空格连接的结果字符串。
​
注意:输入字符串 s中可能会存在前导空格、尾随空格或者单词间的多个空格。返回的结果字符串中,单词间应当仅用单个空格分隔,且不包含任何额外的空格
思路:
    首先把问题分为三步,也就是分成三个函数;此外由于是对字符串进行操作,首先第一步要把字符串转换成字符数组toCharArray
    1.去掉字符串的多余空格,包括字符串开头、结尾的以及字符串单词之间的;
        用到双指针思想,类似于利用双指针删除数组元素;for内用快指针遍历,遇到不是空格的元素先判断当前的慢指针是否指向的是数组开头元素,如果不是则需要添加空格,(不是则可以直接赋值,因此不需要再做判断),while内做当前单词的赋值,如果循环不满足while条件代表当前单词已经移动完成,跳出while循环,继续用for循环移动快指针,遇到空格则不进入循环体,直到又遇到非空格元素,进入循环体后再判断当前慢指针是否指向头部,(显然经过上边的步骤当前已经不是了),因此慢指针处插入一个空格后++移动,然后再进入while对当前单词进行逐步移动赋值,依次循环
    2.反转全部字符
        创建一个reverse函数,用来反转字符,但由于本题还需要反转每个单词的字符,因此在定义反转函数时,参数列表要加入反转的起始和结束位置,反转函数没什么特殊可说的,常规操作
    3.反转每个单词内的字符
        需要调用reverse函数,在调用时输入参数,当前单词的起始和结束位置,因此本函数最重要的point在于确定传入实参的指针,显然传入两个实参就要两个指针,一个指向当前单词的首位,一个指向末尾,for循环遍历字符时,若尾指针遇到空格,则传入尾指针为尾指针-1;若尾指针已经指向末尾,则传入实参的尾指针为尾指针本身
class Solution {
    public String reverseWords(String s) {
        char[] ch = s.toCharArray();
        ch = DropSpace(ch);
        reverse(ch,0,ch.length-1);
        WordReverse(ch);
        return new String(ch);
​
    }
    public char[] DropSpace(char[] ch){
        int left = 0 ;
        int right = 0;
        for ( ; right < ch.length; right++ ){
            if(ch[right] != ' '){//遇到空格不执行,继续向后遍历,直到遇到新单词
                if(left != 0) ch[left++] = ' ';//单独判断当前左指针是否指向数组开头,如果不是则添加空格,用于间隔开单词
                }
                while(right < ch.length && ch[right] != ' '){//当遇到空格后会跳出while循环,进入下一次for循环
                    ch[left++] = ch[right++];//把空格后的单词逐一赋给左指针++
                }//跳出while循环即代表当前单词移位完成,进入下一次for循环,遇到空格则继续跳,直到不是空格才进入for
        }
        char[] newchar = new char[left];//数组在删除空格后,长度会变短,但由于双指针操作没用到第二个数组,因此left后还会有旧数组残留的元素,所以要新建一个数组,把旧数组的内容移过去
        System.arraycopy(ch,0,newchar,0,left);
        return newchar;
    }
    public void reverse(char[] ch,int l,int r){//除数组外还要传入两个指针,在后边进行单词内翻转时会用到
        if(r >= ch.length) return;
        while( l < r){
            char tmp = ch[r];
            ch[r] = ch[l];
            ch[l] = tmp;
            l++;r--;
        }
    }
    public void WordReverse(char[] ch){
        int left = 0;
        for(int right=0 ; right < ch.length ;right++){
            if(ch[right] == ' '){
                reverse(ch,left,right-1);
                left = right +1;
            }else if (right == ch.length-1){
                reverse(ch,left,right);
            }
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小刘成长日记

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值