有关字符串的经典算法题
下面整理10道高频字符串算法例题,覆盖双指针、滑动窗口、哈希统计、KMP、字符串模拟、反转、子串、回文、异位词等经典题型,每题含题意、解题思路 + Java完整代码,面试高频原题。
例题1:反转字符串(双指针)
题目
原地反转字符数组,不能额外开辟数组空间。
public void reverseString(char[] s) {
int left = 0, right = s.length - 1;
while (left < right) {
char tmp = s[left];
s[left] = s[right];
s[right] = tmp;
left++;
right–;
}
}
例题2:验证回文串(过滤非字母数字)
题目
只保留字母和数字,忽略大小写,判断是否回文。
public boolean isPalindrome(String s) {
char[] arr = s.toCharArray();
int l = 0, r = arr.length - 1;
while (l < r) {
while (l < r && !Character.isLetterOrDigit(arr[l])) l++;
while (l < r && !Character.isLetterOrDigit(arr[r])) r–;
if (Character.toLowerCase(arr[l]) != Character.toLowerCase(arr[r])) {
return false;
}
l++;
r–;
}
return true;
}
例题3:无重复字符的最长子串(滑动窗口)
题目
找出字符串中不含重复字符的最长子串长度。
public int lengthOfLongestSubstring(String s) {
int[] win = new int[128];
int left = 0, maxLen = 0;
char[] arr = s.toCharArray();
for (int right = 0; right < arr.length; right++) {
char c = arr[right];
win[c]++;
while (win[c] > 1) {
win[arr[left++]]–;
}
maxLen = Math.max(maxLen, right - left + 1);
}
return maxLen;
}
例题4:有效的字母异位词(哈希计数)
题目
s、t两个字符串,判断是否字母组成完全相同,仅排列顺序不同。
public boolean isAnagram(String s, String t) {
if (s.length() != t.length()) return false;
int[] cnt = new int[26];
for (char c : s.toCharArray()) cnt[c - ‘a’]++;
for (char c : t.toCharArray()) cnt[c - ‘a’]–;
for (int num : cnt) {
if (num != 0) return false;
}
return true;
}
例题5:字符串中的单词反转(整体翻转+局部翻转)
题目
输入 “hello world”,输出 “world hello”,去掉首尾多余空格、单词间只保留单个空格。
public String reverseWords(String s) {
// 去掉首尾空格+按空格分割
String[] arr = s.trim().split(“\s+”);
StringBuilder sb = new StringBuilder();
for (int i = arr.length - 1; i >= 0; i–) {
sb.append(arr[i]);
if (i != 0) sb.append(" ");
}
return sb.toString();
}
例题6:实现strStr() / 查找第一个匹配子串(朴素匹配)
题目
在haystack中找出needle第一次出现的下标,不存在返回-1。
public int strStr(String haystack, String needle) {
int n = haystack.length(), m = needle.length();
if (m == 0) return 0;
for (int i = 0; i <= n - m; i++) {
boolean match = true;
for (int j = 0; j < m; j++) {
if (haystack.charAt(i + j) != needle.charAt(j)) {
match = false;
break;
}
}
if (match) return i;
}
return -1;
}
例题7:字符串的排列(定长滑动窗口)
题目
判断s2中是否包含s1任意一种排列构成的连续子串。
public boolean checkInclusion(String s1, String s2) {
int len1 = s1.length(), len2 = s2.length();
if (len1 > len2) return false;
int[] cnt1 = new int[26];
int[] cnt2 = new int[26];
for (int i = 0; i < len1; i++) {
cnt1[s1.charAt(i)-‘a’]++;
cnt2[s2.charAt(i)-‘a’]++;
}
if (arrEqual(cnt1, cnt2)) return true;
for (int i = len1; i < len2; i++) {
cnt2[s2.charAt(i-len1)-‘a’]–;
cnt2[s2.charAt(i)-‘a’]++;
if (arrEqual(cnt1, cnt2)) return true;
}
return false;
}
private boolean arrEqual(int[] a, int[] b) {
for (int i = 0; i < 26; i++)
if (a[i] != b[i]) return false;
return true;
}
例题8:最长公共前缀(横向遍历)
题目
字符串数组,求所有字符串最长公共开头前缀,无公共前缀返回空串。
public String longestCommonPrefix(String[] strs) {
if (strs == null || strs.length == 0) return “”;
String pre = strs[0];
for (int i = 1; i < strs.length; i++) {
while (strs[i].indexOf(pre) != 0) {
pre = pre.substring(0, pre.length()-1);
if (pre.isEmpty()) return “”;
}
}
return pre;
}
例题9:整数反转(字符串边界处理)
题目
给出int整数,反转数字;超出int范围返回0。
public int reverse(int x) {
long res = 0;
while (x != 0) {
int mod = x % 10;
res = res * 10 + mod;
x /= 10;
}
if (res > Integer.MAX_VALUE || res < Integer.MIN_VALUE) return 0;
return (int) res;
}
例题10:最长回文子串(中心扩散法)
题目
找出字符串中最长回文连续子串。
public String longestPalindrome(String s) {
if (s.length() < 2) return s;
int maxStart = 0, maxLen = 1;
for (int i = 0; i < s.length(); i++) {
int len1 = expand(s, i, i); // 奇数长度
int len2 = expand(s, i, i+1); // 偶数长度
int curMax = Math.max(len1, len2);
if (curMax > maxLen) {
maxLen = curMax;
maxStart = i - (curMax - 1) / 2;
}
}
return s.substring(maxStart, maxStart + maxLen);
}
private int expand(String s, int l, int r) {
while (l >= 0 && r < s.length() && s.charAt(l) == s.charAt®) {
l–;
r++;
}
return r - l - 1;
}
题型分类汇总
-
双指针:例题1、例题2
-
滑动窗口:例题3、例题7
-
字符频次哈希统计:例题4
-
字符串分割拼接:例题5、例题8
-
子串匹配:例题6
-
数字字符串转换:例题9
-
回文子串:例题10
更多推荐




所有评论(0)