字符串冲刺题
一、最长公共前缀
LeetCode14 编写一个函数来查找字符串数组中的最长公共前缀。如果不存在公共前缀,返回空字符串""
示例1:
输入:strs=["flower","fLow","flight"]
输出:"fL"
示例2:
输入:strs=["dog","racecar'","car"]
输出:""
解释:输入不存在公共前缀。
根据题目内容,可以很明显看出两种思路,一种是纵向比较,一种是横向比较。
先看第一种的实现方法,竖着比较。纵向扫描时,从前往后遍历所有字符串的每一列,比较相同列上的字符是否相同,如果相同则继续对下一列进行比较,如果不相同则当前列不再属于公共前缀,当前列之前的部分为最长公共前缀。
public String longestCommonPrefix(String[] strs){
if (strs == null || strs.length == 0){
return "";
}
int length = strs[0].length();
int count = strs.length;
for(int i = 0; i < length; i++){
char c = strs[0].charAt(i);
for (int j = 1; j < count; j++){
if (i == strs[j].length() || strs[j].charAt(i) != c){
return strs[0].substring(0,i);
}
}
}
return strs[0]
}
第二种是横着依次比较,依次遍历字符串数组中的每个字符串,对于每个遍历到的字符串,更新最长公共前缀(其实就是看是否要缩短,一定不会变长),当遍历完所有的字符串以后,即可得到字符串数组中的最长公共前缀。如果在尚未遍历完所有的字符串时,最长公共前缀已经是空串,则最长公共前缀一定是空串,因此不需要继续遍历剩下的字符串,直接返回空串即可。
public String longestCommonPrefix(String[] strs){
if (strs ==null || strs.length == 0){
return "";
}
String prefix = strs[0];
int count = strs.length;
for (int i = 1; i < count; i++){
prefix = longestCommonPrefix(prefix,strs[i]);
if(prefix.length() == 0) break;
}
return prefix;
}
public String longestCommonPrefix(String str1,String str2){
int length = Math.min(str1.length(),str2.length());
int index = 0;
while (index < length && str1.charAt(index) == str2.charAt(index)){
index++;
return str1.substring(0,index);
}
}
二、字符串压缩问题
LeetCode443给你一个字符数组chars,请使用下述算法压缩:
从一个空字符串s开始。对于chars中的每组连续重复字符:
1.如果这一组长度为1,则将字符追加到s中。
2.否则,需要向S追加字符,后跟这一组的长度。压缩后得到的字符串S不应该直接返回,需要转储到字符数组chars中。需要注意的是,如果组长度为10或10以上,则在chars数组中会被拆分为多个字符。
请在修改完输入数组后,返回该数组的新长度。你必须设计并实现一个只使用常量额外空间的算法来解决此问题。
示例1:
输入:chars=["a","a","b","b","c","c","c"]
输出:返回6,输入数组的前6个字符应该是:["a","2","b","2","c","3"]
解释:
"aa"被"a2"替代。"bb"被"b2"替代。"ccc"被"c3"替代。
示例2:
输入:chars=["a"]
输出:返回1,输入数组的前1个字符应该是:["a"]
解释:
没有任何字符串被替代。
示例3:
输入:chars=["a","b","b","b","b","b","b","b","b","b","b","b","b"]
输出:返回4,输入数组的前4个字符应该是:["a","b","1","2"]。
解释:
由于字符"a"不重复,所以不会被压缩。"bbbbbbbbbbbb"被“b12”替代。
注意每个数字在数组中都有它自己的位置。
这个题貌似采用双指针策略来处理就行,但是再分析发现三个指针才够。两个进行正常点扫描,还有一个用来确定修改的位置
这里还有一个问题,就是长度可能超过0,因此还要实现将数字转化为字符串写入到原字符串的功能。这里我们采用短除法将子串长度倒序写入原字符串中,然后再将其反转即可。
class Solution {
public int compress(char[] chars) {
int left = 0,right = 0, change = 0;
int len = chars.length;
//if(len == 1)return 1;
while(right < len){
while(right < len && chars[left] == chars[right]) right++;
//该字符的数量
int sum = right - left;
//存入该字符
chars[change] = chars[left];
change++;
int prechange = change;
//将字符数量逐位存入
if(sum != 1){
int sum1 = sum;
while(sum1 > 0){
chars[change] = (char) (sum1 % 10 + '0');
sum1 /= 10;
change++;
}
//反转sum,前面存的时候是从低位存到高位,与题目要求相反
if(sum >= 10){
int nowchange = change - 1;
while(prechange < nowchange){
char temp = chars[prechange];
chars[prechange] = chars[nowchange];
chars[nowchange] = temp;
prechange++;
nowchange--;
}
}
}
left = right;
}
return change;
}
}