字符串总结

本文介绍了Java中字符串操作的多种实例,包括基本的反转、复杂版本的反转、替换数字和单词反转,以及右旋转字符串,展示了字符串处理的多种解决方案和优化技巧。
摘要由CSDN通过智能技术生成

一、344. 反转字符串

文章链接

1. 思路分析

很基本的字符串操作,后面经常用到的reverse方法。

头尾指针交换后往中间找就是了。

2. 代码展示

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

二、541. 反转字符串 II

文章链接

1. 思路分析

一开始写得太繁复了,其实在for循环中让i每次都加2*k是可行的,只需要加一条限制条件的约束。

本题主要是尽可能把思路逻辑简化。

  • if (i + k <= c.length)
    这个条件表明在下一轮“2k”中,仍然会有k个字符会反转
    我们其实可以把“如果剩余字符小于 2k 但大于或等于 k 个”以及“剩余字符恰好等于2k个”看作一个条件。
  • 于是特殊情况就是“剩余字符少于 k 个”的情况,这时就应该从i开始到字符串的长度结束全部翻转即可。

2. 解法分析

最开始写的反转函数需要传入string传出string,然后时间开销高得要命。

改成了传入char[],函数内部直接修改,不用返回。一下子就0ms了。

看来对象的创建和销毁、传入传出的也很耗时间嘛。要注意一下。

3. 代码展示

class Solution {
    public String reverseStr(String s, int k) {
        int i = 0;
        char[] c = s.toCharArray();
        for (; i < c.length; i += 2 * k) {
            if (i + k <= c.length) {
                reverse(c, i, i + k);
            }
            else{
                reverse(c, i, c.length);
            }
        }
        return new String(c); // 字符数组转字符串
    }

    public void reverse(char[] c, int start, int end) {
        end--;
        while (start < end) {
            char temp = c[start];
            c[start] = c[end];
            c[end] = temp;
            start++;
            end--;
        }
    }

}

三、卡码网:54.替换数字

文章链接

1. 思路分析

Java的String是不可变数据类型,所以必须要加一层辅助空间。

没啥特别的,只是从零开始编程,又把Java程序的结构复习了一遍。

2. 解法分析

创建一个StringBuffer,狠狠地append!

3. 代码展示

import java.util.*;

class Main{
     public static StringBuffer replace (String s) {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < s.length(); i++) {
            if (s.charAt(i) >= '0'&& s.charAt(i) <= '9') {
                sb.append("number");
            }
            else{
                sb.append(s.charAt(i));
            }
        }
        return sb;
    }
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String s = scanner.next();
        System.out.println(replace(s));
    }
}

四、151.翻转字符串里的单词

文章链接

1. 思路分析

本题的难度对我来说挺难的了,我能清楚地感受到自己对于边界条件、代码细节的判断不清,以及Java字符串运用的捉襟见肘。

本题的解法思路为:

  • 移除多余空格: “the sky is blue”
  • 将整个字符串反转:“eulb si yks eht”
  • 将每个单词反转:“blue is sky the”

解题不用总想着一步到位,分着步骤来也可以。只要每一步的时间复杂度都不高,最终的复杂度也不会高一个层级。

2. 解法分析

  1. 首先是“移除多余空格”。去掉头尾空格,单词之间只保留一个空格。

    按照第一反应的思路,自然是找到多余空格然后删掉。我使用了StringBuffer的delete方法(左闭右开)。但是这个方法复杂度为 O ( n ) O(n) O(n),加上for循环后变成 O ( n 2 ) O(n^2) O(n2),直接给我干超时了

    不能这样干。参考 27.移除数组 的解题思路,快慢指针法,让快指针找有效元素赋给慢指针实现时间 O ( n ) O(n) O(n)空间 O ( 1 ) O(1) O(1)的数组移除算法

    我也因此深切地感受到自己对循环条件和细节把握不清,什么条件漏掉了,什么时候++了,需要改好多次才能改掉。

  2. 将整个字符串反转”以及“将每个单词反转”的原理都是一样的。

    都是通过自己写的reverse方法来进行反转,第一次整体,第二次局部,就OK了。

  3. 最后输出String,String有一个特殊的构造方法,能截取特定长度特定部分的字符数组char[]进行构造,挺贴心的。

    public String(char[] value, int offset, int count)

3. 代码展示

class Solution {
    public String reverseWords(String s) {
        // StringBuffer sb = new StringBuffer(s); // 可变数据类型StringBuffer
        // while (sb.charAt(0) == ' ')
        //     sb.delete(0, 0);
        //     // StringBuffer的delete方法,左闭右开,时间复杂度为O(n)
       // while (sb.charAt(sb.length() - 1) == ' ')
        //     sb.delete(sb.length() - 1, sb.length() - 1);
        // for (int i = 0; i < sb.length(); i++) {
        //     while (sb.charAt(i) == ' ' && sb.charAt(i + 1) == ' ') {
        //         sb.delete(i + 1, i + 1);
        //     }
        // }// 试图整顿括号。
        // 上述代码n方复杂度超时了,换成下面的

        // 思路同27.移除元素,只用O(1)的复杂度原地移除,原理是快指针找有效元素赋到慢指针上,
        // 其实就是把该数组前面的内存当成一个新数组存了,因为有效元素更少,所以可以这样做。
        char[] c = s.toCharArray();
        int slow = 0, fast = 0;
        while (c.length > 0 && fast < c.length && c[fast] == ' ') {
            fast++;
        }// 除前导空格
        for (; fast + 1 < c.length; fast++) {
            if (c[fast] == ' ' && c[fast + 1] == ' ') {
                // 不能用fast++,因为是for循环会++两次
                continue;
            }
            else{
                c[slow++] = c[fast];
            }
        }
        if (c[fast] != ' ')
            c[slow++] = c[fast];
        int count = slow;
        reverse(c, 0, count);
        int left = 0, right = 0;
        for (; right < count; right++) {
            if (c[right] == ' ') {
                reverse(c, left, right);
                left = right + 1;
            }
            if (right == count - 1) {
                reverse(c, left, right + 1);
            }
        }//整体反转后再局部反转
        return new String(c, 0, count); // 从字符数组中选取一部分构建新的字符串的构造方法
    }

    // Java的参数传递:基本数据类型都是值传递,而对象都是引用传递。
    // Java中,数组也是对象。
    public void reverse(char[] c, int start, int end) { // 左闭右开
    // 时间复杂度为O(n)
        end--;
        while (start < end) {
            char temp = c[start];
            c[start] = c[end];
            c[end] = temp;
            start++;
            end--;
        }
    }
}

五、卡码网:55.右旋转字符串

文章链接

1. 思路分析

整体反转+局部反转。可以实现原地反转的效果。

2. 解法分析

学到了一些Java输入的代码。
创建好Scanner对象以后,执行nextLine()方法才会读取一行输入

3. 代码展示

import java.util.*;

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

六、总结

Java语法的了解真的更深了。感觉学校的课程基础略显不足。
以及基本上每道题都要使用自己写的reserve方法,随时手敲!

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值