LeetCode刷题小结---字符串篇

一、基本方法

目前遇到的单纯字符串的问题只要注意灵活运用各种String提供的方法其实都不难。

  • Java中String的方法很多,常用的有:
char charAt(int index)
返回指定索引处的 char 值。

int length()
返回此字符串的长度。

char[] toCharArray()
将此字符串转换为一个新的字符数组。

contains(CharSequence chars)
判断是否包含指定的字符系列。

boolean equals(Object anObject)
将此字符串与指定的对象比较。

int indexOf(int ch)
返回指定字符在此字符串中第一次出现处的索引。

int indexOf(String str)
 返回指定子字符串在此字符串中第一次出现处的索引。

isEmpty()
判断字符串是否为空。

char[] toCharArray()
将此字符串转换为一个新的字符数组。

boolean endsWith(String suffix)
测试此字符串是否以指定的后缀结束。在某些题中特别好用。

String toString()
返回此对象本身(它已经是一个字符串!)。

String[] split(String regex, int limit)
根据匹配给定的正则表达式来拆分此字符串。

String toLowerCase()
使用默认语言环境的规则将此 String 中的所有字符都转换为小写。
String toUpperCase()
使用默认语言环境的规则将此 String 中的所有字符都转换为大写。

String substring(int beginIndex, int endIndex)
返回一个新字符串,它是此字符串的一个子字符串。


String replace(char oldChar, char newChar)
返回一个新的字符串,它是通过用 newChar 替换此字符串中出现的所有 oldChar 得到的。

String replaceAll(String regex, String replacement)
使用给定的 replacement 替换此字符串所有匹配给定的正则表达式的子字符串。


String类有11种构造方法,常用的有:

string(const char *s)
使用c风格字符串初始化string对象

string(size_type n, char c)	
创建一个含有n个元素的string对象,其中每个元素都被初始化为字符c

string(const string &str)
将一个string对象初始化为string对象

string()创建一个默认的string对象,长度为0.

string(const char *s, size_type n)
将string对象初始化为s指向的C字符串的前n个字符,即使超过了s的结尾

string(const string &str, size_type pos=0, size_type n = pos)
将一个string对象初始化为对象str中从位置pos开始到结尾的字符,或者从pos开始的n个字符。

template<class Iter>string[Iter begin, Iter end)
将string对象初始化为区间[begin, end)内的字符,其中begin和end的行为就像指针,用于指定位置。

字符串比较

compareTo() 方法用于两种方式的比较:
字符串与对象进行比较。
按字典顺序比较两个字符串。

返回值是整型,它是先比较对应字符的大小(ASCII码顺序),如果第一个字符和参数的第一个字符不等,结束比较,返回他们之间的长度差值,如果第一个字符和参数的第一个字符相等,则以第二个字符和参数的第二个字符做比较,以此类推,直至比较的字符或被比较的字符有一方结束。

如果参数字符串等于此字符串,则返回值 0;
如果此字符串小于字符串参数,则返回一个小于 0 的值;
如果此字符串大于字符串参数,则返回一个大于 0 的值。
说明:
如果第一个字符和参数的第一个字符不等,结束比较,返回第一个字符的ASCII码差值。
如果第一个字符和参数的第一个字符相等,则以第二个字符和参数的第二个字符做比较,以此类推,直至不等为止,返回该字符的ASCII码差值。 如果两个字符串不一样长,可对应字符又完全一样,则返回两个字符串的长度差值。
boolean matches(String regex)
告知此字符串是否匹配给定的正则表达式。
可以用于字符串筛选,或者单字符构成的字符串的筛选(比如选出字母与数字,当然也可以通过ASCII码进行过滤)

补充Integer方法

补充一些Integer的方法,在数字与字符串相互转换时常用:

public static int parseInt(String s)
将字符串转换成整数。

public static String toBinaryString(int i)
将一个正整数转换成2进制字符串。

public static String toOctalString(int i)
将一个正整数转换成8进制字符串。

public static String toHexString(int i)
将一个正整数转换成16进制字符串。

public static String toUnsignedString(int i, int radix)
将一个正整数转换成r进制字符串(r的范围是[2, 64])。

java中可以使用BigInteger操作大整数,也可以转换进制。如果在操作的时候一个整型数据已经超过了整数的最大类型长度long的话,则此数据就无法装入,所以,此时要使用BigInteger类进行操作。这些大数都会以字符串的形式传入。

import java.math.BigInteger;
String string1 = new BigInteger("20", 10).toString(2);
Log.d("TAG","十进制的20转换成二进制是:"+string1);
 
String string2 = new BigInteger("20", 10).toString(8);
Log.d("TAG","十进制的20转换成八进制是:"+string2);
 
String string3 = new BigInteger("20", 10).toString(16);
Log.d("TAG","十进制的20转换成十六进制是:"+string3);
 
String string4 = new BigInteger("110", 2).toString(10);
Log.d("TAG","二进制的110转换成十进制是:"+string4);
 
String string5 = new BigInteger("110", 8).toString(10);
Log.d("TAG","八进制的110转换成十进制是:"+string5);
 
String string6 = new BigInteger("110", 16).toString(10);
Log.d("TAG","十六进制的110转换成十进制是:"+string6);

注意!(正则相关)

split()方法分割IP地址时,split(“.”)会出错,
需要使用

String ip = "211.87.226.11";
String[] ips = ip.split("\\.");

