代码随想录算法训练营第八天| 344. 反转字符串,541. 反转字符串II,剑指Offer05. 替换空格,151. 翻转字符串里的单词,剑指Offer58-II.左旋转字符串

344. 反转字符串

建议: 本题是字符串基础题目,就是考察reverse函数的实现,同时也明确一下平时刷题什么时候用库函数,什么时候不用库函数 

题目链接/文章讲解/视频讲解:代码随想录

重点:

1. 双指针

public static void reverseString(char[] s) {
        int left = 0;
        int right = s.length - 1;
        while (left < right) {
            char temp = s[left];
            s[left] = s[right];
            s[right] = temp;
            left++;
            right--;
        }
}

541. 反转字符串II

建议:本题又进阶了,自己先去独立做一做,然后在看题解,对代码技巧会有很深的体会。 

题目链接/文章讲解/视频讲解:代码随想录

重点:

1. 每2k个字符处理一次,所以只要循环的时候 i += (2 * k) 就可以了

2. 所以当需要固定规律一段一段去处理字符串的时候,要想想在在for循环的表达式上做做文章。

public static String reverseStr(String s, int k) {
        char[] chars = s.toCharArray();
        // 每2k个操作一次
        for (int i = 0; i < chars.length; i += 2 * k) {
            // 左闭右闭规则
            int startIndex = i;
            // 这里是判断尾数够不够k个来取决end指针的位置
            int endIndex = Math.min(startIndex + k - 1, chars.length - 1);
            while (startIndex < endIndex) {
                char temp = chars[startIndex];
                chars[startIndex] = chars[endIndex];
                chars[endIndex] = temp;
                startIndex++;
                endIndex--;
            }
        }
        return new String(chars);
}

剑指Offer 05.替换空格

建议:对于线性数据结构,填充或者删除,后序处理会高效的多。好好体会一下。

题目链接/文章讲解:代码随想录

重点:

1. 直接使用StringBuilder进行模拟操作

2. 双指针

思路:

1. 单线程,直接使用StringBuilder进行模拟操作,append

2. 双指针:

(1) 先把字符串扩容多空格数量的两倍

(2) 定义两个指针,左指针为原始字符串的最后一个位置,右指针为新字符串的最后一个位置

(3) 如果当前左指针的字符不是空格,则右指针的位置放入这个字符,左右指针同时向前移动一位

(4) 如果当前左指针的字符为空格,则左指针保持不动先,把右指针的字符一个一个向前替换三次,然后左右指针再同时向前移动一位

// 模拟操作
public static String replaceSpace(String s) {
        if (s == null) {
            return null;
        }
        StringBuilder stringBuilder = new StringBuilder(s);
        for (int i = 0; i < s.length(); i++) {
            if (s.charAt(i) == ' ') {
                stringBuilder.append("%20");
            } else {
                stringBuilder.append(s.charAt(i));
            }
        }
        return stringBuilder.toString();
}
// 双指针
    public static String replaceSpace(String s) {
        if (s == null || s.length() == 0) {
            return s;
        }
        StringBuilder stringBuilder = new StringBuilder();
        // 统计要新增多少个字符
        for (int i = 0; i < s.length(); i++) {
            if (s.charAt(i) == ' ') {
                stringBuilder.append("  ");
            }
        }
        // 说明没有空格要替换
        if (stringBuilder.length() == 0) {
            return s;
        }
        // 有空格的情况
        // left指向原字符串的最后一位
        int left = s.length() - 1;
        s += stringBuilder.toString();
        // right指向替换完毕后字符串的最后一位
        int right = s.length() - 1;
        char[] chars = s.toCharArray();
        while (left >= 0)  {
            // 如果left所指的字符为空格,right一个一个向前进行替换
            if (chars[left] == ' ') {
                chars[right--] = '0';
                chars[right--] = '2';
                chars[right] = '%';
            } else {
                chars[right] = chars[left];
            }
            left--;
            right--;
        }
        return new String(chars);
}

151.翻转字符串里的单词

建议:这道题目基本把刚刚做过的字符串操作都覆盖了,不过就算知道解题思路,本题代码并不容易写,要多练一练。 

题目链接/文章讲解/视频讲解: 代码随想录

重点:

1. 先整体反转再局部反转

思路:

1. 先去除空格,再反转字符串,接着反转单词

public static String reverseWords(String s) {
        // 1. 去除首尾以及中间多余空格
        StringBuilder stringBuilder = removeSpace(s);
        // 2. 反转整个字符串
        reverseString(stringBuilder, 0, stringBuilder.length() - 1);
        // 3. 反转各个单词
        reverseEachWord(stringBuilder);
        return stringBuilder.toString();
}

private static StringBuilder removeSpace(String s) {
        int start = 0;
        int end = s.length() - 1;
        // 去头空格
        while (s.charAt(start) == ' ') {
            start++;
        }
        // 去尾空格
        while (s.charAt(end) == ' ') {
            end--;
        }
        // 去中间空格
        StringBuilder stringBuilder = new StringBuilder();
        while (start <= end) {
            char c = s.charAt(start);
            // stringBuilder.charAt(stringBuilder.length() - 1) != ' '
            // 为的是保证每个单词之间都有一个空格
            if (c != ' ' || stringBuilder.charAt(stringBuilder.length() - 1) != ' ') {
                stringBuilder.append(c);
            }
            start++;
        }
        return stringBuilder;
}

public static void reverseString(StringBuilder stringBuilder, int start, int end) {
        // 将整个字符串反转
        while (start < end) {
            char temp = stringBuilder.charAt(start);
            stringBuilder.setCharAt(start, stringBuilder.charAt(end));
            stringBuilder.setCharAt(end, temp);
            start++;
            end--;
        }
}

private static void reverseEachWord(StringBuilder stringBuilder) {
        // 一个单词一个单词反转
        int start = 0;
        int end = 1;
        int length = stringBuilder.length();
        while (start < length) {
            while (end < length && stringBuilder.charAt(end) != ' ') {
                end++;
            }
            reverseString(stringBuilder, start, end - 1);
            start = end + 1;
            end = start + 1;
        }
}

剑指Offer58-II.左旋转字符串

建议:题解中的解法如果没接触过的话,应该会想不到
题目链接/文章讲解: 代码随想录

重点:

1. 先局部反转再整体反转

思路:

1. 反转前n个字符

2. 反转n+1到最后一个字符

3. 反转0到最后一个字符

public static String reverseLeftWords(String s, int n) {
        // 1. 反转区间为前n的子串
        int len = s.length();
        StringBuilder stringBuilder = new StringBuilder(s);
        reverseString(stringBuilder, 0, n - 1);
        // 2. 反转区间为n到末尾的子串
        reverseString(stringBuilder, n, len - 1);
        // 3. 反转整个字符串
        return stringBuilder.reverse().toString();
}

private static void reverseString(StringBuilder stringBuilder, int start, int end) {
        while (start < end) {
            char temp = stringBuilder.charAt(start);
            stringBuilder.setCharAt(start, stringBuilder.charAt(end));
            stringBuilder.setCharAt(end, temp);
            start++;
            end--;
        }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值