给自己复盘的随想录笔记-字符串练习题

反转字符串

344. 反转字符串 - 力扣(LeetCode)

双指针+元素交换 

class Solution {
    public void reverseString(char[] s) {
    char temp;
    int l=0,r=s.length-1;
    while(l<r){
        temp=s[l];
        s[l]=s[r];
        s[r]=temp;
        l++;
        r--;
    }
    }
}

反转字符串ii

541. 反转字符串 II - 力扣(LeetCode)

这个题目就是上一个题目的加强版本,我的解法不具有通用性,脑子太死了

找到反转区间的规律,然后对其进行反转;

反转区间的确定+区间反转

class Solution {
    public String reverseStr(String s, int k) {
        char[] cs = s.toCharArray();
        int n = s.length();
        for (int l = 0; l < n; l = l + 2 * k) {
            int r = l + k - 1;
            reverse(cs, l, Math.min(r, n - 1));
        }
        return String.valueOf(cs);
    }
    void reverse(char[] cs, int l, int r) {
        while (l < r) {
            char c = cs[l];
            cs[l] = cs[r];
            cs[r] = c;
            l++; r--;
        }
    }
}

替换数字

54. 替换数字(第八期模拟笔试) (kamacoder.com)

统计数组个数,新建数组进行扩容,给数组进行赋值; 

import java.util.*;

public class Main{
    
    public static void main(String[] args){
     Scanner sc=new Scanner(System.in);  
     String s= sc.next();
     
     int len=s.length();
     int count=0;
     for(int i=0;i<len;i++){
         if(s.charAt(i)>='0'&&s.charAt(i)<='9'){
             count++;
         }
     }
     
     char[] res=new char[len+count*5];
     for(int j=len-1,k=len+count*5-1;j>=0;j--){
         if(s.charAt(j)>='0'&&s.charAt(j)<='9'){
             res[k--]='r';
             res[k--]='e';
             res[k--]='b';
             res[k--]='m';
             res[k--]='u';
             res[k--]='n';
             
         }else{
             res[k--]=s.charAt(j);
         }
     }
     System.out.println(new String(res));
        
        
        
    }
      
}

翻转字符串中的单词

双指针找到单词的所在区间,然后存入结果

151. 反转字符串中的单词 - 力扣(LeetCode)

class Solution {
    public String reverseWords(String s) {
    s.trim();
    int l=s.length()-1,r=s.length()-1;
    StringBuilder res=new StringBuilder();
    while(l>=0){
        while(l>=0&&s.charAt(l)!=' ') l--;
        res.append(s.substring(l+1,r+1)+' ');
        while(l>=0&&s.charAt(l)==' ') l--;
        r=l;
    }
    return res.toString().trim();
    }
}

1.
s是String类型
s.trim() 方法用于移除字符串两端的空白字符,包括空格、制表符、换行符等。这行代码的作用是将变量 s 中存储的字符串两端的空白字符去掉,并将处理后的字符串重新赋值给变量 s。

2.
为什么定义res是StringBuilder类型
在Java中,String 类型是不可变的(immutable),这意味着每次对字符串进行修改时,都会创建一个新的字符串对象。如果在一个循环中不断地对字符串进行修改,比如拼接操作,那么每次修改都会生成一个新的字符串对象,这会导致大量的内存分配和垃圾回收,从而降低程序的性能。

而 StringBuilder 类是可变的(mutable),它提供了一个可变的字符序列,可以在不生成大量临时对象的情况下进行字符串拼接操作。这使得 StringBuilder 成为处理字符串拼接的首选方式,尤其是在循环中进行大量拼接操作时。


3.
res是StringBuilder类型
res.append(...):这是调用 res 字符串的 append 方法,将拼接后的字符串添加到 res 的末尾。

4.
String substring(int beginIndex, int endIndex)
beginIndex:子字符串开始处的索引(包括此索引处的字符)。
endIndex:子字符串结束处的索引(不包括此索引处的字符)。
返回从 beginIndex 到 endIndex - 1 的子字符串。
相当于左闭右开

分裂+倒序

