字符串部分刷题笔记

字符串部分刷题记录

以下仅为个人刷题记录

一、字符

question 520(检测大写字母)

在这里插入图片描述
answer:
两种情况 1:都是大写 2:从第二个开始都是小写

lass Solution {
    public boolean detectCapitalUse(String word) {
        //分两种情况
        //1:所有字符都是大写
        //2:从第二个字符开始都是小写
        return word.equals(word.toUpperCase())||word.substring(1).equals(word.substring(1).toLowerCase());
    }
}

二、回文串的定义

question 125(验证回文串)

在这里插入图片描述
answer
双指针遍历比较

class Solution {
    public boolean isPalindrome(String s) {
        int n = s.length();
        int left = 0, right = n - 1;
        //将字符串转化为字符数组
        char[] curr = s.toCharArray();
        while (left < right) {
            //从左开始查找字符
            while (left < right && !Character.isLetterOrDigit(curr[left])) {
                ++left;
            }
            //从右查找字符
            while (left < right && !Character.isLetterOrDigit(curr[right])) {
                --right;
            }
            //比较是否相等
            if (left < right) {
                if (Character.toLowerCase(curr[left]) != Character.toLowerCase(curr[right])) {
                    return false;
                }
                ++left;
                --right;
            }
        }
        return true;
    }
}

利用StringBuffer

class Solution {
    public boolean isPalindrome(String s) {
        StringBuffer buff=new StringBuffer();
        int len=s.length();
        for(int i=0;i<len;i++){
            char tag=s.charAt(i);
            if(Character.isLetterOrDigit(tag)){
                buff.append(Character.toLowerCase(tag));
            }
        }
        StringBuffer buff_reverse =new StringBuffer(buff).reverse();
        return (buff.toString()).equals(buff_reverse.toString());
    }
}

三、公共前缀

question 434(字符串中的单词数)

在这里插入图片描述
answer:

class Solution {
    public int countSegments(String s) {
        int len=s.length();
        //统计每个单词第一个下标
        //需要满足两个条件 1:当前下标不为空,2前一个下标为空,或者下标为0
        int count=0;
        for(int i=0;i<len;i++){
            if((i==0||s.charAt(i-1)==' ')&&s.charAt(i)!=' '){
                count++;
            }
        }
        return count;
    }
}

question 58 (最后一个单词的长度)

在这里插入图片描述
answer:从后往前遍历,过滤最后面的空格

class Solution {
    public int lengthOfLastWord(String s) {
        if(s==null||s.length()==0){
            return 0;
        }
        int len=s.length();
        int count=0;
        for(int i=len-1;i>=0;i--){
            if(s.charAt(i)!=' '){
                count++;
            //如果当前字符为空 并且count有值 返回count
            }else if(count!=0){
                return count;
            }
        }
        return count;
    }
}

四、字符串的反转

question 344(反转字符串 )

在这里插入图片描述
answer:

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

question 541(反转字符串)

在这里插入图片描述
answer:
可以翻译为,每2k个字符反转k个,最后不够k,全部反转

class Solution {
    public String reverseStr(String s, int k) {
        if(k==1){return s;}
        int len=s.length();
        char[] sa=s.toCharArray();
        for(int i=0;i<len;i+=2*k){
            reverse(sa,i,Math.min(i+k-1,len-1));           
        }
        return new String(sa);
    }

    public void reverse(char[] arr,int i,int j){
        while(i<j){
           char temp=arr[i];
           arr[i]=arr[j];
           arr[j]=temp;
           i++;
           j--;    
        }
    }
}

question 557(反转字符串中的单词)

在这里插入图片描述
answer

class Solution {
    public String reverseWords(String s) {
        String[] strs = s.split(" ");
        int len=strs.length;
        StringBuffer buff=new StringBuffer();
        for(int i=0;i<len;i++){
            buff.append(new StringBuffer(strs[i]).reverse());
            buff.append(" ");
        }
        return buff.toString().trim();
    }
}

question 151(颠倒字符串中的单词)

在这里插入图片描述
answer 双指针

class Solution {
    public String reverseWords(String s) {
        int left = 0, right = s.length() - 1;
        // 去掉字符串开头的空白字符
        while (left <= right && s.charAt(left) == ' ') {
            ++left;
        }

        // 去掉字符串末尾的空白字符
        while (left <= right && s.charAt(right) == ' ') {
            --right;
        }

        Deque<String> d = new ArrayDeque<String>();
        StringBuilder word = new StringBuilder();
        
        while (left <= right) {
            char c = s.charAt(left);
            if ((word.length() != 0) && (c == ' ')) {
                // 将单词 push 到队列的头部
                d.offerFirst(word.toString());
                word.setLength(0);
            } else if (c != ' ') {
                word.append(c);
            }
            ++left;
        }
        d.offerFirst(word.toString());

        return String.join(" ", d);
    }
}

answer2

class Solution {
    public String reverseWords(String s) {
        s=s.trim();
        String[] str=s.split(" +");
        //将数组转化成List集合
        List<String> wordList=Arrays.asList(str);
        //对集合反转
        Collections.reverse(wordList);
        用空格连接集合中的两个数
        return String.join(" ",wordList);
    }
}

