LeetCode刷题-字符串(一)

LeetCode刷题-字符串

String数组和List集合之间的转化

数组转化为list

Integer [] arr={1,2,3};
List<Integer> list2 = Arrays.asList(arr2);
List<Integer> list=new ArrayList<>(list2);

list转化为数组

List<String> list = new ArrayList<>();
list.add("guan");
list.add("bao");
String[] array = list.toArray(new String[0]);

字符

520.检测大写字母

就直接从题目出发

  • 要不全小写相等
  • 要不全大写相等
  • 切割,第一个字母是大写,剩余的字母一定是小写
public boolean detectCapitalUse(String word) {
    if (word.length()<=1){
        return true;
    }else {
        if (word.toLowerCase().equals(word)){
            return true;
        }else if (word.toUpperCase().equals(word)){
            return true;
        }else {
            String substring = word.substring(1, word.length());
            char firstChar = word.charAt(0);
            if (firstChar<'Z' && substring.toLowerCase().equals(substring)){
                return true;
            }else {
                return false;
            }
        }
    }
}

回文串

125.验证回文串

首先移除非字母和数字的字符,并且全部转化为小写。

然后就修改完的字符串,只需要比较头尾的字符是否相等即可

public boolean isPalindrome(String s) {
    String cleanString = cleanString(s);
    int start = 0;
    int end = cleanString.length()-1;
    boolean result = true;
    while (start<end){
        if (cleanString.charAt(start)!=cleanString.charAt(end)){
            result = false;
            break;
        }
        start++;
        end--;
    }
    return result;

}

//用来移除非字母和数字的字符,并且全部转化为小写
public String cleanString(String str){
    StringBuffer result = new StringBuffer();
    for (int i = 0; i < str.length(); i++) {
        char c = str.charAt(i);
        if ((c>='a'&&c<='z') || (c>='A' &&c<='Z') || (c>='0' &&c<='9')){
            result.append(c);
        }
    }
    return result.toString().toLowerCase();
}

公共前缀

14.最长公共前缀

纵向遍历,用第一个字符的每个字母和别的字符的每个字母比较
如果都拥有该字母,那么添加进入公共前缀,否则立刻结束

fig2

public String longestCommonPrefix(String[] strs) {
    String firstStr = strs[0];
    if (strs.length==1){
        return firstStr;
    }else {
        for (int i = 0;i<firstStr.length();i++) {
            //获得第一个单词的每一个字符
            char c = firstStr.charAt(i);
            //从第二个字符串开始遍历
            for (int j = 1;j<strs.length;j++){
                //如果当前字符的长度已经超出了第一个字符的长度,停止
                //或者当前字符不匹配,停止
                if (i == strs[j].length() || strs[j].charAt(i) != c) {
                    return strs[0].substring(0, i);
                }
            }
        }
        return firstStr;
    }
}

单词

434.字符串中的单词数

特别要注意是连续的多个空格,所以正则表达式要求匹配连续的一个或者多个一个以上的空格

public int countSegments(String s) {
    int result = 0;
    //匹配连续的一个或者多个一个以上的空格
    String[] split = s.split("\\ +");
    for (String str:split) {
        if (str!=null && !"".equals(str)){
            result++;
        }
    }
    return result;
}

58.最后一个单词的长度

public int lengthOfLastWord(String s) {
    //匹配连续的一个或者多个一个以上的空格
    String[] split = s.split("\\ +");
    return split[split.length-1].length();
}

字符串的反转

344.反转字符串

经典原地反转,可以利用于所有的数组

public void reverseString(char[] s) {
    int start = 0;
    int end = s.length-1;
    while (start<end){
        char temp = s[start];
        s[start] = s[end];
        s[end] = temp;
        start++;
        end--;
    }
}

541.反转字符串 II

通过字符串的长度/2k先求出哪些字符串肯定可以反转,通过字符串的长度%2k求出哪些字符串是可能要反转的。对于前者,我们在交替反转(即0-k反转,k-2k不反转,2k-3k反转……),对于后者,我们判断长度来进行反转

public String reverseStr(String s, int k) {
    int length = s.length();
    if (k>length){
        return turn(s,0,length-1);
    }
    //查看是否有余数
    int remainder = length%(2*k);
    //得到商的长度
    int quotient = length/(2*k);
    //获得肯定可以翻转的字符
    String newS = s.substring(0,2*k*quotient);
    //得到额外需要判定的翻转字符
    String canNotTurnS = s.substring(length-remainder,length);
    int lengthTurn = canNotTurnS.length();
    //标记反转(1要反转,-1不反转)
    int flag = 1;
    for (int i = 0; i < newS.length(); i++) {
        if ((i+1)%k==0){
            if (flag==1){
                newS = turn(newS,i+1-k,i);
                flag = -1;
            }else {
                flag = 1;
            }
        }
    }
    if (lengthTurn<=0){
        return newS;
    }else if (lengthTurn>0 && lengthTurn<k){
        return newS+turn(canNotTurnS,0,canNotTurnS.length()-1);
    }else {
        return newS+turn(canNotTurnS,0,k-1);
    }
}

//反转字符串的某几个字符
public String turn(String str,int start,int end){
    char[] s = str.toCharArray();
    while (start<end){
        char temp = s[start];
        s[start] = s[end];
        s[end] = temp;
        start++;
        end--;
    }
    return new String(s);
}

字符的统计

387. 字符串中的第一个唯一字符

利用map先对字符串进行字符数量的统计,然后找出value第一个出现的为1的key即可

public int firstUniqChar(String s) {
    char[] chars = s.toCharArray();
    Map<Character,Integer> map = new HashMap<>();
    for (int i = 0; i < chars.length; i++) {
        Character c = chars[i];
        if (map.containsKey(c)){
            map.put(c,map.get(c)+1);
        }else {
            map.put(c,1);
        }
    }
    int result = -1;
    for (int j = 0; j < chars.length; j++) {
        if (map.get(chars[j])==1){
            result = j;
            break;
        }
    }
    return result;
}

