最长公共前缀
- 两两比较
class Solution {
public String longestCommonPrefix(String[] strs) {
String ret = strs[0];
for(int i = 1; i < strs.length; i++) {
ret = findCommon(strs[i], ret);
}
return ret;
}
String findCommon(String s1, String s2) {
int i = 0;
while(i < Math.min(s1.length(), s2.length()) && s1.charAt(i) == s2.charAt(i))
i++;
return s1.substring(0, i);
}
}
- 统一比较
class Solution {
public String longestCommonPrefix(String[] strs) {
for(int i = 0; i < strs[0].length(); i++) {
char tmp = strs[0].charAt(i);
for(int j = 1; j < strs.length; j++) {
if(i == strs[j].length() || strs[j].charAt(i) != tmp)
return strs[0].substring(0, i);
}
}
return strs[0];
}
}
最长回文子串
- 中心扩散
如果⼀个子串是回⽂串,并且长度⼤于 2,那么将它首尾的两个字母去除之后,它仍然是个回文串。⼀直去除首尾到长度小于等于 2 。长度为 1 的,⾃⾝与⾃⾝就构成回⽂;而⻓度为 2 的,就要判断这两个字符是否相等了。
从这个性质可以反推,从回文串的中心开始,往左读和往右读也是⼀样的。那么可以枚举回文串的中心。
从中心向两边扩展,如果两边的字母相同,我们就可以继续扩展;如果不同,我们就停止扩展。这样只需要⼀层 for 循环,我们就可以完成先前两层 for 循环的工作量。
class Solution {
public String longestPalindrome(String s) {
int begin = 0, len = 0, n = s.length();
for(int i = 0; i < n; i++) { //固定中心点
//扩展奇数长度的子串
int left = i, right = i;
while(left >= 0 && right < n && s.charAt(left) == s.charAt(right)) {
left--;
right++;
}
if(right - left - 1 > len) {
begin = left + 1;
len = right - left - 1;
}
//扩展偶数长度
left = i; right = i + 1;
while(left >= 0 && right < n && s.charAt(left) == s.charAt(right)) {
left--;
right++;
}
if(right - left - 1 > len) {
begin = left + 1;
len = right - left - 1;
}
}
return s.substring(begin, begin + len);
}
}
- 动态规划
以后会出动态规划相关文章,到时候附上链接
二进制求和
算法思路(模拟十进制的大数相加的过程):
模拟十进制列竖式计算两个数之和的过程。但是这里是⼆进制的求和,我们不是逢十进一,⽽是逢⼆进⼀。
class Solution {
public String addBinary(String a, String b) {
StringBuffer ret = new StringBuffer();
int cur1 = a.length() - 1, cur2 = b.length() - 1, t = 0;
while(cur1 >= 0 || cur2 >= 0 || t != 0) {
if(cur1 >= 0) t += a.charAt(cur1--) - '0';
if(cur2 >= 0) t += b.charAt(cur2--) - '0';
ret.append(t % 2);
t /= 2;
}
return ret.reverse().toString();
}
}
字符串相乘
算法思路(无进位相乘然后相加,最后处理进位):
整体思路就是模拟列竖式计算两个数相乘的过程。但是为了书写代码的方便性,我们选择优化的版本,就是在计算两数相乘的时候,先不考虑进位,等到所有结果计算完毕之后,再去考虑进位。如下图:

class Solution {
public String multiply(String num1, String num2) {
//1.准备工作
int m = num1.length(), n = num2.length();
char[] n1 = new StringBuffer(num1).reverse().toString().toCharArray();
char[] n2 = new StringBuffer(num2).reverse().toString().toCharArray();
int[] tmp = new int[m + n - 1];
//2.无进位相乘,然后相加
for(int i = 0; i < m; i++)
for(int j = 0; j < n; j++)
tmp[i+j] += (n1[i] - '0') * (n2[j] - '0');
//3.处理进位
int cur = 0, t = 0;
StringBuffer ret = new StringBuffer();
while(cur < m + n - 1 || t != 0) {
if(cur < m + n - 1) t += tmp[cur++];
ret.append(t % 10);
t /= 10;
}
//4.处理前导0
while(ret.length() > 1 && ret.charAt(ret.length() - 1) == '0')
ret.deleteCharAt(ret.length() - 1);
return ret.reverse().toString();
}
}
前导0的情况也就是一个乘数为0 的情况,可以改成如下代码:
class Solution {
public String multiply(String num1, String num2) {
if (num1.equals("0") || num2.equals("0")) {
return "0";
}
//1.准备工作
int m = num1.length(), n = num2.length();
char[] n1 = new StringBuffer(num1).reverse().toString().toCharArray();
char[] n2 = new StringBuffer(num2).reverse().toString().toCharArray();
int[] tmp = new int[m + n - 1];
//2.无进位相乘,然后相加
for(int i = 0; i < m; i++)
for(int j = 0; j < n; j++)
tmp[i+j] += (n1[i] - '0') * (n2[j] - '0');
//3.处理进位
int cur = 0, t = 0;
StringBuffer ret = new StringBuffer();
while(cur < m + n - 1 || t != 0) {
if(cur < m + n - 1) t += tmp[cur++];
ret.append(t % 10);
t /= 10;
}
return ret.reverse().toString();
}
}
非对称之美
- 如果全是相同的字母,比如aaaaaaaa,那就输出0
- 回文串减去1个字母就不是回文串了
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
char[] s = in.next().toCharArray();
int n = s.length;
boolean flag = false;
for(int i = 1; i < n; i++) {
if(s[i] != s[0]) {
flag = true;
break;
}
}
if(flag) {//不是相同字符
flag = false;
//判断本身是不是回文
int left = 0, right = n - 1;
while (left < right) {
if(s[left] == s[right]) {
left++;
right--;
} else {
flag = true;
break;
}
}
if(flag) System.out.println(n);
else System.out.println(n-1);
} else {//是相同字符
System.out.println(0);
}
}
}
字符串分类
import java.util.Arrays;
import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
Set<String> set = new HashSet<>();
while (n-- != 0) {
char[] s = in.next().toCharArray();
Arrays.sort(s);
set.add(String.valueOf(s));
}
System.out.println(set.size());
}
}
小红的ABC
因为只包含三种字符, 所以仅需判断长度为2 以及 长度为3 的子串是否是回文串即可,如果没有就返回-1
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
char[] s = in.next().toCharArray();
int ret = -1;
int n = s.length;
for(int i = 0; i < n; i++) {
if(i+1 < n && s[i] == s[i+1]) { // 判断长度为 2 的子串
ret = 2;
break;
}
if(i+2 < n && s[i] == s[i+2]) // 判断长度为 3 的子串
ret = 3;
}
System.out.println(ret);
}
}
旋转字符串
class Solution {
public boolean rotateString(String s, String goal) {
return s.length() == goal.length() && (s + s).contains(goal);
}
}
旋转字符串(二)
import java.util.*;
public class Solution {
public boolean solve (String A, String B) {
int n = A.length();
int m = B.length();
if(n != m) return false;
for(int i = 1; i < n; i++) {
String s1 = A.substring(0, i);
String s2 = A.substring(i, n);
if((s2 + s1).equals(B)) return true;
}
return false;
}
}
本文介绍了几种常见的字符串处理算法,包括最长公共前缀的两种实现方法、寻找最长回文子串的中心扩散策略、二进制求和和字符串相乘的计算逻辑,以及非对称字符串的识别和小红的ABC问题的解决方案。
476

被折叠的 条评论
为什么被折叠?