五、字符的统计

question 387(字符串中第一个唯一字符)

在这里插入图片描述
answer

class Solution {
    public int firstUniqChar(String s) {
        int len=s.length();
        if(len==1){return 0;}
        Map<Character,Integer> map = new HashMap<>();
        for(int i=0;i<len;i++){
            map.put(s.charAt(i),map.getOrDefault(s.charAt(i),0)+1);
        }
        for(int i=0;i<len;i++){
            if(map.getOrDefault(s.charAt(i),0)==1){
                return i;
            }
        }
        return -1;
    }
}

question 389(找不同)

在这里插入图片描述
answer:计数

首先遍历字符串 s,对其中的每个字符都将计数值加 1;然后遍历字符串 t,对其中的每个字符都将计数值减 1。当发现某个字符计数值为负数时,返回字符

class Solution {
    public char findTheDifference(String s, String t) {
        int[] cnt = new int[26];
        for (int i = 0; i < s.length(); ++i) {
            char ch = s.charAt(i);
            cnt[ch - 'a']++;
        }
        for (int i = 0; i < t.length(); ++i) {
            char ch = t.charAt(i);
            cnt[ch - 'a']--;
            if (cnt[ch - 'a'] < 0) {
                return ch;
            }
        }
        return ' ';
    }
}

answer2 求和
将字符串 s,t 中每个字符的 ASCII 码的值求和,求字符差值

class Solution {
    public char findTheDifference(String s, String t) {
        int acount=0,tcount=0;
        for(int i=0;i<s.length();i++){
            acount+=s.charAt(i);
        }
        for(int i=0;i<t.length();i++){
            tcount+=t.charAt(i);
        }
        return (char)(tcount-acount);

    }
}

question 383()

在这里插入图片描述
answer 计数

class Solution {
    public boolean canConstruct(String ransomNote, String magazine) {
        if (ransomNote.length() > magazine.length()) {
            return false;
        }
        int[] cnt = new int[26];
        for (char c : magazine.toCharArray()) {
            cnt[c - 'a']++;
        }
        for (char c : ransomNote.toCharArray()) {
            cnt[c - 'a']--;
            if(cnt[c - 'a'] < 0) {
                return false;
            }
        }
        return true;
    }
}

question 242(有效的字母异位词)

在这里插入图片描述
answer

class Solution {
    public boolean isAnagram(String s, String t) {
        if(s.length()!=t.length()){
            return false;
        }
        char[] srr=s.toCharArray();
        char[] trr=t.toCharArray();
        int[] count=new int[26];
        for(int i=0;i<s.length();i++){
            count[srr[i]-'a']++;
        }
        for(int i=0;i<t.length();i++){
            count[trr[i]-'a']--;
            if(count[trr[i]-'a']<0){
                return false;
            }
        }
        return true;
    }
}

question 49(字母异位词分析)

在这里插入图片描述
answer:

class Solution {
    public List<List<String>> groupAnagrams(String[] strs) {
        //将单词排序,排序的单词作为一个键      
        Map<String,List<String>> map = new HashMap<>();
        //遍历数组里的每一个数
        for(String str:strs){
            //接收遍历到的数组元素
            //比如"eat"
            char[] cur=str.toCharArray();
            //对eat排序 aet
            Arrays.sort(cur);
           
           String key=new String(cur);

           List<String> list = map.getOrDefault(key,new ArrayList<String>());

           list.add(str);
           map.put(key,list);
        }
       //泛型 里面的内容可能不会自动转化。
        return new ArrayList<>(map.values());
       
    }
}

question 451(根据字符出现的频率排序)

在这里插入图片描述
answer:

class Solution {
    public String frequencySort(String s) {
        if(s.length()<=1){
            return s;
        }
        Map<Character,Integer> map=new HashMap<>();
        char[] array=s.toCharArray();
        for(char str:array){
            map.put(str,map.getOrDefault(str,0)+1);
        }
        StringBuilder sb=new StringBuilder();
        //每次找数量最大的一个;
        while(map.size()>0){
            int max=0;
            char key=' ';
            for(Map.Entry<Character,Integer> entry: map.entrySet()){
                if(entry.getValue()>max){
                    max=entry.getValue();
                    key=entry.getKey();
                }
            }
            map.remove(key);
            for(int i=0;i<max;i++){
                sb.append(key);
            }
        }
        return sb.toString();
    }
}

question 423(从英文中重建数字)

在这里插入图片描述
answer:
在这里插入图片描述