389. 找不同

思维爆炸,两个字符串的分别字符ascii码相加,两者之差就是添加的字符

public char findTheDifference(String s, String t) {
    int sAsc = 0,tAsc =0;
    for (int i = 0; i < s.length(); i++) {
        sAsc = sAsc+s.charAt(i);
    }
    for (int j = 0; j < t.length(); j++) {
        tAsc = tAsc+t.charAt(j);
    }
    return (char)(tAsc-sAsc);
}

242. 有效的字母异位词

如果是异位词,那么排序之后结果就是一样

public boolean isAnagram(String s, String t) {
    char[] sChars = s.toCharArray();
    char[] tChars = t.toCharArray();
    Arrays.sort(sChars);
    Arrays.sort(tChars);
    return Arrays.equals(sChars,tChars);
}

49. 字母异位词分组

  1. 排序,将每个字符串进行排序,那么【字母异位词】排序的结果应该是一样的
  2. 我们将key设置为排序的结果,value设置集合,其中存放排序结果相同的字符串
  3. map.getOrDefault(key,default)表示如果集合中有这个键,那么取值,否则直接将值赋值为我们自定义的默认值default
  4. 最后添加当前字符串更新map集合即可
public List<List<String>> groupAnagrams(String[] strs) {
    Map<String,List<String>> map = new HashMap<>();
    for (int i = 0; i < strs.length; i++) {
        char[] chars = strs[i].toCharArray();
        Arrays.sort(chars);
        //获得排序好的字符串
        String key = new String(chars);
        //如果有key,那么直接取出 value = List<String>
        //如果没有key,设置默认值为 value = new ArrayList<String>()
        //将key为当前字符串排序结果的value取出来
        List<String> value = map.getOrDefault(key, new ArrayList<String>());
        //添加当前字符串
        value.add(strs[i]);
        //更新map集合
        map.put(key,value);
    }
    return new ArrayList<List<String>>(map.values());
}

451. 根据字符出现频率排序

难点在于如何重写排序器实现字符出现的 频率 对其进行 降序排序

public String frequencySort(String s) {
    Map<Character, Integer> map = calculate(s);
    //重写排序器
    Comparator com = new Comparator<Character>() {
        @Override
        public int compare(Character o1, Character o2) {
            Integer one = map.get(o1);
            Integer two = map.get(o2);
            return two-one;
        }
    };
    List<Character> keyList = new ArrayList<Character>(map.keySet());
    //降序输出key
    Collections.sort(keyList,com);
    StringBuilder result = new StringBuilder();
    //遍历每个字符
    for (int i = 0; i < keyList.size(); i++) {
        //遍历每个字符对应的次数
        for (int j = 0; j < map.get(keyList.get(i)); j++) {
            result.append(keyList.get(i));
        }
    }
    return new String(result);
}


//用于字符串中每个字符的计数
public Map<Character,Integer> calculate(String str){
    Map<Character,Integer> map = new TreeMap<>();
    char[] chars = str.toCharArray();
    for (int i = 0; i < chars.length; i++) {
        Character c = chars[i];
        //getOrDefault()表示如果对应的key如果没有value,那么设置为0
        //如果有value,取改key对应的value
        map.put(c,map.getOrDefault(c,0)+1);
    }
    return map;
}

551. 学生出勤记录 I

public boolean checkRecord(String s) {
    int late = 0;
    int absent = 0;
    char[] chars = s.toCharArray();
    for (int i = 0; i < chars.length; i++) {
        if (chars[i]=='A'){
            absent++;
            if (absent>=2){
                return false;
            }
        }
        if (chars[i]=='L'){
            late++;
            if (late>=3){
                return false;
            }
        }else {
            //但凡不是L,就置0
            late=0;
        }
    }
    return true;
}

696. 计数二进制子串

思路实在重要,本题不需要调用任何算法

  1. 创建数组用于放置连续的0或者1的数量,假设为[a,b,c,d]
  2. a和b肯定为连续的0和1的数量,可以构造的连续的子字符数量就是min(a,b)
  3. 那么我们的答案就是连续两个数字的最小值min(a,b)+min(b,c)+min(c,d)累加之和
public int countBinarySubstrings(String s) {
    List<Integer> list = new ArrayList<>();
    int oneCount = 0, zeroCount = 0;
    int length = s.length();
    for (int i = 0; i < length; i++) {
        char c = s.charAt(i);
        //连续的数字碰到下一个和自己互异的数字就截断
        if (c =='0'){
            if (oneCount>0){
                list.add(oneCount);
                oneCount = 0;
            }
            zeroCount++;
        }else {
            if (zeroCount > 0) {
                list.add(zeroCount);
                zeroCount = 0;
            }
            oneCount++;
        }
    }
    //把最后一段连续的0或者1加入
    list.add(oneCount>0?oneCount:zeroCount);
    int result = 0;
    int size = list.size();
    for (int i = 1; i < size; i++) {
        result+=Math.min(list.get(i),list.get(i-1));
    }
    return result;
}

535. TinyURL 的加密与解密

public class Codec {

    //利用map集合存储(id,url),每个url添加一个id到longUrl后面
    //取的时候根据id将url取出来
    Map<Integer,String> map = new TreeMap<>();
    int id;

    public String encode(String longUrl) {
         id++;
         map.put(id,longUrl);
         return longUrl+"/"+id;
    }

    public String decode(String shortUrl) {
        String[] split = shortUrl.split("/");
        Integer id = Integer.parseInt(split[split.length-1]);
        return map.get(id);
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值