字符串

925. 长按键入

image.png
思路: 使用两个指针判断当前的字符,如果一样的话两个都+1 如果不一样的话看看是不是和前一位一样,一样的话跳过

  1. class Solution {
  2. public boolean isLongPressedName(String name, String typed) {
  3. int len1 = name.length();
  4. int len2 = typed.length();
  5. if(len2<len1){return false;}
  6. int i=0,j=0;
  7. while(i<len1 && j<len2){
  8. if(name.charAt(i)== typed.charAt(j)){
  9. i++;
  10. j++;
  11. }else if(j>0 && typed.charAt(j-1)== typed.charAt(j)){
  12. j++;
  13. }else{
  14. return false;
  15. }
  16. }
  17. if(i<len1){
  18. return false;
  19. }else{
  20. while(j<len2){
  21. if(i>0 && name.charAt(i-1)==typed.charAt(j)){
  22. j++;
  23. }else{
  24. return false;
  25. }
  26. }
  27. return true;
  28. }
  29. }
  30. }

1002. 查找常用字符

image.png
这道题需要我们求的是,在这个数组里面,每一个str里面,每一个字符出现的次数。 这个出现的次数是所有的共同次数。 就用一个freq 和当前的str里面的频率。 取得里面的最小值

  1. class Solution {
  2. public List<String> commonChars(String[] A) {
  3. int[] freq = new int[26];
  4. List<String> res = new LinkedList<>();
  5. Arrays.fill(freq,Integer.MAX_VALUE);
  6. for(String str:A){
  7. int[] fre = new int[26];
  8. for (int i = 0; i < str.length(); i++) {
  9. fre[str.charAt(i)-'a']++;
  10. }
  11. for (int i = 0; i < 26; i++) {
  12. freq[i] = Math.min(fre[i],freq[i]);
  13. }
  14. }
  15. for (int i = 0; i < 26; i++) {
  16. for (int j = 0; j < freq[i]; j++) {
  17. res.add(String.valueOf((char)(i+'a')));
  18. }
  19. }
  20. return res;
  21. }
  22. }

402. 移掉K位数字

image.png
扫描k次,每次找到后面比前面大的数,删掉,不然的话就删除最前面的数字。

  1. class Solution {
  2. public String removeKdigits(String num, int k) {
  3. StringBuilder sb = new StringBuilder(num);
  4. if (num.length() == k) return "0";
  5. for (int i = 0; i < k; i++) {
  6. int index = 0;
  7. for (int j = 1; j < sb.length()&& sb.charAt(j)>=sb.charAt(j-1); j++) {
  8. index = j;
  9. }
  10. sb.delete(index,index+1);
  11. while (sb.length()>1&& sb.charAt(0)=='0'){
  12. sb.delete(0,1);
  13. }
  14. }
  15. return sb.toString();
  16. }
  17. }

647. 回文子串

image.png
最简单的暴力的方法,遍历整个长度,截取里面的每一段,去判断一下。

  1. class Solution {
  2. int res = 0;
  3. public int countSubstrings(String s) {
  4. for (int i = 0; i < s.length(); i++) {
  5. count(s,i,i);
  6. count(s,i,i+1);
  7. }
  8. return res;
  9. }
  10. private void count(String s, int start, int end) {
  11. while (start>=0&& end<s.length() && s.charAt(start) == s.charAt(end)){
  12. res++;
  13. start --;
  14. end++;
  15. }
  16. }
  17. }

解法二: 对于每一个位置的i,判断i开始的和i,i+1开始的。里面投几个回文串

  1. class Solution {
  2. int res = 0;
  3. public int countSubstrings(String s) {
  4. for (int i = 0; i < s.length(); i++) {
  5. count(s,i,i);
  6. count(s,i,i+1);
  7. }
  8. return res;
  9. }
  10. private void count(String s, int start, int end) {
  11. while (start>=0&& end<s.length() && s.charAt(start) == s.charAt(end)){
  12. res++;
  13. start --;
  14. end++;
  15. }
  16. }
  17. }

14. 最长公共前缀

image.png
思路:
先把里面的字符串拆分出来看一下,对于两个字符串我们怎么进行一个匹配?
用两个指针分别指向头,开始循环,遇到不一样的时候就break,记录相同的位置,做一个切片。
基本的操作就是这样的,加上列表的循环就是答案了。

class Solution {
    public String longestCommonPrefix(String[] strs) {
        String ans = "";
        if(strs.length<1)return ans;

        ans = strs[0];

        for (int i=0;i<strs.length;i++){
            int j=0;
            for (int g=0;j<ans.length() && g<strs[i].length();j++,g++){
                if(ans.charAt(j)!=strs[i].charAt(g)){
                    break;
                }
            }
            ans = ans.substring(0,j);
        }
        return ans;
    }
}