split方法中的参数是正则表达式,“.” 原本需要一个 “\” 来转义,但是正则表达式中,“” 也需要一个"" 来转义,因此一共需要两个 “” 。
同理如果,需要以 “” 分割 windows下的文件地址,需要四个 “” 。split( “\\”)


字符串的表达式求解:

可以使用一个库直接对字符串求解:

import javax.script.*;

        String input = sc.nextLine();
        ScriptEngine scriptEngine = new ScriptEngineManager().getEngineByName("nashorn");
        System.out.println(scriptEngine.eval(input));

但是使用这个库有点投机取巧的味道,如果不这样做可以使用逆波兰式+栈的方式求解字符串表达式,具体方式为:
在这里插入图片描述
在这里插入图片描述
当然逆波兰式的转化属实有点伤脑筋,那还有一个办法就是用两个栈,一个存储数字,一个存储括号和运算符。当读到 ’ ) ’ 时,符号栈弹出直到下一个前括号的符号,数字栈弹出相应数量数字,构成一个不含括号的运算式,对这个式子要考虑运算符优先级的处理,先把所有的乘除按顺序算完,再算加减。

正则表达式

JAVA正则表达式

String、StringBuffer和StringBuilder

String 对象是不可改变的。每次使用 System.String 类中的方法之一时,都要在内存中创建一个新的字符串对象,这就需要为该新对象分配新的空间。

StringBuilder 对象是动态对象,允许扩充它所封装的字符串中字符的数量,但是您可以为它可容纳的最大字符数指定一个值,当修改 StringBuilder 时,在达到容量之前,它不会为其自己重新分配空间。当达到容量时,将自动分配新的空间且容量翻倍。可以使用重载的构造函数之一来指定 StringBuilder 类的容量。

StringBuilder 类在 Java 5 中被提出,它和 StringBuffer 之间的最大不同在于 StringBuilder 的方法不是线程安全的(不能同步访问)。

由于 StringBuilder 相较于 StringBuffer 有速度优势,所以多数情况下建议使用 StringBuilder 类。

相互转化

public String toString():通过 toString() 就可以实现把StringBuilder转成String。

StringBuilder(String str):通过构造方法就可以实现把String转成StringBuilder。

StringBuilder常用方法
初始化:
StringBuilder sb = new StringBuilder();

append(String s)
将指定的字符串追加到此字符序列。

reverse()
 将此字符序列用其反转形式取代。
 
delete(int start, int end)
移除此序列的子字符串中的字符。

deleteCharAt(int i)
删除指定处字符

insert(int offset, int i)int 参数的字符串表示形式插入此序列中。

insert(int offset, String str)
将 str 参数的字符串插入此序列中。

replace(int start, int end, String str)
使用给定 String 中的字符替换此序列的子字符串中的字符。

二、题解

字符串的题,较为简单的都是些字符串的基本处理,由于JAVA自带的方法很多所以难度并不高,而涉及复杂算法的不多,常见的就是滑动窗口或者双指针;而较难的题又不仅仅考察字符串,更考察算法。

对于字符串相关的问题,更需要注意的是边界条件的考虑和处理,很多时候测试用例差那么一部分不通过就是因为没考虑极端或者边界情况。

在字符串统计方面,HashMap使用得比较多,有一些题统计字符时,甚至可以使用普通字符数组来当哈希表,数组下标即是字符的ASCII码值。

涉及字符串分割处理或者是统计某些子串的时候,巧妙运用split()方法很有效。

1、最大数

在这里插入图片描述


首先肯定是大的数排前面,也就是降序排序。

对于位数不同的数要自定义排序规则,处理像3与30哪个放前面的问题,具体为:拼接两个数字后比较大小,如330>303,那么3排在30的前面,就是说3比30大,那么使用自定义sort,因为sort默认是从小到大排序,也就是return为负数时不变,代表a<b。而我们要按我们自己的规则降序排序,就要使a小于b时return正数(交换ab位置),a大于b时return负数(保持不变)。

class Solution {
    public String largestNumber(int[] nums) {
        int n = nums.length;
        String[] ss = new String[n];
        //将整数转化为字符串
        for (int i = 0; i < n; i++) {
            ss[i] = "" + nums[i];
        }
        Arrays.sort(ss, (a, b) -> {
            String sa = a + b, sb = b + a ;
            return sb.compareTo(sa);
        });
        
        StringBuilder sb = new StringBuilder();
        for (String s : ss) sb.append(s);
        int len = sb.length();
        int k = 0;
        while (k < len - 1 && sb.charAt(k) == '0') k++; //剔除字符串前部的0
        return sb.substring(k);
    }
}

2、数字序列中某一位的数字

在这里插入图片描述


数字范围    数量  位数    占多少位
1-9        9      1       9
10-99      90     2       180
100-999    900    3       2700
1000-9999  9000   4       36000  ...

例如 2901 = 9 + 180 + 2700 + 12 即一定是4位数,第12位   n = 12;
对应的数字为 = 1000 + (12 - 1)/ 4  = 1000 + 2 = 1002
定位1002中的位置 = (n - 1) %  4 = 3    s.charAt(3) = 2;

    public int findNthDigit(int n) {
        int digit = 1;  //n位数的数位
        long start = 1; //n位数的数字起始
        long count = 9; //计算数位总和

        while (n > count) { 
            n -= count;
            digit += 1;
            start *= 10;
            count = digit * start * 9;
        }
        long num = start + (n - 1) / digit; 
        return Long.toString(num).charAt((n - 1) % digit) - '0'; 
    }

总结

寄。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值