class Solution {
    public String originalDigits(String s) {
        //zero one two three four five six seven eight nine
        Map<Character,Integer> map=new HashMap<>();
        char[] array=s.toCharArray();
        for(char str: array){
            map.put(str,map.getOrDefault(str,0)+1);
        }
       int[] cur=new int[10];
       cur[0]=map.getOrDefault('z',0);
       cur[2]=map.getOrDefault('w',0);
       cur[4]=map.getOrDefault('u',0);
       cur[6]=map.getOrDefault('x',0);
       cur[8]=map.getOrDefault('g',0);
       //h:3,8  f:4,5  s:6,7
       cur[3]=map.getOrDefault('h',0)-map.getOrDefault('g',0);
       cur[5]=map.getOrDefault('f',0)-map.getOrDefault('u',0);
       cur[7]=map.getOrDefault('s',0)-map.getOrDefault('x',0);
       //o:0,1,2,4 ; i:5,6,8,9
       cur[1]=map.getOrDefault('o',0)-cur[0]-cur[2]-cur[4];
       cur[9]=map.getOrDefault('i',0)-cur[5]-cur[6]-cur[8];

       StringBuilder sb=new StringBuilder();
       for(int i=0;i<10;i++){
           if(cur[i]==0){
               continue;
           }//出现的可能不止一个
          for(int j=0;j<cur[i];j++){
              sb.append(i);
          }
       }
       return sb.toString();
    }
}

question 657(机器人能否返回原点)

在这里插入图片描述
answer:

class Solution {
    public boolean judgeCircle(String moves) {
        //统计RL UD次数  判断是否相等
        if(moves.length()==0){return true;}
        if(moves.length()%2!=0){return false;}
        int x=0,y=0;
        char[] array=moves.toCharArray();
        for(char str: array){
            if(str=='U'){y--;}
            else if(str=='D'){y++;}
            else if(str=='L'){x--;}
            else if(str=='R'){x++;}
        }
        if(x==0&&y==0){
            return true;
        }
        return false;
    }
}

question 551(学生出勤记录1)

在这里插入图片描述

answer

class Solution {
    public boolean checkRecord(String s) {
        if(s.length()<2){return true;}
        int len=s.length();
        char[] array=s.toCharArray();
        int a=0,l=0;
        for(int i=0;i<len;i++){
            if(array[i]=='A'){
                a++;
                if(a>=2){
                    return false;
                }
            }else if(array[i]=='L'){
                //如果当前迟到,判断是否连续三天都迟到
                if(i+2<len){
                    if(array[i+1]=='L'&&array[i+2]=='L'){
                        return false;
                    }
                }
            }
        }
        return true;
    }
}

answer2

class Solution {
    public boolean checkRecord(String s) {
        int absents = 0, lates = 0;
        int n = s.length();
        for (int i = 0; i < n; i++) {
            char c = s.charAt(i);
            if (c == 'A') {
                absents++;
                if (absents >= 2) {
                    return false;
                }
            }
            if (c == 'L') {
                lates++;
                if (lates >= 3) {
                    return false;
                }
            } else {
                lates = 0;
            }
        }
        return true;
    }
}

question 696(计数二进制字串)

在这里插入图片描述
answer:

class Solution {
    public int countBinarySubstrings(String s) {
        List<Integer> list=new ArrayList<>();
        char[] array=s.toCharArray();
        int pre=0,last=s.length();
        while(pre<last){
            char cur=array[pre];
            int count=0;
            while(pre<last&&cur==array[pre]){
                pre++;
                count++;
            }
            list.add(count);
        }
        int res=0;
        for(int i=0;i<list.size()-1;i++){
            res+=Math.min(list.get(i),list.get(i+1));
        }
        return res;
    }
}

question 467

question 535

六、数字与字符串间转换

question 299(猜数字)

在这里插入图片描述
answer
对于奶牛,需要满足数字猜对但是位置不对。我们可以统计secret,guess各个字符的出现次数,记在两个长度为 10 的数组中,数组下标和字符相等,
由于多余的数字无法匹配,对于 0 到 9 的每位数字,应取其在 secret 和 guess 中的出现次数的最小值。将每位数字出现次数的最小值累加,即为奶牛的个数。

class Solution {
    public String getHint(String secret, String guess) {        
        int[] scount=new int[10];
        int[] gcount=new int[10];
        int bull=0,cow=0;
        for(int i=0;i<secret.length();i++){
            //位置数字都相等
            if(secret.charAt(i)==guess.charAt(i)){
                bull++;
            }else{
                //当不相等时,统计secret guess字符串中字符出现的次数
                scount[secret.charAt(i)-'0']++;
                gcount[guess.charAt(i)-'0']++;
            }
        }
        //字符与下标对应,取非公牛出现数量最少的字符=>奶牛的个数
        for(int i=0;i<10;i++){
            cow+=Math.min(scount[i],gcount[i]);
        }
        return bull+"A"+cow+"B";
    }
}

question 412(FIZZ BUZZ)

在这里插入图片描述
answer:

class Solution {
    public List<String> fizzBuzz(int n) {
        List<String> res=new ArrayList<>();
        for(int i=1;i<=n;i++){
            if(i%3==0&&i%5==0){
                res.add("FizzBuzz");
            }else if(i%3==0){
                res.add("Fizz");
            }else if(i%5==0){
                res.add("Buzz");
            }else{
                res.add(String.valueOf(i));
            }
        }
        return res;
    }
}

question 506 (相对名词)

