Leetcode刷题day8|344.反转字符串, 541. 反转字符串II, 剑指Offer 05.替换空格, 151.翻转字符串里的单词, 剑指Offer58-II.左旋转字符串

一、反转字符串

题目链接

思路分析

双指针,一首一尾,同时移动。循环终止条件为两者不相遇,其实这个问题也可以被归纳为二分问题。

AC代码

class Solution {
    public void reverseString(char[] s) {
        int left=0;
        int right=s.length-1;
        while(left<right){
            swap(s,left,right);
            left++;
            right--;
        }
    }
    private void swap(char[] s,int a,int b){
        char tmp=s[a];
        s[a]=s[b];
        s[b]=tmp;
    }
}

二、反转字符串II

题目链接

思路分析

本题实际上就是第一道题的拓展,还是转成字符数组,只不过是分组反转。那么问题的关键就在于我们怎么实现分组?

可以使用for循环控制,关键是循环头部的三条语句。判断条件是不到字符串的末尾,最为关键的就是每次循环之后循环变量的改变——i+=2*k;

循环体内部left每次初始值均为left,right是字符串末尾和left+k-1的较小值。

AC代码

class Solution {
    public String reverseStr(String s, int k) {
        char[] ch=s.toCharArray();
        for(int i=0;i<ch.length;i+=2*k){//注意这句
            int left=i;//注意这里的赋值
            int right=Math.min(ch.length-1,left+k-1);//注意这句
            while(left<right){
                swap(ch,left,right);
                left++;
                right--;
            }
        }
        return new String(ch);
    }
    private void swap(char[] s,int a,int b){
        char tmp=s[a];
        s[a]=s[b];
        s[b]=tmp;
    }
}

三、替换空格

题目链接

思路分析

思路一:使用标准库函数中的replace函数s.replace(" “,”%20);

思路二:将字符串转换成为StringBuilder,进行遍历,之后使用sb.toString方法

思路三【重点理解】:使用双指针。根据空格的数量对转化出来的字符数组进行扩容。注意此时的指针一个指向原来的尾巴,一个指向扩容后的尾巴,对字符数组进行原地修改。

图示分析

这里思路三可能比较难理解,我们主要就这个解法进行解释。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-N86fLp9b-1672995810703)(F:\typora插图\image-20230106160520583.png)]

AC代码

class Solution {
    public String replaceSpace(String s) {
        return s.replace(" ","%20");
    }
}
class Solution {
    public String replaceSpace(String s) {
        StringBuilder sb=new StringBuilder();
        char[] ch=s.toCharArray();
        for(int i=0;i<ch.length;i++){
            if(ch[i]==' '){
                sb.append("%20");
            }else{
                sb.append(ch[i]);
            }
        }
        return sb.toString();
    }
}
class Solution {
    public String replaceSpace(String s) {
        char[] ch=s.toCharArray();
        int left=ch.length-1;
        //统计空格的个数,用于确定数组扩容
        int cnt=0;
        for(int i=0;i<ch.length;i++){
            if(ch[i]==' '){
                cnt++;
            }
        }
        ch=Arrays.copyOf(ch,ch.length+2*cnt);
        
        int right=ch.length-1;
        while(left>=0){
            if(ch[left]==' '){
                ch[right--]='0';
                ch[right--]='2';
                ch[right--]='%';
            }else{
                ch[right--]=ch[left];
            }
            left--;
        }
        return new String(ch);
    }
}

四、翻转字符串里的单词

题目链接

思路分析

思路一:使用标准库函数split得到字符串数组,然后对单词倒序相加。需要注意的是,想通过trim来替代去除多余空格的功能是不可行的,因为它只能去除首尾的,这里中间可能有多个但是最终结果只能有一个。

思路二:不使用额外辅助空间,原地修改。移除多余空格—>将整个字符串反转---->对每个单词进行反转。

另外,这里的删除多余空格其实整体逻辑和我们之前原地删除重复元素思路是类似的;同时这里的reverseString,是对指定StringBuilder对象的指定区域反转,以后可能会经常用到。

AC代码

class Solution {
    public String reverseWords(String s) {
        StringBuilder sb=removeSpace(s);
        reverseString(sb,0,sb.length()-1);
        reverseEachWord(sb);
        return sb.toString();
    }
    private StringBuilder removeSpace(String s){
        int start=0;
        int end=s.length()-1;
        while(s.charAt(start)==' '){
            start++;
        }
        while(s.charAt(end)==' '){
            end--;
        }
        StringBuilder sb=new StringBuilder();
        while(start<=end){
            char c=s.charAt(start);
            //重点理解这里删除元素的逻辑【类比之前数组的删除元素】
            if(c != ' ' || sb.charAt(sb.length() - 1) != ' ') sb.append(c);
            start++;
        }
        return sb;
    }
    private void reverseString(StringBuilder sb,int start,int end){
        while(start<=end){
            char tmp=sb.charAt(start);
            sb.setCharAt(start,sb.charAt(end));
            sb.setCharAt(end,tmp);
            start++;
            end--;
        }
    }
    private void reverseEachWord(StringBuilder sb){
        int start=0;
        int end=1;
        int n=sb.length();
        while(start<n){
            while(end<n&&sb.charAt(end)!=' '){
                end++;
            }
            reverseString(sb,start,end-1);
            start=end+1;
            end=start+1;
        }
    }
}

五、左旋字符串

题目链接

思路分析

思路一:使用标准库中的substring函数

思路二:先整体反转,再反转两个区间:0~len-1-n个 and len-n~len-1个字符。此时空间复杂度为O(1)

AC代码

class Solution {
    public String reverseLeftWords(String s, int n) {
        return s.substring(n)+s.substring(0,n);
    }
}
class Solution {
    public String reverseLeftWords(String s, int n) {
        char[] chars = s.toCharArray();
        reverse(chars, 0, chars.length - 1);
        reverse(chars, 0, chars.length - 1 - n);
        reverse(chars, chars.length - n, chars.length - 1);
        return new String(chars);
    }

    public void reverse(char[] chars, int left, int right) {
        while (left < right) {
            chars[left] ^= chars[right];
            chars[right] ^= chars[left];
            chars[left] ^= chars[right];
            left++;
            right--;
        }
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值