1、字符处理:
1)字符过滤:只保留大小字母和数字:
StringBuffer sgood = new StringBuffer();
int length = s.length();
for (int i = 0; i < length; i++) {
char ch = s.charAt(i);
if (Character.isLetterOrDigit(ch)) {
sgood.append(Character.toLowerCase(ch));
}
}
2)大小写转换:
Character.toLowerCase(char ch)
2、字母统计:
1)所有字符都要统计
int[] count = new int[128];
for(int i=0; i < A.length(); i++)
count[A.charAt(i)]++;
2)只统计小写字母或大写字母
int[] count = new int[26];
for(int i=0; i < A.length(); i++)
count[A.charAt(i)-'a']++;
3、回文字符串:正读反读都一样的字符串
1)判断是否是回文字符串
常见的做法是使用双指针。定义左右指针,初始时分别指向字符串的第一个字符和最后一个字符,每次判断左右指针指向的字符是否相同,如果不相同,则不是回文串;如果相同,则将左右指针都往中间移动一位,直到左右指针相遇,则字符串是回文串。
class Solution {
public boolean validPalindrome(String s) {
int low = 0, high = s.length() - 1;
while (low < high) {
char c1 = s.charAt(low), c2 = s.charAt(high);
if (c1 != c2)
return false;
}
return true;
}
}
在允许最多删除一个字符的情况下,同样可以使用双指针,通过贪心算法实现。初始化两个指针 low 和 high 分别指向字符串的第一个字符和最后一个字符。每次判断两个指针指向的字符是否相同,如果相同,则更新指针,令 low = low + 1 和 high = high - 1,然后判断更新后的指针范围内的子串是否是回文字符串。如果两个指针指向的字符不同,则两个字符中必须有一个被删除,此时我们就分成两种情况:即删除左指针对应的字符,留下子串 s[low + 1], s[low + 1], ..., s[high],或者删除右指针对应的字符,留下子串 s[low], s[low + 1], ..., s[high - 1]。当这两个子串中至少有一个是回文串时,就说明原始字符串删除一个字符之后就以成为回文串。
class Solution {
public boolean validPalindrome(String s) {
int low = 0, high = s.length() - 1;
while (low < high) {
char c1 = s.charAt(low), c2 = s.charAt(high);
if (c1 == c2) {
low++;
high--;
} else {
boolean flag1 = true, flag2 = true;
for (int i = low, j = high - 1; i < j; i++, j--) {
char c3 = s.charAt(i), c4 = s.charAt(j);
if (c3 != c4) {
flag1 = false;
break;
}
}
for (int i = low + 1, j = high; i < j; i++, j--) {
char c3 = s.charAt(i), c4 = s.charAt(j);
if (c3 != c4) {
flag2 = false;
break;
}
}
return flag1 || flag2;
}
}
return true;
}
}
2)判断最长回文字串的长度
有两个点要注意:
1.回文串中每个字母都会使用偶数次(统计出所有字母的出现次数后,采用/2*2的方法,将出现奇数次的-1,出现偶数次的保持不变)
for(int v:alphabet){
max += v/2*2;
}
2.中文线使用竖线|(回文串长度是偶数)还是字母(回文串长度是奇数),如果某个字母出现了奇数次且当前的回文串长度是偶数,则回文串长度+1,代码如下
for(int v:alphabet){
max += v/2*2;
if((v%2==1&&max%2==0))
max += 1;
}
4、上升下降字符串:
给定第一个字符串,第一遍从小到大遍历末尾,第二遍从大到小遍历并移动到末尾,如果每次遍历时最小或者最大字符不止一个 ,可以选择其中任意一个。
输入:s = "aaaabbbbcccc"
输出:"abccbaabccba"
解释:第一轮的步骤 1,2,3 后,结果字符串为 result = "abc"
第一轮的步骤 4,5,6 后,结果字符串为 result = "abccba"
第一轮结束,现在 s = "aabbcc" ,我们再次回到步骤 1
第二轮的步骤 1,2,3 后,结果字符串为 result = "abccbaabc"
第二轮的步骤 4,5,6 后,结果字符串为 result = "abccbaabccba"
class Solution {
public String sortString(String s) {
//相当于26个桶
int[] ch = new int[26];
//把s中的字符分别放到对应的桶里
for(int i=0; i<s.length();i++){
ch[s.charAt(i)-'a'] ++;
}
//存储计算的结果
StringBuffer res = new StringBuffer();
while(res.length()<s.length()){
//先从左往右找,遍历26个桶,如果当前桶不为空,
//就从当前桶里拿出一个元素出来
for(int i =0;i<26;i++){
if(ch[i]>0){
res.append((char) (i + 'a'));
ch[i]--;//拿出之后桶中元素的个数要减1
}
}
//从右往左拿,同上
for(int i=25;i>-1;i--){
if(ch[i]>0){
res.append((char) (i + 'a'));
ch[i]--;
}
}
}
//把结果转化为字符串
return res.toString();
}
}