在这里插入图片描述

class Solution {
    public String[] findRelativeRanks(int[] score) {
        int len=score.length;
        int[] temp=new int[len];
        //将分数复制一份
        for(int i=0;i<len;i++){
            temp[i]=score[i];
        }
        //将分数排序,顺序排序
        Arrays.sort(temp);
        //《得分,名次》
        Map<Integer,Integer> map=new HashMap<>();
        for(int i=0;i<len;i++){
            map.put(temp[i],len-i);
        }
        //res 名词数组
        String[] res=new String[len];
        for(int i=0;i<len;i++){
           int level=map.get(score[i]);
           if(level==1){
               res[i]="Gold Medal";
           }else if(level==2){
               res[i]="Silver Medal";
           }else if(level==3){
               res[i]="Bronze Medal";
           }else {
               res[i]=String.valueOf(level);
           }
        }
        return res;
    }
}

question 539(最小时间差)

在这里插入图片描述
answer

class Solution {
    public int findMinDifference(List<String> timePoints) {
        //对时间点进行排序
        //排序后的时间 最小值差值出现在相邻时间或者首位时间中
        Collections.sort(timePoints);
        int ans = Integer.MAX_VALUE;
        int t0Minutes = getMinutes(timePoints.get(0));
        int preMinutes = t0Minutes;
        for (int i = 1; i < timePoints.size(); ++i) {
            int minutes = getMinutes(timePoints.get(i));
            ans = Math.min(ans, minutes - preMinutes); // 相邻时间的时间差
            preMinutes = minutes;
        }
        //24:60=1440秒
        ans = Math.min(ans, t0Minutes + 1440 - preMinutes); // 首尾时间的时间差
        return ans;
    }

    public int getMinutes(String t) {
        return ((t.charAt(0) - '0') * 10 + (t.charAt(1) - '0')) * 60 + (t.charAt(3) - '0') * 10 + (t.charAt(4) - '0');
    }
}

question 640(求解方程)

在这里插入图片描述
answer:
首先使用 = 将方程左右两边拆分开,然后使用方法 breakIt 分别遍历方程的左右两边,解析出其中的数字和 x,并将结果以数组的形式返回。

对任意一个给定的方程,将其转换为所有的 x 都在 = 左侧,所有的数字都在 = 右侧,例如
x+5-3+x=6+x-2
x+x-x=6-2-5+3
把在原始方程左边的 x 看做正值,右边的 x 看做负值。同理,原始方程左边每个数字都被看做负数,右边每个数字都看作正数。那么 lhs 包含了方程中所有的 x,rhs 包含了方程中所有的数字。

public class Solution {
    
    public String solveEquation(String equation) {
        //将等式从=处分割
        String[] lr = equation.split("=");
        int lhs = 0, rhs = 0;
        for (String x: breakIt(lr[0])) {
            if (x.indexOf("x") >= 0) {
                lhs += Integer.parseInt(coeff(x));
            } else
                rhs -= Integer.parseInt(x);
        }
        for (String x: breakIt(lr[1])) {
            if (x.indexOf("x") >= 0)
                lhs -= Integer.parseInt(coeff(x));
            else
                rhs += Integer.parseInt(x);
        }
        if (lhs == 0) {
            if (rhs == 0)
                return "Infinite solutions";
            else
                return "No solution";
        }
        return "x=" + rhs / lhs;
    }
    //处理等式一边,放到一个集合list中
    public List < String > breakIt(String s) {
        List < String > res = new ArrayList < > ();
        String r = "";
        for (int i = 0; i < s.length(); i++) {
            if (s.charAt(i) == '+' || s.charAt(i) == '-') {
                if (r.length() > 0)
                    res.add(r);
                r = "" + s.charAt(i);
            } else
                r += s.charAt(i);
        }
        res.add(r);
        return res;
    }
    //处理 x
    public String coeff(String x) {
        //例如 5x的情况 返回5
        if (x.length() > 1 && x.charAt(x.length() - 2) >= '0' && x.charAt(x.length() - 2) <= '9')
            return x.replace("x", "");
        //如果只有x返回1 -x返回-1
        return x.replace("x", "1");
    }
}

question 38(外观数列)

在这里插入图片描述
answer
每次遍历前一个String 用stringBuilder存中间结果

class Solution {
    public String countAndSay(int n) {
        String str = "1";
        for(int i=2;i<=n;i++){
            StringBuilder sb=new StringBuilder();
            //哨兵开始位置
            int start=0;
            //指针走动位置,去遍历前一个string
            int pos=0;
            while(pos<str.length()){
                while(pos<str.length()&&str.charAt(pos)==str.charAt(start)){
                    pos++;
                }
                sb.append(Integer.toString(pos-start)).append(str.charAt(start));
                start=pos;
            }
            str=sb.toString();
        }
        return str;
    }
}

question 443(压缩字符串)

在这里插入图片描述

