代码随想录刷题day08|反转字符串&反转字符串里面的单词&替换数字&右旋转字符串


day08学习内容

day08主要内容

  • 反转字符串
  • 反转字符串2
  • 替换数字
  • 翻转字符串里面的单词
  • 右旋转字符串

一、 反转字符串

344原题链接

核心思路

1、很简单的一题,没啥好说的
2、记录一下异或的用法,第一次见

1.正确写法1

class Solution {
    public 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--;
        }
    }
}


2.正确写法–使用异或

class Solution {
    public void reverseString(char[] s) {
        int l = 0;
        int r = s.length - 1;
        while (l < r) {
            s[l] ^= s[r];  
            s[r] ^= s[l];  
            s[l] ^= s[r];  
        	//等价于下面的写法
            //s[l] = (char) (s[l]^ s[r]);
            //s[r] = (char) (s[r]^s[l]);
            //s[l] = (char) (s[l]^s[r]);
            l++;
            r--;
        }
    }
}

怎么理解上面的代码

  1. 初始化指针
    1.1.int l = 0;:左指针l指向数组的第一个字符。
    1.2.int r = s.length - 1;:右指针r指向数组的最后一个字符。
  2. 循环条件:while (l < r) 确保左指针始终小于右指针。当这两个指针相遇或交错时,数组已经完全反转。
  3. 交换字符
    3.1. s[l] ^= s[r];:对s[l]和s[r]进行异或运算,并将结果存储在s[l]中。此时,s[l]存储了s[l]和s[r]的异或结果。
    3.2. s[r] ^= s[l];:用s[l](现在包含s[l]和s[r]的异或结果)与s[r]进行异或运算,并将结果存储在s[r]中。此时,s[r]存储了原始的s[l]值。
    3.3. s[l] ^= s[r];:再次用s[r](现在包含原始的s[l]值)与s[l]进行异或运算,并将结果存储在s[l]中。此时,s[l]存储了原始的s[r]值,从而完成了两个字符的交换。
  4. 移动指针
    4.1. l++;:左指针向右移动一位。
    4.2. r–;:右指针向左移动一位。
  5. 重复:当左指针小于右指针时,重复上述交换和移动指针的步骤,直到整个数组被反转。

再来个demo

public class Example {  
    public static void main(String[] args) {  
        // 定义两个整数  
        int a = 5; // 二进制表示为 0101  
        int b = 10; // 二进制表示为 1010  
  
        // 对两个整数进行异或操作  
        int result = a ^ b;  
  
        // 输出结果  
        System.out.println("异或结果: " + result); // 输出 15,二进制表示为 1111  
    }  
}

2.1. 这样写的好处是?

这个异或操作被用来在不使用临时变量的情况下交换两个字符。通过连续三次异或同一个值(在这种情况下是 s[r]),s[l] 的原始值会被恢复并存储在 s[r] 中,而 s[r] 的原始值则会被存储在 s[l] 中,从而完成了两个字符的交换。
这种方法避免了使用额外的内存空间来存储临时值


二、反转字符串2

541原题链接

思路

  1. 怎么每隔2K个元素计数一次
  2. 怎么反转这2k字符中的前 k个字符。
  3. 怎么判断剩余字符少于 k 个
  4. 怎么判断剩余字符小于 2k 但大于或等于 k 个

1.正确写法1

class Solution {
  public String reverseStr(String s, int k) {
      if (s.length() < 2) return s;
      char[] c = s.toCharArray();        
      for (int i = 0; i < s.length(); i += 2*k) {
          //这里说明剩余字符数小于k个。
          if (i + k > s.length()) {
              reverse(c, i, s.length() - 1);
              break;
          }
          //反转前k个
          reverse(c, i, i + k - 1);
      }       
      return new String(c);
  }
  
  public void reverse(char[] ch, int start, int end) {
    while (start < end) {
          char t = ch[start];
          ch[start] = ch[end];
          ch[end] = t;
          end--;
          start++;
      }
  }
}

1.1.为什么i + k > s.length()表示剩余字符少于 k 个

很简单,这个条件i + k > s.length()意味着从索引i开始到字符串末尾的字符数不足k个。换句话说,如果我们尝试从索引i开始反转k个字符,我们将超出字符串的边界。因此,我们需要反转从索引i到字符串末尾的所有字符,并终止循环。
举个例子
假设s = “abcdefg"且k = 3。
当i = 0时,i + k = 0 + 3 = 3,小于或等于字符串长度,这里满足大于2K,所以只反转前K个,即我们会反转前3个字符(“abc”),得到"cbadefg”。
当i = 3时,i + k = 3 + 3 = 6,小于或等于字符串长度,因此我们会反转接下来的3个字符(“def”),得到"cbadfeg"。
当i = 6时,i + k = 6 + 3 = 9,大于字符串长度,因此我们知道只剩下1个字符(“g”),不足k个。此时,我们将反转从索引6到字符串末尾的所有字符(“g”),得到"cbadfeg",并且终止循环。

1.2.为什么i + k <= s.length()表示剩余字符少于 2k 个 但大于K个

和1.1反着来就对了


三、替换数字

四、翻转字符串里面的单词

151原题链接

1.思考

核心思路

  • 先看懂题目,开头和结尾的空格需要删除,中间如果有多个空格,那么只保留一个空格。
  • 先翻转全部单词,不管每个单词里面的顺序
  • 然后翻转每个单词的字母顺序(所谓单词就是用空格隔开的就是单词)
  • 复杂在于多余的空格删除 :双指针法删除多余空格

2.正确写法

不会写,抄的题解,后面想明白了再来补

五、右旋转字符串

卡码网的,先略过

总结

1.感想

  • 翻转字符串用了异或法,体会一下和使用临时变量存储并替换的区别。主要好处就是节省内存空间。
  • 翻转字符串里面的单词,这题对我来说比较难吧。。
  • 明天要刷KMP了,又是全新的东西,加油吧

2.思维导图

本文思路引用自代码随想录,感谢代码随想录作者。

  • 25
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值