class Solution {
    public String reverseWords(String s) {
   String[] strs=s.trim().split(" ");
   StringBuilder res=new StringBuilder();

   for(int i=strs.length-1;i>=0;i--){
    if(strs[i].equals("")) continue;
    res.append(strs[i]+" ");
   }
   return res.toString().trim();
    }
}

1.
   String[] strs=s.trim().split(" ");
     split 方法是 Java 中 String 类的一个非常有用的实例方法,它用于将字符串分割成子字符串数组。这个方法根据指定的正则表达式来分割原始字符串。
     split 方法需要一个正则表达式作为参数,而正则表达式应该用双引号包围,即 " " 而不是 ' '
     " ":匹配空格字符。
",":匹配逗号字符。
[,;]:匹配逗号或分号字符。
     
2.
  if(strs[i].equals("")) continue;
在 Java 中,不能直接将 char 类型与 String 类型进行比较。如果需要比较字符串中的字符,应该将 char 转换为 String,或者直接比较 String 类型的变量。所以是“”双引号,表示空单词

另外,使用 equals 方法比较字符串
     
3.
方法一和方法二注意细节,方法一是引入字符数组的形式处理,方法二引入字符串数组的形式处理
 

右旋字符串

55. 右旋字符串(第八期模拟笔试) (kamacoder.com)

import java.util.Scanner;

public class Main{
    
    public static void main(String[] args){
       Scanner in = new Scanner(System.in);
        int k = Integer.parseInt(in.nextLine());
        String s = in.nextLine();
        
        char[] str=s.toCharArray();
        int len=str.length;
        rever(str,0,len-1);
        rever(str,0,k-1);
        rever(str,k,len-1);
        System.out.println(new String(str));
    }
    public static void rever(char[] str,int start,int end){
        char temp;
        while(start<end){
            temp=str[start];
            str[start]=str[end];
            str[end]=temp;
            start++;
            end--;
        }
    }
}

     Scanner in = new Scanner(System.in);
        int k = Integer.parseInt(in.nextLine());
        String s = in.nextLine();
        

 换行读取键入的对象

找出字符串第一个匹配项的下标

巧思妙想,我自己没有想到

class Solution {
    public int strStr(String ss, String pp) {
        int lenss=ss.length(),lenpp=pp.length();
        char[] s=ss.toCharArray(),p=pp.toCharArray();

        for(int i=0;i<=lenss-lenpp;i++){
            int a=i,b=0;
            while(b<lenpp&&s[a]==p[b]){
                a++;
                b++;
            }
            if(b==lenpp) return i;
        }
        return -1;
    }
}

这道题可以用KMP算法,我先留个尾巴,回头再来看

28. 找出字符串中第一个匹配项的下标 - 力扣(LeetCode)

重复的子字符串

我发现简单题其实不简单,因为考察的更多是思路;

反而难度的题目其实就是麻烦

 459. 重复的子字符串 - 力扣(LeetCode)

 这个代码给的太优雅了,我真的佩服

class Solution {
   public boolean repeatedSubstringPattern(String s) {
        String str = s + s;
        return str.substring(1, str.length() - 1).contains(s);
}
}

思路分析:假设字符串s是由s1+s2组成的,s+s后,str就变成了s1+s2+s1+s2;

去掉首尾,破环了首尾的s1和s2,变成了s3+s2+s1+s4;

此时str中间就是s2+s1,如果s是循环字串,也就是s1=s2,所以str中间的s2+s1就和原字符串相等。如果s不是循环字串,s1!=s2,那么s1+s2是不等于s2+s1的,也就是str中间不包含s

主要是要把重复子串全部理解为重复两次,不要考虑太多

另一个思路

也特别奇思妙想

但是我打死都想不出来

459. 重复的子字符串 - 力扣(LeetCode)

class Solution {
    public boolean repeatedSubstringPattern(String s) {
        int lens = s.length(), i = 0;
        while (++i < lens) {
            if (lens % i != 0) continue;
            if (s.substring(lens - i, lens).equals(s.substring(0, i))) // 判断x是不是基串
                if (s.substring(i, lens).equals(s.substring(0, lens - i))) return true; // 判断拿去x后是否相等
        }
        return false;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值