class Solution {
    public int compress(char[] chars) {
        int n = chars.length;
        //left 是遍历不同字符的起点,write记录有多少个字符
        int write = 0, left = 0;
        for (int i = 0; i < n; i++) {
            if (i == n - 1 || chars[i] != chars[i + 1]) {
                chars[write++] = chars[i];
                  int count = i - left + 1;
                  if (count > 1) {
                      //如果count>9要分割
                     String str = String.valueOf(count);
                     for (int j = 0; j < str.length(); j++){
                     chars[write++] = str.charAt(j);
                    }
                }
                left = i + 1;
            }
        }
        return write;
    }
}

question 8(字符串转整数)

在这里插入图片描述
answer

class Solution {
    public int myAtoi(String s) {
        //去掉前面空格
        s=s.trim();
        //把s转化为数组
        char[] str=s.toCharArray();
        int len=str.length;
        if(len==0){
            return 0;
        }
        int flag=1;
        int index=0;
        //+-号只能存在第一位
        if(str[0]=='+'){
            flag=1;
            index++;
        }else if(str[0]=='-'){
            flag=-1;
            index++;
        }
        int res=0;
        while(index<len&&(str[index]>='0'&&str[index]<='9')){
            //res*10+(str[index]-'0')>max
            int temp=str[index]-'0';
            if(flag==1){
                if(res>(Integer.MAX_VALUE-temp)/10){
                return  Integer.MAX_VALUE;
               }
            }else if(flag==-1){
                 //-res*10-(str[index]-'0')<min
                if(-res<(Integer.MIN_VALUE+temp)/10){
                return  Integer.MIN_VALUE;
                }
            }
            res =res*10+temp; 
            index++;                   
        }
         return res*flag;
    }
    
}

question 13(罗马数字转整数)

在这里插入图片描述
answer

class Solution {
    public int romanToInt(String s) {
        char[] str=s.toCharArray();
        int index=0,len=str.length;
        int res=0;
        while(index<len){
            int temp=0;
            switch(str[index]){
                case 'I' : temp=1; break;
                case 'V' : temp=5; break;
                case 'X' : temp=10; break;
                case 'L' : temp=50; break;
                case 'C' : temp=100; break;
                case 'D' : temp=500; break;
                case 'M' : temp=1000; break;
            }
            if(index+1<len&&(temp==1||temp==10||temp==100)){
                if(temp==1&&str[index+1]=='V'){
                    res+=4;
                    index+=2;
                    continue;
                }else if(temp==1&&str[index+1]=='X'){
                    res+=9;
                   index+=2;
                    continue;
                }else if(temp==10&&str[index+1]=='L'){
                    res+=40;
                    index+=2;
                    continue;
                }else if(temp==10&&str[index+1]=='C'){
                    res+=90;
                   index+=2;
                    continue;
                }else if(temp==100&&str[index+1]=='D'){
                    res+=400;
                    index+=2;
                    continue;
                }else if(temp==100&&str[index+1]=='M'){
                    res+=900;
                    index+=2;
                    continue;
                }
            }
            res+=temp;
            index++;
        }
        return res;
    }
}

管解更好
在这里插入图片描述

class Solution {
    Map<Character, Integer> symbolValues = new HashMap<Character, Integer>() {{
        put('I', 1);
        put('V', 5);
        put('X', 10);
        put('L', 50);
        put('C', 100);
        put('D', 500);
        put('M', 1000);
    }};

    public int romanToInt(String s) {
        int ans = 0;
        int n = s.length();
        for (int i = 0; i < n; ++i) {
            int value = symbolValues.get(s.charAt(i));
            if (i < n - 1 && value < symbolValues.get(s.charAt(i + 1))) {
                ans -= value;
            } else {
                ans += value;
            }
        }
        return ans;
    }
}

question 12(整数转罗马数字)

在这里插入图片描述
answer

class Solution {
    public String intToRoman(int num) {
        int[] arr={1000,900,500,400,100,90,50,40,10,9,5,4,1};
        String[] str={"M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I"};
        StringBuilder sb=new StringBuilder();
        for(int i=0;i<13;i++){
            int temp=arr[i];
            while(num>=temp){
                sb.append(str[i]);
                num-=temp;
            }
            if(num==0){
                break;
            }
        }
        return sb.toString();
    }
}

七、子序列

question 392(判断子序列)

在这里插入图片描述
answer

class Solution {
    public boolean isSubsequence(String s, String t) {
       if((s==null&&t==null)||(s.length()==0&&t.length()==0)){
           return true;
       }
       if(s==null||t==null||s.length()>t.length()){
           return false;
       } 
        int n = s.length(), m = t.length();
        int i = 0, j = 0;
        while (i < n && j < m) {
            if (s.charAt(i) == t.charAt(j)) {
                i++;
            }
            j++;
        }
        return i == n;
    }
}

question 524(通过删除字母匹配到字典里最长单词)

在这里插入图片描述
answer
先对字符串排序,再判断是否为子串

