数据结构与算法学习⑪(字符串算法)

本文详细介绍了多种字符串算法的解法,包括将字符串转换为小写、查找最后一个单词长度、宝石与石头问题、首个唯一字符定位、最长公共前缀、单词翻转、正则表达式匹配、不同子序列计算以及实现strStr()函数。涉及到的算法思路包括位运算、哈希表、双指针、递归与分治等。
摘要由CSDN通过智能技术生成

数据结构与算法学习⑪(字符串算法)

709. 转换成小写字母

709. 转换成小写字母

解法1:使用内置API,不推荐
解法2:ASCCII码操作
在线ASCCII对照表

发现:
a-z:97-122
A-Z:65-90
0-9:48-57
大写字母和小写字母之间差了32,故,遍历字符串中的每个字符,如果是大小字母,加上32即可

class Solution {
    public String toLowerCase(String str) {
       char[]result= str.toCharArray();
            for(int i=0;i<result.length;i++){
                if(result[i]>='A'&&result[i]<='Z'){
                    result[i]+=32;
                }
            }
            return new String(result);
    }
}

解法3:位运算
基于ASCCII码的区别,使用位运算的技巧。

  • 大写变小写、小写变大写:字符 ^= 32;

异或操作的另一种理解方式:不进位加法

在这里插入图片描述

class Solution {
    public String toLowerCase(String str) {
       char[]result= str.toCharArray();
            for(int i=0;i<result.length;i++){
                if(result[i]>='A'&&result[i]<='Z'){
                    result[i]|=32;
                }
            }
            return new String(result);
    }
}

58. 最后一个单词的长度

58. 最后一个单词的长度

优秀题解

class Solution {
    public int lengthOfLastWord(String s) {
          int count=0;
          int right=s.length()-1;
             
         while(right>=0&&s.charAt(right)==' '){
                  right--;
        }

        while(right>=0&&s.charAt(right)!=' '){
            right--;
            count++;
        }
        return count;
          
    }
}

771. 宝石与石头

771. 宝石与石头

解法1:暴力,遍历S,对于 S 中的每个字符,遍历一次字符串 J,如果其和 J 中的某一个字符相同,
则是宝石。—不推荐
解法2:哈希集合
此处只需要用一个基础的数组即可,因为题设条件说了: J 中的字母不重复, J 和 S 中的所有字
符都是字母。字母区分大小写。

搞一个数组存放64个,也就是大小写所有的位置,然后遍历查看

class Solution {
    public int numJewelsInStones(String jewels, String stones) {
           int[]hash=new int[64];
           char[]js=jewels.toCharArray();
           for(char c:js){
               hash[c-'A']++;
           }

           int count=0;
           char[]s=stones.toCharArray();
           for(int i=0;i<s.length;i++){
               if(hash[s[i]-'A']!=0){
                    count++;
               }
           }
           return count;
    }
}

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

387. 字符串中的第一个唯一字符
题意说明: 第一个不重复的字符,并非指字符串中前后两个字符不重复, 这里的意思是: 对于某个字母,
它在整个字符串中是否有重复的,
解法1: 哈希表辅助,两次遍历,一次遍历求出现的频率,二次遍历找第一个出现频率为1的字符

class Solution {
    public int firstUniqChar(String s) {
           int[]hash=new int[32];
           char[]strs=s.toCharArray();

           for(char str:strs){
               hash[str-'a']++;
           }

           for(int i=0;i<strs.length;i++){
               if(hash[strs[i]-'a']==1){
                   return i;
               }
           }
           return -1;
    }
}

多解法

14. 最长公共前缀

14. 最长公共前缀
在这里插入图片描述

在这里插入图片描述
分治+前缀比较

class Solution {
    public String longestCommonPrefix(String[] strs) {
        if(strs.length==0||strs==null){
            return "";
        }
         return findfix(strs,0,strs.length-1);
    }

    public String findfix(String[] strs,int start,int end){

        if(start>=end){
            return strs[start];
        }
        int mid=((end-start)>>1)+start;

        String left=findfix(strs,start,mid);
        String right=findfix(strs,mid+1,end);
        
       return  fix(left,right);
    }

    public String fix(String left,String right){
        StringBuilder sb=new StringBuilder();

        int smallLength=left.length()>=right.length()?right.length():left.length();
     
        for(int i=0;i<smallLength;i++){
            if(left.charAt(i)!=right.charAt(i)){
                break;
            }
            sb.append(left.charAt(i));
            
        }
        return sb.toString();

    }

}

下面这个不用Stringbuilder拼接,更省空间

class Solution {
    public String longestCommonPrefix(String[] strs) {
        if (strs == null || strs.length == 0) {
            return "";
        } else {
            return longestCommonPrefix(strs, 0, strs.length - 1);
        }
    }

    public String longestCommonPrefix(String[] strs, int start, int end) {
        if (start == end) {
            return strs[start];
        } else {
            int mid = (end - start) / 2 + start;
            String lcpLeft = longestCommonPrefix(strs, start, mid);
            String lcpRight = longestCommonPrefix(strs, mid + 1, end);
            return commonPrefix(lcpLeft, lcpRight);
        }
    }

    public String commonPrefix(String lcpLeft, String lcpRight) {
        int minLength = Math.min(lcpLeft.length(), lcpRight.length());       
        for (int i = 0; i < minLength; i++) {
            if (lcpLeft.charAt(i) != lcpRight.charAt(i)) {
                return lcpLeft.substring(0, i);
            }
        }
        return lcpLeft.substring(0, minLength);
    }
}

151. 翻转字符串里的单词

151. 翻转字符串里的单词

class Solution {
    public String reverseWords(String s) {
        StringBuilder sb=new StringBuilder();
        way(s,sb,0);
       return sb.toString().trim();
    }

