【算法day8】字符串:344.反转字符串 541.反转字符串II 剑指offer05.替换空格 151.旋转字符串里的单词 剑指offer58II.左旋转字符

344.反转字符串

编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。
不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。

思路
双指针就可以原地完成反转

Java代码

public void reverseString(char[] s) {
    //初始化双指针
    int i = 0;//指向第一个元素
    int j = s.length - 1;//指向最后一个元素
    while(i < j) {//两指针交换元素的值
        char temp = ' ';
        temp = s[i];
        s[i] = s[j];
        s[j] = temp;
        i++;
        j--;
    }
}

541.反转字符串II

给定一个字符串 s 和一个整数 k,从字符串开头算起,每计数至 2k 个字符,就反转这 2k 字符中的前 k 个字符。

  • 如果剩余字符少于 k 个,则将剩余字符全部反转。
  • 如果剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符,其余字符保持原样。

示例 1:
输入: s = “abcdefg”, k = 2
输出: “bacdfeg”
示例 2:
输入: s = “abcd”, k = 2
输出: “bacd”

思路
每计数至2k个字符,所以让指针每次跨越2k个字符,反转这2k个字符的前k个字符。
例如下面的a b c d e f g字符串,当 k = 2 时:

image.png

先反转该字符串的第1个字符a和第2个字符b,前4个元素就执行完毕了,接着反转后面的元素,由于剩下3个元素,根据题意,就反转前2个,也就是e和f,至此交换结束。

所以我们可以定义一个反转字符串的方法,上面的344.反转字符串正是我们需要的方法,可以加上两个参数,分别是反转区间的开头和结束的索引,可以大大方便反转的操作。下面的reverse方法就是反转字符串某段区间的方法。

String转为StringBuffer是为了可以直接利用StringBuffer
setCharAt(int index,char x)方法。

Java代码

public String reverseStr(String s, int k) {
    //将String转为StringBuffer便于调用方法
    StringBuffer sb = new StringBuffer(s);
    int i = 0;
    int l = sb.length();
    while(i < l) {
        if(l - i < k) {//剩下元素小于k个 全部反转
            reverse(sb,i,l-1);
        }
        else{
            reverse(sb,i,i+k-1);//反转前k个元素
        }
        i += 2 * k;
    }
    return sb.toString();
}
//反转 StringBuffer 第 i-1 个至第 j-1 个字符的方法
private void reverse(StringBuffer temp,int i,int j) {
    while(i >= 0 && j > 0 && i < j && j < temp.length()) {
        char t = temp.charAt(i);
        temp.setCharAt(i,temp.charAt(j));
        temp.setCharAt(j,t);
        i++;
        j--;
    }
}

剑指offer05.替换空格

请实现一个函数,把字符串 s 中的每个空格替换成"%20"。

思路
这道题没有要求原地排序,索引 可以借助一个StringBuffer,遍历字符串s依次把s中的字符添加到StringBuffer中,如果是空格,则加入%20

Java代码

public String replaceSpace(String s) {
        StringBuffer sb = new StringBuffer();
        for(int i = 0; i < s.length(); i++) {
            if(s.charAt(i) != ' ') {
                sb.append(s.charAt(i));
            }
            else {
                sb.append("%20");
            }
        }
        return sb.toString();
    }

151.反转字符串里的单词

给你一个字符串 s ,请你反转字符串中 单词 的顺序。

单词 是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的 单词 分隔开。

返回 单词 顺序颠倒且 单词 之间用单个空格连接的结果字符串。

注意: 输入字符串 s中可能会存在前导空格、尾随空格或者单词间的多个空格。返回的结果字符串中,单词间应当仅用单个空格分隔,且不包含任何额外的空格。

示例 1:
输入: s = “the sky is blue”
输出: “blue is sky the”
示例 2:
输入: s = " hello world "
输出: “world hello”
解释: 反转后的字符串中不能存在前导空格和尾随空格。
示例 3:
输入: s = “a good example”
输出: “example good a”
解释: 如果两个单词间有多余的空格,反转后的字符串需要将单词间的空格减少到仅有一个。