class Solution {
    public String findLongestWord(String s, List<String> dictionary) {
        // 即返回值为正数时,交换数组中正在比较的
		// 两个元素的位置,返回值为负数时,不交换。 
        //比较器
        Collections.sort(dictionary,(String word1,String word2)->{
            if(word1.length()!=word2.length()){
               return word2.length()-word1.length();
            }else{
                return word1.compareTo(word2);
            }
        });
        //遍历dictionary列表
        for(String t:dictionary){
            int i=0,j=0;
            while(i<t.length()&&j<s.length()){
                if(t.charAt(i)==s.charAt(j)){
                    i++;
                }
                j++;
            }
            if(i==t.length()){
                return t;
            }
        }
        return "";
    }
}

question 522(最长特殊序列)

在这里插入图片描述

public class Solution {
    //x是否为y的子串
    public boolean isSubsequence(String x, String y) {
        int j = 0;
        int i = 0;
      while( i < y.length() && j < x.length() )
           { if (x.charAt(j) == y.charAt(i))
                { 
                    j++;
                }
                i++;
           }
        return j == x.length();
    }
    public int findLUSlength(String[] strs) {
        int res = -1;
        //遍历每一个字符串
        for (int i = 0, j; i < strs.length; i++) {
            for (j = 0; j < strs.length; j++) {
                if (j == i)
                    continue;
                if (isSubsequence(strs[i], strs[j]))
                    break;
            }
            //如果str[i]不是其他字符的子序列
            if (j == strs.length)
                res = Math.max(res, strs[i].length());
        }
        return res;
    }
}

八、高精度运算

question 66(加一)

在这里插入图片描述
answer
只有整数为9时,才需要进位

class Solution {
    public int[] plusOne(int[] digits) {
        int len=digits.length;
        for(int i=len-1;i>=0;i--){
            digits[i]=(digits[i]+1)%10;
            if(digits[i]!=0){
                return digits;
            }
        }
        //首位还需进一,扩展数组长度
        int res[]=new int[len+1];
        res[0]=1;
        for(int i=1;i<len+1;i++){
            res[i]=digits[i-1];
        }
        return res;
    }
}

question 67(二进制求和)

在这里插入图片描述
answer

class Solution {
    public String addBinary(String a, String b) {
        StringBuffer ans = new StringBuffer();
        //carry存储进位数
        int n = Math.max(a.length(), b.length()), carry = 0;
        for (int i = 0; i < n; ++i) {
            carry += i < a.length() ? (a.charAt(a.length() - 1 - i) - '0') : 0;
            carry += i < b.length() ? (b.charAt(b.length() - 1 - i) - '0') : 0;
            ans.append((char) (carry % 2 + '0'));
            carry /= 2;
        }

        if (carry > 0) {
            ans.append('1');
        }
        ans.reverse();

        return ans.toString();
    }
}

question 415(字符串相加)

在这里插入图片描述
answer

class Solution {
    public String addStrings(String num1, String num2) {
        //add存储进位
        int i = num1.length() - 1, j = num2.length() - 1, add = 0;
        StringBuffer ans = new StringBuffer();
        while (i >= 0 || j >= 0 || add != 0) {
            int x = i >= 0 ? num1.charAt(i) - '0' : 0;
            int y = j >= 0 ? num2.charAt(j) - '0' : 0;
            int result = x + y + add;
            ans.append(result % 10);
            add = result / 10;
            i--;
            j--;
        }
        // 计算完以后的答案需要翻转过来
        ans.reverse();
        return ans.toString();
    }
}

question 43(字符串相乘)

在这里插入图片描述
answer
在这里插入图片描述

class Solution {
    public String multiply(String num1, String num2) {
        //num1,num2有一个为0,返回0
        if(num1.equals("0")||num2.equals("0")){
            return "0";
        }
        int len1=num1.length();
        int len2=num2.length();
        String res="0";
        //num2中的每一项,分别×num1,再累加
        for(int i=len2-1;i>=0;i--){
            StringBuilder sb=new StringBuilder();
            //补齐0
            for(int j=len2-1;j>i;j--){
                sb.append(0);
            }
            //sum存进位
            int sum=0;
            int temp=num2.charAt(i)-'0';
            for(int d=len1-1;d>=0;d--){
                int cur=num1.charAt(d)-'0';
                sb.append((sum+cur*temp)%10);
                sum=(sum+cur*temp)/10;
            }
            if(sum!=0){
                sb.append(sum);
            }
            res=addString(res,sb.reverse().toString());

        }
         return res;
    }
    //两个字符串相加
      public String addString(String s1,String s2){
            int m=s1.length()-1;
            int n=s2.length()-1;
            int add=0;
            StringBuilder ans=new StringBuilder();
            while(m>=0||n>=0||add!=0){
                int temp1= m>=0? s1.charAt(m)-'0' : 0;
                int temp2= n>=0? s2.charAt(n)-'0' : 0;
                ans.append((temp1+temp2+add)%10);
                add=(temp1+temp2+add)/10;
                m--;
                n--;
            }
            ans.reverse();
            return ans.toString();
        }
}

question 306(累加数)

在这里插入图片描述
answer

