中心拓展法
解决问题:回文字符
原理:循环各字符,拿到一个字符s.charAT(i),分别先向左或者右边扩展,寻找与中心点(也就是该字符)相等的字符,寻找结束。之后同时拓展左右两边,寻找左右两点相等的字符,直至不相等,则以中心字符的寻找结束,进入下一次以s.charAT(i+1)为中心来拓展寻找回文字符。
public String longestPalindrome(String s) {
if(s==null || s.length()==0)return "";
int length=s.length();
int i=0, j=0, left=0, right=0, len=1;//len存回文字符的长度,初始值为1
int max=0; //记录最长的回文长度
int start=0; // 记录回文起始位置
for( ; i<length; i++) {
left=i-1; //先left right指针分别移动一个位置
right=i+1;
while(left>=0 && s.charAt(i)==s.charAt(left)) {
left--;len++; //若像左边扩散成功,继续扩散并且len长度增加
}
while(right<length && s.charAt(i)==s.charAt(right)) {
right++;len++; //继续向右边扩散
}
while(left>=0 && right<length && s.charAt(left)==s.charAt(right)) {
left--;right++;
len+=2; //向两边同时扩散寻找回文字符
}
if(len>max) {
max=len;
start=left;
}
len=1; //每次结束一次中心字符的选取就要对len重新赋值
}
return s.substring(start+1, start+max+1); //substring截取子串,取头不取尾,所以结束的索引要加1
//start加1,因为while循环退出时,left多减了1
}
Z字形变换
原理:如图所示
class Solution { //while循环太多了,超出时间限制,自己写的测试用例都没问题
public String convert(String s, int numRows) {
if(numRows==1)return s;
char[][] a=new char[1000][1000];
int length=s.length();
int row=0, col=0, i=0;
int end=0;
while(i<length) {
if(row==0) {
while(row<numRows && i<length) {
a[row][col]=s.charAt(i);
i++;row++;
}
}
if(row==numRows) {
row=numRows-1;
while(row>1 && i<length) {
a[row-1][col+1]=s.charAt(i);
row--;col++;
i++;
}
row--;col++;
}
if(i==length)end=col;
}
StringBuilder q = new StringBuilder(); //因为新创建用来存储变换后的字符,会发生很多次修改,所以使用StringBuilder对q对象尾部添加字符
for(int i1=0; i1<numRows; i1++)
for(int j=0; j<=end; j++) {
if(a[i1][j] >= 'A' && a[i1][j] <='Z') q.append(a[i1][j]);
}
return q.toString();//返回string类对象
}
}
翻转数字
原理:转换为字符串然后翻转,用try catch处理溢出
String xString=Integer.toString(x);
String string=xString;
int flag=1;
if(x<0) {
flag=-1;
string=xString.substring(1);//若为负数去掉符号
}
try {
return Integer.valueOf(new StringBuilder(string).reverse().toString())*flag;
//reverse返回的是stringbuilder对象,要用tostring返回字符串
} catch (Exception e) {
return 0;
}
下面的是我的题解,虽然ac了,但是时间复杂度不低,而且溢出的判断有些玄学,并不满足所有溢出判断,应该是只能ac这道题。
class Solution {
public int reverse(int x) {
int len=0;
int y=x;
int ans=0;
while(Math.abs(y)>0) {
len++;
y=y/10;
}
y=x;
int[] num=new int[len];
int[] renum=new int[len];
for(int i=0; i<len; i++) {
num[i]=y%10;
y=y/10;
}
for(int i=0, j=len-1; i<len && j>=0; i++, j--) {
ans+=Math.pow(10, j)*num[i];
}
if(ans==Integer.MIN_VALUE || ans==Integer.MAX_VALUE)return 0;
else return ans;
}
}
存数组然后再按位存放,有些笨的方法,可以不使用数组。如下:
public int reverse(int x) {
long n = 0;
while(x != 0) {
n = n*10 + x%10;
x = x/10;
} //不需要数组
return (int)n==n? (int)n:0;
}