字符串相关算法题
1.有效的字母异位词
力扣242:https://leetcode-cn.com/problems/valid-anagram/description/
给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。
示例 1:
- 输入: s = "anagram", t = "nagaram"
- 输出: true
示例 2:
- 输入: s = "rat", t = "car"
- 输出: false
题解:可以用 HashMap 来映射字符与出现次数,然后比较两个字符串出现的字符数量是否相同。
由于本题的字符串只包含 26 个小写字符,因此可以使用长度为 26 的整型数组对字符串出现的字符进行统计,不再使用 HashMap。
代码实现:
public boolean isAnagram(String s, String t) {
int[] cnts = new int[26];
for (char c : s.toCharArray()) {
cnts[c - 'a']++;
}
for (char c : t.toCharArray()) {
cnts[c - 'a']--;
}
for (int cnt : cnts) {
if (cnt != 0) {
return false;
}
}
return true;
}
2.最长回文串
力扣409:https://leetcode-cn.com/problems/longest-palindrome/description/
给定一个包含大写字母和小写字母的字符串,找到通过这些字母构造成的最长的回文串。
在构造过程中,请注意区分大小写。比如 "Aa" 不能当做一个回文字符串。
注意:假设字符串的长度不会超过 1010。
示例 1:
- 输入:"abccccdd"
- 输出:7
解释:我们可以构造的最长的回文串是"dccaccd", 它的长度是 7。
题解:使用长度为 256 的整型数组来统计每个字符出现的个数,每个字符有偶数个可以用来构成回文字符串。
因为回文字符串最中间的那个字符可以单独出现,所以如果有单独的字符就把它放到最中间。
代码实现:
public int longestPalindrome(String s) {
int[] cnts = new int[256];
for (char c : s.toCharArray()) {
cnts[c]++;
}
int palindrome = 0;
for (int cnt : cnts) {
palindrome += (cnt / 2) * 2;
}
if (palindrome < s.length()) {
palindrome++; // 这个条件下 s 中一定有单个未使用的字符存在,可以把这个字符放到回文的最中间
}
return palindrome;
}
3.同构字符串
力扣205:https://leetcode-cn.com/problems/isomorphic-strings/description/
给定两个字符串 s 和 t,判断它们是否是同构的。
如果 s 中的字符可以被替换得到 t ,那么这两个字符串是同构的。
所有出现的字符都必须用另一个字符替换,同时保留字符的顺序。两个字符不能映射到同一个字符上,但字符可以映射自己本身。
示例 1:
- 输入: s = "egg", t = "add"
- 输出: true
示例 2:
- 输入: s = "foo", t = "bar"
- 输出: false
示例 3:
- 输入: s = "paper", t = "title"
- 输出: true
说明:你可以假设 s 和 t 具有相同的长度。
题解:记录一个字符上次出现的位置,如果两个字符串中的字符上次出现的位置一样,那么就属于同构。
代码实现:
public boolean isIsomorphic(String s, String t) {
int[] preIndexOfS = new int[256];
int[] preIndexOfT = new int[256];
for (int i = 0; i < s.length(); i++) {
char sc = s.charAt(i), tc = t.charAt(i);
if (preIndexOfS[sc] != preIndexOfT[tc]) {
return false;
}
preIndexOfS[sc] = i + 1;
preIndexOfT[tc] = i + 1;
}
return true;
}
4.回文子串
力扣647:https://leetcode-cn.com/problems/palindromic-substrings/
给定一个字符串,你的任务是计算这个字符串中有多少个回文子串。
具有不同开始位置或结束位置的子串,即使是由相同的字符组成,也会被视作不同的子串。
示例 1:
- 输入:"abc"
- 输出:3
解释:三个回文子串: "a", "b", "c"
示例 2:
- 输入:"aaa"
- 输出:6
解释:6个回文子串: "a", "a", "a", "aa", "aa", "aaa"
代码实现:
//https://leetcode-cn.com/problems/palindromic-substrings/solution/liang-dao-hui-wen-zi-chuan-de-jie-fa-xiang-jie-zho/
class Solution {
public int countSubstrings(String s) {
if(s==null) return 0;
int count = 0;
int len = s.length();
boolean[][] dp = new boolean[len][len];
for(int j=0;j<len;j++){
for(int i=0;i<=j;i++){
if(s.charAt(i)==s.charAt(j) && (j-i<2 || dp[i+1][j-1])){
dp[i][j] = true;
count++;
}
}
}
return count;
}
}
//解二
private int cnt = 0;
public int countSubstrings(String s) {
for (int i = 0; i < s.length(); i++) {
extendSubstrings(s, i, i); // 奇数长度
extendSubstrings(s, i, i + 1); // 偶数长度
}
return cnt;
}
private void extendSubstrings(String s, int start, int end) {
while (start >= 0 && end < s.length() && s.charAt(start) == s.charAt(end)) {
start--;
end++;
cnt++;
}
}
5.回文数
力扣9:https://leetcode-cn.com/problems/palindrome-number/description/
判断一个整数是否是回文数。回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。
示例 1:
- 输入: 121
- 输出: true
示例 2:
- 输入: -121
- 输出: false
解释: 从左向右读, 为 -121 。 从右向左读, 为 121- 。因此它不是一个回文数。
示例 3:
- 输入: 10
- 输出: false
解释: 从右向左读, 为 01 。因此它不是一个回文数。
代码实现:
class Solution {
public boolean isPalindrome(int x) {
String str = String.valueOf(x);
StringBuffer sb = new StringBuffer(str);
String s = sb.reverse().toString();
if(str.contains(s))
return true;
else
return false;
}
}
//将整数分成左右两部分,右边那部分需要转置,然后判断这两部分是否相等。
public boolean isPalindrome(int x) {
if (x == 0) {
return true;
}
if (x < 0 || x % 10 == 0) {
return false;
}
int right = 0;
while (x > right) {
right = right * 10 + x % 10;
x /= 10;
}
return x == right || x == right / 10;
}
6.计算二进制字串
力扣696:https://leetcode-cn.com/problems/count-binary-substrings/description/
给定一个字符串 s,计算具有相同数量0和1的非空(连续)子字符串的数量,并且这些子字符串中的所有0和所有1都是组合在一起的。
重复出现的子串要计算它们出现的次数。
示例 1 :
- 输入: "00110011"
- 输出: 6
解释: 有6个子串具有相同数量的连续1和0:“0011”,“01”,“1100”,“10”,“0011” 和 “01”。
请注意,一些重复出现的子串要计算它们出现的次数。
另外,“00110011”不是有效的子串,因为所有的0(和1)没有组合在一起。
示例 2 :
- 输入: "10101"
- 输出: 4
解释: 有4个子串:“10”,“01”,“10”,“01”,它们具有相同数量的连续1和0。
代码实现:
class Solution {
public int countBinarySubstrings(String s) {
if(s==null || s.length()<2) return 0;
int count = 1;
int len = s.length();
List<Integer> list = new ArrayList();
for(int i=0;i<len-1;i++){
if(s.charAt(i)==s.charAt(i+1)){
count++;
}else{
list.add(count);
count = 1;
}
}
list.add(count);
len = list.size()-1;
count = 0;
for(int i=0;i<len;i++){
count += Math.min(list.get(i),list.get(i+1));
}
return count;
}
}
7.最短回文串
力扣214:https://leetcode-cn.com/problems/shortest-palindrome/
给定一个字符串 s,你可以通过在字符串前面添加字符将其转换为回文串。找到并返回可以用这种方式转换的最短回文串。
示例 1:
- 输入: "aacecaaa"
- 输出: "aaacecaaa"
示例 2:
- 输入: "abcd"
- 输出: "dcbabcd"
代码实现:
class Solution {
public String shortestPalindrome(String s) {
String r = new StringBuilder(s).reverse().toString();
int len = s.length();
int i=0;
for(i=0;i<len;i++){
if (s.substring(0, len - i).equals(r.substring(i))) {
break;
}
}
return new StringBuilder(s.substring(len-i)).reverse()+s;
}
}