    public void way(String s,StringBuilder sb,int left){
      
        while(left<s.length()&&s.charAt(left)==' '){
            left++;
        }
        if(left==s.length()){
            return;
        }
        int right=left;
        while(right<s.length()&&s.charAt(right)!=' '){
            right++;
        }
        way(s,sb,right);
        sb.append(s,left,right).append(" ");
    }
}

还有一些加油
344. 反转字符串
345. 反转字符串 II
346. 反转字符串中的单词 III
347. 仅仅反转字母
348. 验证回文串
349. 验证回文字符串 Ⅱ

10. 正则表达式匹配

10. 正则表达式匹配
在这里插入图片描述

class Solution {
    
    public boolean isMatch(String s, String p) {
            char[]ss=s.toCharArray();
            char[]pp=p.toCharArray();
            return isMatch(ss,0,pp,0);

    }

    public boolean isMatch(char[]ss,int left,char[]pp,int right){
        if(pp.length==right){
            return left==ss.length;
        }

        boolean isMatch=left<ss.length&&(ss[left]==pp[right]||pp[right]=='.');
        //左边的判断条件是防止越界
         if(pp.length-right>=2&&pp[right+1]=='*'){
             //第一种是为0,也就是直接跳过a和*,匹配后面的
             //第二章是往后匹配
             return isMatch(ss,left,pp,right+2)||(isMatch&&isMatch(ss,left+1,pp,right));
         }
         return isMatch&&isMatch(ss,left+1,pp,right+1);      
    }
}

dp
在这里插入图片描述

class Solution {
    
    public boolean isMatch(String s, String p) {
            char[]ss=s.toCharArray();
            char[]pp=p.toCharArray();

boolean [][] dp = new boolean[ss.length+1][pp.length+1];

         dp[0][0]=true;
         for(int k=0;k<pp.length;k++){
             if(pp[k]=='*'&&dp[0][k-1]){
                 dp[0][k+1]=true;
             }
         }


      for(int i=1;i<=ss.length;i++){
          for(int j=1;j<=pp.length;j++){
              if(ss[i-1]==pp[j-1]||pp[j-1]=='.'){
                  dp[i][j]=dp[i-1][j-1];
              }else if(pp[j-1]=='*'){
                  if(pp[j-1-1]==ss[i-1]||pp[j-1-1]=='.'){
                      dp[i][j]=dp[i-1][j]||dp[i][j-2];
                  }else{
                      dp[i][j]=dp[i][j-2];
                  }
              }
          }
      }
      return dp[ss.length][pp.length];
   
    }

}

115. 不同的子序列

115. 不同的子序列

在这里插入图片描述

class Solution {
    public int numDistinct(String s, String t) {
           char[]ss=s.toCharArray();
           char[]tt=t.toCharArray();
           int n=ss.length;
           int m=tt.length;
           int[][]dp=new int[n+1][m+1];
           
           for(int k=0;k<m;k++){
               dp[k][0]=1;
           }

           for(int i=1;i<=n;i++){
               for(int j=1;j<=m;j++){
                   if(ss[i-1]==tt[j-1]){
                       dp[i][j]=dp[i-1][j-1]+dp[i-1][j];
                   }else{
                       dp[i][j]=dp[i-1][j];
                   }
               }
           }
           return dp[n][m];
    }
}

压缩一下

class Solution {
    public int numDistinct(String s, String t) {
           char[]ss=s.toCharArray();
           char[]tt=t.toCharArray();
           int m=ss.length;
           int n=tt.length;
           int[]dp=new int[n+1];
           
         dp[0]=1;

         
            for(int i=1;i<=m;i++){
                for(int j=n;j>=1;j--){
                if(ss[i-1]==tt[j-1]){
                    dp[j]=dp[j-1]+dp[j];
                }       
             }
            }
           return dp[n];
    }
}

28. 实现 strStr()

28. 实现 strStr()

class Solution {
    public int strStr(String haystack, String needle) {
               int left=0;
               int right=0;

            while(left<haystack.length()&&right<needle.length()){
                if(haystack.charAt(left)==needle.charAt(right)){
                    left++;
                    right++;
                }else{
                    left=left-right+1;
                    right=0;
                }
            }
            return right==needle.length()?left-needle.length():-1;
    }
}

KMP的代码,目前还无法理解,记录下,加油

public class Code01_KMP {

	public static int getIndexOf(String s, String m) {
		if (s == null || m == null || m.length() < 1 || s.length() < m.length()) {
			return -1;
		}
		char[] str1 = s.toCharArray();
		char[] str2 = m.toCharArray();
		int i1 = 0;
		int i2 = 0;
		int[] next = getNextArray(str2);
		while (i1 < str1.length && i2 < str2.length) {
			if (str1[i1] == str2[i2]) {
				i1++;
				i2++;
			} else if (next[i2] == -1) {
				i1++;
			} else {
				i2 = next[i2];
			}
		}
		return i2 == str2.length ? i1 - i2 : -1;
	}

	public static int[] getNextArray(char[] ms) {
		if (ms.length == 1) {
			return new int[] { -1 };
		}
		int[] next = new int[ms.length];
		next[0] = -1;
		next[1] = 0;
		int i = 2;
		int cn = 0;
		while (i < next.length) {
			if (ms[i - 1] == ms[cn]) {
				next[i++] = ++cn;
			} else if (cn > 0) {
				cn = next[cn];
			} else {
				next[i++] = 0;
			}
		}
		return next;
	}

	public static void main(String[] args) {
		String str = "abcabcababaccc";
		String match = "ababa";
		System.out.println(getIndexOf(str, match));

	}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值