令人头痛的字符串

概述

String的特性

  • String类:代表字符串。Java程序中的所有字符串字面值(如"abc")都作为此类的实例实现。
  • String是一个final类,代表不可变的字符序列。体现:
    • 1.当对字符串重新赋值时,需要重新指定内存区域赋值,不能使用原有的value进行赋值。
    • 2.当对现有的字符串进行连接操作时,也需要重新指定内存区域赋值,不能使用原有的value进行赋值。
    • 3.当调用String的replace()方法修改指定字符或字符串时,也需要重新指定内存区域赋值,不能使用原有的value进行赋值。
  • 字符串是常量,用双引号引起来表示。它们的值在创建之后不能更改
  • String对象的字符内容是存储在一个byte数组value[]中的。

String常用方法

  • int length():返回字符串的长度:return value.length
  • char charAt(int index):返回某索引处的字符:return value[index]
  • boolean isEmpty():判断是否是空字符串:return value.length == 0
  • String toLowerCase():使用默认语言环境,将String 中的所有字符转换为小写
  • String toUpperCase():使用默认语言环境,将String 中的所有字符转换为大写
  • String trim():返回字符串的副本,忽略前导空白和尾部空白(即忽略前后字符串之间多余的空白,但中间的空格不省略,详见s4)
  • boolean equals(Object ibj):比较字符串的内容是否相同
  • boolean equalsIgnoreCase(String anotherString):与equals方法类似,忽略大小写
  • String concat(Sting str):将指定字符串连接到此字符串的结尾。等价于用"+"
  • int compareTo(String anotherString):比较两个字符串的大小
  • String substring(int beginIndex):返回一个新的字符串,它是此字符串的从beginIndex开始
  • String substring(int beginIndex,int endIndex):返回一个新字符串,它是此字符串从beginIndex开始截取到endIndex(不包含)的一个字符串。
  • boolean endsWith(String suffix):测试此字符串是否以指定的后缀结束
  • boolean startsWith(String prefix):测试此字符串是否以指定的前缀开始
  • boolean startsWith(String prefix,int toffset):测试此字符串从指定索引开始的子字符串是否以指定前缀开始
  • boolean contains(CharSequence s):当且仅当此字符串包含指定的char值序列时,返回true
  • int indexOf(String str):返回指定字符串在此字符串中第一次出现处的索引
  • int indexOf(String str,int fromIndex):返回指定字符串在此字符串中第一次出现处的索引,从指定的索引开始
  • int lastIndexOf(String str):返回指定子字符串在此字符串中最右边出现处的索引
  • int lastIndexOf(String str,int fromIndex):返回指定子字符串在此字符串中最后一次出现处的索引,从指定的索引开始反向搜索
  • String replace(char oldChar,char newChar):返回一个新的字符串,它是通过使用newChar替换此字符串中出现的所有oldChar得到的。
  • String replace(CharSequence target,CharSequence replacement):使用指定的字面替换序列替换此字符窜所有匹配字面值目标序列的子字符串。
  • String replaceAll(String regex,String replacement):使用给定的replacement替换此字符串所有匹配给定的正则表达式的子字符串。
  • String replaceFist(String regex,String replacement):使用给定的replacement替换此字符串匹配给定的正则表达式的第一个子字符串。
  • 匹配:
  • boolean matches(String regex):告知此字符串是否匹配给定的正则表达式。
  • String[] split(String regex):根据给定正则表达式的匹配拆分此字符串。
  • String[] split(String regex,int limit):根据匹配给定的正则表达式来拆分此字符串,最多不超过limit个,如果超过了,剩下的全部都放到最后一个元素中。

字符串相关的类:StringBuffer类和StringBuilder类

  1. String、StringBuffer、StringBuilder三者的异同?

    • String:不可变的字符序列;

    • StringBuffer:可变的字符序列;线程安全的,效率低

    • StringBuilder:可变的字符序列;JDK5.0新增的,线程不安全的,效率高

    • 相同点:底层都是使用byte[]存储

  2. 常用方法:

    • StringBuffer append(xxx):提供了很多的append()方法,用于进行字符串拼接
    • StringBuffer delete(int start,int end):删除指定位置的内容
    • StringBuffer replace(int start, int end, String str):把[start,end)位置替换为str
    • StringBuffer insert(int offset, xxx):在指定位置插入xxx
    • StringBuffer reverse() :把当前字符序列逆转
    • public int indexOf(String str)
    • public String substring(int start,int end):返回一个从start开始到end索引结束的左闭右开区间的子字符串
    • public int length()
    • public char charAt(int n )
    • public void setCharAt(int n ,char ch)
  3. String 与StringBuffer、StringBuilder之间的转换

    • String --> StringBuffer、StringBuilder:调用StringBuffer、StringBuilder构造器
    • StringBuffer、StringBuilder --> String:①调String的构造器;②StringBuffer、StringBuilder的toString()

