龙空技术网

面试BAT 却被小小字符串秒杀?这13道题帮你一举击败字符串算法题

追逐仰望星空 336

前言:

此刻看官们对“cba算法”可能比较注重,你们都需要了解一些“cba算法”的相关知识。那么小编也在网摘上汇集了一些对于“cba算法””的相关文章,希望朋友们能喜欢,大家快快来了解一下吧!

推荐阅读:

秋招面试总结:Java+并发+Spring+MySQL+分布式+Redis+算法+JVM等
字节跳动秋招面经:后端开发工程师,已拿意向书
美团一面凉凉:MySQL+Java+Redis+算法+网络+Linux等一个都讲不清
前言

面试BAT却被一道小小字符串算法题秒杀,崩溃不?没事,这就来总结一下13道字符串必备算法题,分享出来给大家一起参考学习,一举击败字符串~

首先在这里先分享一下我的算法刷题资料:包含 (线性表、字符串、栈和队列、树、排序、查找、暴力枚举法、广度优先搜素、深度优先搜素、分治法、贪心法、动态规划、图)+详细答案解析,有需要的小伙伴可以私信 “学习” 免费领取我的算法刷题资料~

算法刷题:答案

算法刷题:答案

接下来一起来看看这13道字符串高频面试算法题,看看你全部掌握没有~(文末还有分享一些我的算法学习资料,可以关注一下哦~)

1. KMP 算法

谈到字符串问题,不得不提的就是 KMP 算法,它是用来解决字符串查找的问题,可以在一个字符串(S)中查找一个子串(W)出现的位置。KMP 算法把字符匹配的时间复杂度缩小到 O(m+n) ,而空间复杂度也只有O(m)。因为“暴力搜索”的方法会反复回溯主串,导致效率低下,而KMP算法可以利用已经部分匹配这个有效信息,保持主串上的指针不回溯,通过修改子串的指针,让模式串尽量地移动到有效的位置。

1.1 BM 算法

BM算法也是一种精确字符串匹配算法,它采用从右向左比较的方法,同时应用到了两种启发式规则,即坏字符规则 和好后缀规则 ,来决定向右跳跃的距离。基本思路就是从右往左进行字符匹配,遇到不匹配的字符后从坏字符表和好后缀表找一个最大的右移值,将模式串右移继续匹配。

2. 替换空格

请实现一个函数,将一个字符串中的每个空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。

public class Solution { public String replaceSpace(StringBuffer str) { StringBuffer res = new StringBuffer(); int len = str.length() - 1; for(int i = len; i >= 0; i--){ if(str.charAt(i) == ' ') res.append("02%"); else res.append(str.charAt(i)); } return res.reverse().toString(); }}
3. 最长公共前缀

编写一个函数来查找字符串数组中的最长公共前缀。如果不存在公共前缀,返回空字符串 ""。

首先对字符串数组进行排序,然后拿数组中的第一个和最后一个字符串进行比较,从第 0 位开始,如果相同,把它加入 res 中,不同则退出。最后返回 res

class Solution { public String longestCommonPrefix(String[] strs) { if(strs == null || strs.length == 0) return ""; Arrays.sort(strs); char [] first = strs[0].toCharArray(); char [] last = strs[strs.length - 1].toCharArray(); StringBuffer res = new StringBuffer(); int len = first.length < last.length ? first.length : last.length; int i = 0; while(i < len){ if(first[i] == last[i]){ res.append(first[i]); i++; } else break; } return res.toString(); }}
4. 最长回文串

给定一个包含大写字母和小写字母的字符串,找到通过这些字母构造成的最长的回文串。在构造过程中,请注意区分大小写。比如 "Aa" 不能当做一个回文字符串。

统计字母出现的次数即可,双数才能构成回文。因为允许中间一个数单独出现,比如“abcba”,所以如果最后有字母落单,总长度可以加 1。

class Solution { public int longestPalindrome(String s) { HashSet hs = new HashSet(); int len = s.length(); int count = 0; if(len == 0) return 0; for(int i = 0; i= 0 && r < s.length() && s.charAt(l) == s.charAt(r)){ l--; r++; } if(len < r - l - 1){ index = l + 1; len = r - l - 1; } }}

4.3 最长回文子序列

给定一个字符串s,找到其中最长的回文子序列。可以假设s的最大长度为1000。 最长回文子序列和上一题最长回文子串的区别是,子串是字符串中连续的一个序列,而子序列是字符串中保持相对位置的字符序列,例如,"bbbb"可以使字符串"bbbab"的子序列但不是子串。

动态规划: dp[i][j] = dp[i+1][j-1] + 2 if s.charAt(i) == s.charAt(j) otherwise, dp[i][j] = Math.max(dp[i+1][j], dp[i][j-1])

class Solution { public int longestPalindromeSubseq(String s) { int len = s.length(); int [][] dp = new int[len][len]; for(int i = len - 1; i>=0; i--){ dp[i][i] = 1; for(int j = i+1; j < len; j++){ if(s.charAt(i) == s.charAt(j)) dp[i][j] = dp[i+1][j-1] + 2; else dp[i][j] = Math.max(dp[i+1][j], dp[i][j-1]); } } return dp[0][len-1]; }}
5. 字符串的排列

给定两个字符串 s1 和 s2,写一个函数来判断 s2 是否包含 s1 的排列。 换句话说,第一个字符串的排列之一是第二个字符串的子串。

我们不用真的去算出s1的全排列,只要统计字符出现的次数即可。可以使用一个哈希表配上双指针来做。

class Solution { public boolean checkInclusion(String s1, String s2) { int l1 = s1.length(); int l2 = s2.length(); int [] count = new int [128]; if(l1 > l2) return false; for(int i = 0; i 0 && str[i-1] != 'e' && str[i-1] != 'E') return false; if(sign && str[i-1] != 'e' && str[i-1] != 'E') return false; sign = true; }else if(str[i] == 'e' || str[i] == 'E'){ if(i == len - 1) return false; if(hasE) return false; hasE = true; }else if(str[i] == '.'){ if(hasE || decimal) return false; decimal = true; }else if(str[i] < '0' || str[i] > '9') return false; } return true; }}
13. 字符流中第一个不重复的字符

请实现一个函数用来找出字符流中第一个只出现一次的字符。例如,当从字符流中只读出前两个字符”go”时,第一个只出现一次的字符是”g”。当从该字符流中读出前六个字符“google”时,第一个只出现一次的字符是”l”。

用一个哈希表来存储每个字符及其出现的次数,另外用一个字符串 s 来保存字符流中字符的顺序。

import java.util.HashMap;public class Solution { HashMap map = new HashMap(); StringBuffer s = new StringBuffer(); //Insert one char from stringstream public void Insert(char ch) { s.append(ch); if(map.containsKey(ch)){ map.put(ch, map.get(ch)+1); }else{ map.put(ch, 1); } } //return the first appearence once char in current stringstream public char FirstAppearingOnce() { for(int i = 0; i < s.length(); i++){ if(map.get(s.charAt(i)) == 1) return s.charAt(i); } return '#'; }}
最后:

还有更多算法学习资料分享给大家,关注一下免费获取方式:转发+转发+私信关键词 “学习”!!!

算法目录

算法内容

再分享一些我的架构学习笔记:

架构学习笔记

Redis+学习脑图

标签: #cba算法 #编写一个函数来查找字符串数组中的最长公共后缀