8. 字符串转换整数 (atoi)

首先把空格给去掉,接着对正负号进行处理。最后是需要对溢出的情况做一个处理。在+和x10的情况里面都可能会出现溢出的情况。处理的方式 ans*10+tmp< Integer.MIN_VALUE ,做一个变化,就可以得到这个判断式子。

class Solution {
    public int myAtoi(String str) {
        char[] res = str.toCharArray();
        int i =0;
        while (i<res.length&&res[i]==' '){
            i++;
        }
        if(i == res.length) return 0;
        boolean isNagative = false;
        if(res[i] =='-'){
            isNagative =true;
            i++;
        }else if(res[i] =='+'){
            i++;
        }
        int ans = 0;
        while (i<res.length&&Character.isDigit(res[i])){
            int tmp = res[i] -'0';
            if(ans>(Integer.MAX_VALUE-tmp)/10){
                return isNagative?Integer.MIN_VALUE:Integer.MAX_VALUE;
            }
            ans=ans*10+tmp;
            i++;
        }
        return isNagative?-ans:ans;

    }
}

1071-字符串的最大公因数

image.png

思路: 首先 str1+str2 ==str2+str1 然后使用辗转相除法

class Solution {
    public String gcdOfStrings(String str1, String str2) {
        /*
        如果 str1 和 str2 存在最大公约数 str,那么就相当于 str1 和 str2 都是由 str 组成的,那么 str1 + str2 和 str2 + str1 应该是相等的
        如果不满足,那么不存在最大公约数

        我们可以通过 两个字符串的长度来求得最大公约数的长度
        比如 str1 = "ABABAB", str2 = "ABAB"
            len1 = 6         len2 = 4
            那么最大公约数 str = "AB"
                         len = 2
        */
        if(!(str1+str2).equals(str2+str1)){
            return "";
        }

        return str1.substring(0,gcd(str1.length(),str2.length()));

    }

    private int gcd(int a,int b){
        return b==0?a:gcd(b,a%b);
    }
}

面试题 01.06. 字符串压缩

image.png
思路:
使用一个Stringbuilder来接受判断的字符。从头开始遍历,记录一下pre和cur,做一下比较。如果一致的话,次数加一。如果不是的话,将这个字符和次数添加到res里面。最终比较一下里面的大小。

class Solution {
    public String compressString(String S) {
        if(S ==null || S.length()==0){
            return S;
        }

        StringBuilder res = new StringBuilder();

        char pre = S.charAt(0);
        int times = 1;

        for(int i=1;i<S.length();i++){
            char cur = S.charAt(i);
            if(cur == pre){
                times++;
            }else{
                res.append(pre);
                res.append(times);
                pre = cur;
                times = 1;
            }
        }
        res.append(pre);
        res.append(times);

        if(res.length()>=S.length()){
            return S;
        }
        return res.toString();

    }
}

804. 唯一摩尔斯密码词

image.png
思路:
吧每一个单词转换为摩斯电码,加入到set中,最后取出size

class Solution {
    public int uniqueMorseRepresentations(String[] words) {
        String[] codes = {".-","-...","-.-.","-..",".","..-.","--.","....","..",".---","-.-",".-..","--","-.","---",".--.","--.-",".-.","...","-","..-","...-",".--","-..-","-.--","--.."};

        Hash  Set<String> set = new HashSet<>();
        for(String word:words){
            StringBuilder res = new StringBuilder();
            for(int i=0;i<word.length();i++){
                res.append(codes[word.charAt(i)-'a']);
            }
            set.add(res.toString());
        }
        return set.size();
    }
}

409. 最长回文串

image.png
思路:
首先需要统计一下给定字符串的各个字母出现的次数。这里可以使用哈希表来做,也可以使用数组来做。统计完之后我们需要计算res。因为回文串中最多只有一个字母可以出现奇数次。 假如a出现了3次我们需要res增加2次。如果是a出现了1次。不能增加。 这里有一个好方法,res+=x-(x&1)。 非常的漂亮。
ascii 码中 A是65 a是97

class Solution {
    public int longestPalindrome(String s) {
        if(s.length()<1) return 0;
        HashMap<Character,Integer> map = new HashMap<>();

        for(int i=0;i<s.length();i++){
            if(!map.containsKey(s.charAt(i))){
                map.put(s.charAt(i),1);
            }else {
                map.put(s.charAt(i),map.get(s.charAt(i))+1);
            }
        }
        int res = 0;
        System.out.println(map.toString());
        for(Character c:map.keySet()){
           res += map.get(c)-(map.get(c)&1);
        }
        return res<s.length()?res+1:res;
    }
}