class Solution {
    public boolean isAdditiveNumber(String num) {
        //当它的第一个数字和第二个数字以及总长度确定后,这整个累加序列也就确定了。
        //根据这个性质,我们可以穷举累加序列的第一个数字和第二个数字的所有可能性
        int n=num.length();

       //第二个数的起始位置,从下标1开始枚举
        for(int secondStart=1;secondStart<n-1;secondStart++){
            //除数字 0 之外,不能以 0 开头
            if(num.charAt(0)=='0'&&secondStart!=1){
                break;
            }
            //第二个数的结束位置,从第二个数的开始位置枚举
            for(int secondEnd=secondStart;secondEnd<n-1;secondEnd++){
                // 当某个数字长度大于等于 2 时,这个数字不能以 0 开头,
                if(num.charAt(secondStart)=='0'&&secondStart!=secondEnd){
                    break;
                }
                //判断是否为有效的累加数列
                if(valid(secondStart,secondEnd,num)){
                    return true;
                }
            }
        }
        return false;
    }
    public boolean valid(int secondStart,int secondEnd,String num){
        int n=num.length();
        //第一个数起止位置
        int firstStart=0,firstEnd=secondStart-1;
        while(secondEnd<=n-1){
            //第三个数的值
            String third=stringAdd(num,firstStart,firstEnd,secondStart,secondEnd);
            //第三个数起止位置
            int thirdStart=secondEnd+1;
            int thirdEnd=secondEnd+third.length();
            //判断第三个数的值是否与截取下标位置的数相等
            if(thirdEnd>=n||!num.substring(thirdStart,thirdEnd+1).equals(third)){
                break;
            }
            if(thirdEnd==n-1){
                return true;
            }
            firstStart=secondStart;
            firstEnd=secondEnd;
            secondStart=thirdStart;
            secondEnd=thirdEnd;
        }
          return false;
    }
    //两个字符串的和
    public String stringAdd(String s,int firstStart,int firstEnd,int secondStart,int secondEnd){
        StringBuffer third=new StringBuffer();
        int carry=0,cur=0;
        while(firstStart<=firstEnd||secondStart<=secondEnd||carry!=0){
            cur=carry;
            if(firstStart<=firstEnd){
                cur+=s.charAt(firstEnd)-'0';
                firstEnd--;
            }
            if(secondStart<=secondEnd){
                cur+=s.charAt(secondEnd)-'0';
                secondEnd--;
            }
            carry=cur/10;
            cur=cur%10;
            third.append(cur);
        }
        third.reverse();
        return third.toString();
    }
}

九、字符串变换

question 482(密钥格式化)

在这里插入图片描述
answer
因为第一组长度可以比K短,其余组长度需要等于K,所以从后往前遍历读取

class Solution {
    public String licenseKeyFormatting(String s, int k) {
        char[] arr=s.toCharArray();
        StringBuffer res=new StringBuffer();
        int len=arr.length;
        int temp=0;
        for(int i=len-1;i>=0;i--){
            if(arr[i]!='-'){
                res.append(Character.toUpperCase(arr[i]));
                temp++;
                //每K个数插入 -
                if(temp%k==0){
                res.append("-");
               }
            }           
        }
        //如果最前面为 ‘-’ ,则删除
        if(res.length()>0&&res.charAt(res.length()-1)=='-'){
            res.deleteCharAt(res.length()-1);
        }
        res.reverse();
        return res.toString();
    }
}

question 6(z字变换)

在这里插入图片描述