例题

做相关例题练习的时候,不要太迷恋于库函数。

344.反转字符串

描述

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

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

示例

输入:s = ["h","e","l","l","o"]
输出:["o","l","l","e","h"]

题解
对于这道题目我们可能直接调用库函数 reverse就完事了,但是这里我们还是主要理解其相应的实现。

我们定义两个指针(也可以说是索引下标),一个从字符串前面,一个从字符串后面,两个指针同时向中间移动,并交换元素。不难写出代码:

class Solution {
    public void reverseString(char[] s) {

        int left = 0;
        int right = s.length - 1;

        while(left < right){
            s[left] ^= s[right];
            s[right] ^= s[left];
            s[left] ^= s[right];
            left++;
            right--;
        }

    }
}

541. 反转字符串 II

描述

给定一个字符串 s 和一个整数 k,从字符串开头算起,每计数至 2k 个字符,就反转这 2k 字符中的前 k 个字符。
	如果剩余字符少于 k 个,则将剩余字符全部反转。
	如果剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符,其余字符保持原样。

示例

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

题解
这道题目其实也是模拟,实现题目中规定的反转规则就可以了。

如果为了处理逻辑:每隔2k个字符的前k的字符,写了一堆逻辑代码或者再搞一个计数器,来统计2k,再统计前k个字符。这样的思路太麻烦了。

其实在遍历字符串的过程中,只要让 i += (2 * k),i 每次移动 2 * k 就可以了,然后判断是否需要有反转的区间。

因为要找的也就是每2 * k 区间的起点,这样写,程序会高效很多。

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

class Solution {
    public String reverseStr(String s, int k) {
        char[] arr = s.toCharArray();

        for(int i = 0; i < arr.length; i += 2* k){
            int start = i;

            //这里是判断尾数够不够k个来取决end指针的位置
            int end = Math.min(arr.length - 1,start + k -1);

            while(start < end){
                arr[start] ^= arr[end];
                arr[end] ^= arr[start];
                arr[start] ^= arr[end];
                start++;
                end--;
            }
        }
        return new String(arr);
    }
}

剑指 Offer 05. 替换空格

描述

请实现一个函数,把字符串 s 中的每个空格替换成"%20"

示例

输入:s = "We are happy."
输出:"We%20are%20happy."

题解
通过StringBuffer或者StringBuilder来求解

将s转换为char型数组,对数组进行遍历,当遇到’ '空格时,就进行添加"%20",否则就进行添加该char型字符。

class Solution {
    public String replaceSpace(String s) {
       char[] arr = s.toCharArray();

       StringBuffer sb = new StringBuffer();

       for(char c : arr){
           if(c == ' ') sb.append("%20");
           else sb.append(c);
       }
        return sb.toString();
    }
}

151. 反转字符串中的单词

描述

给你一个字符串 s ,请你反转字符串中 单词 的顺序。

单词 是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的 单词 分隔开。

返回 单词 顺序颠倒且 单词 之间用单个空格连接的结果字符串。

注意:输入字符串 s中可能会存在前导空格、尾随空格或者单词间的多个空格。返回的结果字符串中,单词间应当仅用单个空格分隔,且不包含任何额外的空格。

示例

输入:s = "the sky is blue"
输出:"blue is sky the"
输入:s = "  hello world  "
输出:"world hello"
解释:反转后的字符串中不能存在前导空格和尾随空格。

题解
双指针:

  • 倒序遍历字符串 s ,记录单词左右索引边界 i , j ;
  • 每确定一个单词的边界,则将其添加至单词列表 res ;
  • 最终,将单词列表拼接为字符串,并返回即可。
class Solution {
    public String reverseWords(String s) {
        s = s.trim(); // 删除首尾空格
        int j = s.length() - 1, i = j;
        StringBuilder res = new StringBuilder();
        while(i >= 0) {
            while(i >= 0 && s.charAt(i) != ' ') i--; // 搜索首个空格
            res.append(s.substring(i + 1, j + 1) + " "); // 添加单词
            while(i >= 0 && s.charAt(i) == ' ') i--; // 跳过单词间空格
            j = i; // j 指向下个单词的尾字符
        }
        return res.toString().trim(); // 转化为字符串并返回
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值