字符串|反转字符串|反转字符串II |替换数字 |翻转字符串里的单词|右旋转字符串|实现 strStr()|字符串总结|双指针回顾

344.反转字符串

力扣题目链接(opens new window)

编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 char[] 的形式给出。

不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。

你可以假设数组中的所有字符都是 ASCII 码表中的可打印字符。

示例 1:
输入:["h","e","l","l","o"]
输出:["o","l","l","e","h"]

示例 2:
输入:["H","a","n","n","a","h"]
输出:["h","a","n","n","a","H"]

解题思路:

  • 双指针:定义两个指针一前一后,将指向的元素两两交换
  • 对于使用for循环,每个指针移动的范围小于数组长度的一半(奇数个偶数个均如此)     [ i < len/2 ]
  • 对于使用while循环,当两个指针相遇时(奇数个,left = right),或两个指针交错时(偶数个,left > right)退出循环,即循环条件是:while(left < right)
class Solution {
    public void reverseString(char[] s) {
        //双指针,一前一后,两两交换
        int left = 0;
        int right = s.length - 1;
        //当两个指针相遇或交错时退出循环
        while(left < right){
            //交换
            s[left] ^= s[right];//构造 a ^ b 的结果,并放在 a 中
            s[right] ^= s[left];//将 a ^ b 这一结果再 ^ b ,存入b中,此时 b = a, a = a ^ b
            s[left] ^= s[right];//a ^ b 的结果再 ^ a ,存入 a 中,此时 b = a, a = b 完成交换
            //移动两个指针
            left++;
            right--;
        }
    }
}

541. 反转字符串II

力扣题目链接(opens new window)

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

如果剩余字符少于 k 个,则将剩余字符全部反转。

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

示例:

输入: s = "abcdefg", k = 2
输出: "bacdfeg"

解题思路:

  • 按照传统的固定思维,遍历数组时,i每次只移动一个位置(即i++),如果本题这样逐个遍历,需要写很多逻辑代码,再搞一个计数器,来统计2k,再统计前k个字符,很麻烦
  • 其实在遍历字符串的过程中,只要让 i += (2 * k),i 每次移动 2 * k 就可以了,然后判断是否需要有反转的区间。
  • 需要反转的部分也就是每个2 * k 区间的起点,这样写,程序会高效很多
  • 所以当需要固定规律一段一段去处理字符串的时候,要想想在for循环的表达式上做做文章。

题目反转规则具体分析:

  • 1. 每隔 2k 个字符的前 k 个字符进行反转
  • 2. 剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符
  • 3. 剩余字符少于 k 个,则将剩余字符全部反 转
  • 三条规则可转换为一个判断条件:i + k < str.length()
  • 若满足,说明当前 i 的位置加上k后还没有超出数组长度,反转 i ~( i + k -1),包含条件1,2
  • 若不满足,说明 i+k 已经超过数组长度,即剩余字符不足k个,反转 i ~(str.length()-1 )

易错点:

  • String 在 Java 中是不可变的,意味着不能直接修改 String 对象的内容,需要将字符串转换为字符数组后作为参数传入 reverse 方法
  • i + k - 1 是前k个字符的最后一个字符的下标

class Solution {
    public String reverseStr(String s, int k) {
        char[] ch = s.toCharArray(); // 将字符串转换为字符数组
        // 每次移动 2*k 个位置
        for (int i = 0; i < ch.length; i += (2 * k)) {
            // 每个2 * k 区间的起点就是反转的起点
            // 判断从起点开始往后是否有k个字符
            if (i + k < ch.length) {
                // 有k个
                // 注意:i + k - 1 是前k个字符的最后一个字符
                reverse(ch, i, i + k - 1); 
            } else {
                // 不足k个
                reverse(ch, i, ch.length - 1);
            }
        }
        return ne
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值