answer
把字符串一列一列的填充,,2*numRows-2为一组填充的数字(1234 32//123 2 )

class Solution {
    public String convert(String s, int numRows) {
        int len=s.length();
        if(len==1||len<=numRows||numRows==1){return s;}
        int r=numRows;
        //创建一个buffer数组,保存对应每一行的字符
        StringBuffer[] cur=new StringBuffer[r];
        for(int i=0;i<r;i++){
            cur[i]=new StringBuffer();
        }
        int tag=2*r-2;
        //buffer   cur[]的下标
        int j=0;
        for(int i=0;i<len;i++){
            cur[j].append(s.charAt(i));
            if((i%tag)<r-1){
                j++;
            }else{
                j--;
            }
        }
        StringBuffer res=new StringBuffer();
        for(StringBuffer sb:cur){
            res.append(sb);
        }
        return res.toString();
    }
}

question 68*

十、字符串匹配

question 28(实现IndexOf())

在这里插入图片描述
answer

class Solution {
    public int strStr(String haystack, String needle) {
        if(needle==null){return 0;}
        int i=0,j=0;
        int temp=0;
        while(i<haystack.length()&&j<needle.length()){
            if(haystack.charAt(i)==needle.charAt(j)){
                i++;
                j++;
                temp++;
            }else{
                j=0;
                i=i-temp+1;
                temp=0;
            }
        }
        if(j==needle.length()){
            return i-j;
        }
        return -1;
    }
}

KMP更好啦,,,

question 686(重复叠加字符串匹配)

在这里插入图片描述

answer

class Solution {
    public int repeatedStringMatch(String a, String b) {
        StringBuffer arr=new StringBuffer();
        int  res=0;
        //字符长度的最大值,因为一个完整的B可能首部用到A的一部分,尾部用到A的一部分故总长<=2*A+B
        int max=2*a.length()+b.length();
        while(arr.length()<max){
            arr.append(a);
            res++;
            if(arr.toString().indexOf(b)!=-1){
                return res;
            }
        }
        return -1;
    }
}

question 459(重复的子字符串)

在这里插入图片描述
answer

class Solution {
    public boolean repeatedSubstringPattern(String s) {
        int n = s.length();
        if(n<=1) return false;
        Set<String> set = new HashSet<>();
        //i枚举子字符串的长度
        for(int i=1;i<n;i++){
            //len=8  子字符串长度,可能划分2 2 2 2/4 4///3,5,6,7不可能
            if(n%i!=0) continue;
            set.clear();

            for(int j=0;j<=n-i;j+=i){  
                //把每个子字符串添加到set中
                set.add(s.substring(j,j+i));
            }
            if(set.size()==1) return true;
        }

        return false;
    }
}

question 214*

十一、中心拓展法

question 5(最长回文串)

在这里插入图片描述
answer
动态规划

class Solution {
     //转移方程
     //p(i,i)=true
     //p(i,i+1)=(Si==S(i+1))
     //p(i,j)=p(i+1,j-1)^(Si==Sj)
    public String longestPalindrome(String s) {
        int len=s.length();
        if(len<2){return s;}
        //dp[i][j] 表示(si,sj)之间是否是回文串
        boolean[][] dp=new boolean[len][len];
        //初始长度为1的子串都是回文串
        for(int i=0;i<len;i++){
            dp[i][i]=true;
        }
        int maxLen=1;
        int begin=0;
        char[] array=s.toCharArray();
        //递推开始,枚举子串长度,l:长度
        for(int l=2;l<=len;l++){
            //i代表左边界
            for(int i=0;i<len;i++){
                //由ll和i可以确定右边界j,即j-i+1=l
                int j=l-1+i;
                if(j>=len){
                    break;
                }
                //i左边界,j有边界,判断两个字符是否相等
                if(array[i]!=array[j]){
                    dp[i][j]=false;
                }else{
                    //如果长度为2直接设置为true,否则 看dp[i+1][j-1]
                    if(j-i<3){
                        dp[i][j]=true;
                    }else{
                        dp[i][j]=dp[i+1][j-1];
                    }
                }
                //如果dp[i][j]==true,即为回文串,记录回文串长度和起始位置
                if(dp[i][j]==true&&l>maxLen){
                    maxLen=l;
                    begin=i;
                }
            }
        }
        return s.substring(begin,begin+maxLen);
    }

}

answer2 中心扩展

在这里插入图片描述

class Solution {
    
    public String longestPalindrome(String s) {
        if (s == null || s.length() < 1) {
            return "";
        }
        int start = 0, end = 0;
        for (int i = 0; i < s.length(); i++) {
            //长度奇数偶数
            int len1 = expandAroundCenter(s, i, i);
            int len2 = expandAroundCenter(s, i, i + 1);
            int len = Math.max(len1, len2);
            if (len > end - start) {
                start = i - (len-1) / 2;
                end = i + len / 2;
            }
        }
        return s.substring(start, end + 1);
    }

    public int expandAroundCenter(String s, int left, int right) {
        while (left >= 0 && right < s.length() && s.charAt(left) == s.charAt(right)) {
            --left;
            ++right;
        }
        return right - left - 1;
    }
}

question 647(回文子串)

在这里插入图片描述
answer 动态规划

class Solution {
    public int countSubstrings(String s) {
        int len=s.length();
        if(len<2){return len;}
        int sum=0;
        boolean[][] dp=new boolean[len][len];
        //初始化长度为1的子串
        for(int i=0;i<len;i++){
            dp[i][i]=true;
            sum++;
        }
        //从2开始枚举子串长度
        for(int l=2;l<=len;l++){
            //枚举左边界
            for(int i=0;i<len;i++){
                //右边界j j-i+1=len
                int j=l-1+i;
                if(j>=len){
                    break;
                }
                if(s.charAt(i)!=s.charAt(j)){
                    dp[i][j]=false;
                }else{
                    if(l<3){
                        dp[i][j]=true;
                    }else{
                        dp[i][j]=dp[i+1][j-1];
                    }
                }
                if(dp[i][j]==true){
                    sum++;
                }
            }
        }
        return sum;
    }
}

answer2 中心扩展
枚举出所有的子串,然后再判断这些子串是否是回文;
枚举每一个可能的回文中心,然后用两个指针分别向左右两边拓展,当两个指针指向的元素相同的时候就拓展,否则停止拓展

class Solution {
public:
    int countSubstrings(string s) {
        int n = s.size(), ans = 0;
        for (int i = 0; i < 2 * n - 1; ++i) {
            // 中心有(i,i),(i,i+1)两种
            int l = i / 2, r = i / 2 + i % 2;
            while (l >= 0 && r < n && s[l] == s[r]) {
                --l;
                ++r;
                ++ans;
            }
        }
        return ans;
    }
};
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值