思路
本题把前面几题对字符串的操作都覆盖了。
这道题,想一想,如果把整个字符串反过来,单词的顺序确实是反了,
但是每个单词的字母也反了,那么再将每个单词反过来不就正回来了。
当然,应该先去一下多余的空格。

分三步走:

1. 去除多余的空格
2. 将整个字符串反转
3. 将每个单词反转

例如:
原字符串是 " you are cute "
1. 去除多余的空格:“you are cute”
2. 将整个字符串反转:“etuc era uoy”
3. 将每个单词反转:“cute are you”

这三步每一步都设为一个方法

Java代码

public String reverseWords(String s) {
    StringBuffer sb = new StringBuffer(s);
    //去掉多余空格 例如 " love  you  " --> "love you"
    sb = deleteSpace(sb);
    //反转整个字符串 例如"love you"-->"uoy evol"
    reverse(sb,0,sb.length()-1);
    //反转字符串里面的单词 例如"uoy evol"-->"love you"
    wordsReverse(sb);
    return sb.toString();
}
//去点多余空格 例如 " love  you  "-->"love you"
private StringBuffer deleteSpace(StringBuffer sb) {
    int wordNum = 0;
    int fast = 0;
    int length = sb.length();
    StringBuffer newSb = new StringBuffer();
    while(fast < length) {
        if(sb.charAt(fast) != ' ') {//指到字母
            //在添加单词前添加空格(已添加单词数为0就不添加空格)
            if(wordNum != 0) {
                newSb.append(' ');
            }
            while (fast < length && sb.charAt(fast) != ' ') {
                //添加一个字母
                newSb.append(sb.charAt(fast));
                //往后走
                fast++;
            }
            wordNum++;//当前单词字母添加结束 数量+1
        }
        else {//指到空格 直接往后走
            fast++;
        }
    }
    return newSb;
}
//反转字符串某个区间 
private void reverse(StringBuffer sb,int left,int right) {
    while (left < right) {
        char temp = sb.charAt(left);
        sb.setCharAt(left,sb.charAt(right));
        sb.setCharAt(right,temp);
        left++;
        right--;
    }
}
//反转字符串里面的每个单词
private void wordsReverse(StringBuffer sb) {
    int left = 0;
    int right = 0;
    while (right < sb.length()) {
        if(sb.charAt(right) != ' ') {
            left = right;//记下单词的开头索引
            while (right < sb.length() && sb.charAt(right) != ' ') {
                right++;//单词最后的索引
            }
            reverse(sb,left,right-1);
        }
        right++;
    }
}

剑指offer58II.左旋转字符

字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串左旋转操作的功能。比如,输入字符串"abcdefg"和数字2,该函数将返回左旋转两位得到的结果"cdefgab"。

示例 1:
输入: s = “abcdefg”, k = 2
输出: “cdefgab”
示例 2:
输入: s = “lrloseumgh”, k = 6
输出: “umghlrlose”

思路
分别反转,再全部反转。
例如 原字符串为 "hello"k=2:
分别反转,也就是反转前2个字母和后3个字母得到:"eholl"
再全部反转得到:"llohe"

前面的题目用过多次的反转字符串某个区间的方法在这里还是能使用

Java代码

     public String reverseLeftWords(String s, int n) {
        //转为StringBuilder是为了
        //后面直接使用其reverse()方法(将整个StringBuilder反转的方法)
        StringBuilder sb = new StringBuilder(s);
        //反转前n个字符
        reverse(sb,0,n-1);
        //反转后面剩下所有字符
        reverse(sb,n,s.length()-1);
        //全部反转 然后toString()返回
        return sb.reverse().toString();
     }
    //反转字符串某个区间的方法
    private void reverse(StringBuilder sb, int i, int j) {
        while(i < j) {
            char temp = sb.charAt(i);
            sb.setCharAt(i,sb.charAt(j));
            sb.setCharAt(j,temp);
            i++;
            j--;
        }
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

CrazyJavaCoder

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

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

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

打赏作者

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

抵扣说明:

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

余额充值