字符串部分刷题记录
以下仅为个人刷题记录
一、字符
question 520(检测大写字母)
answer:
两种情况 1:都是大写 2:从第二个开始都是小写
lass Solution {
public boolean detectCapitalUse(String word) {
//分两种情况
//1:所有字符都是大写
//2:从第二个字符开始都是小写
return word.equals(word.toUpperCase())||word.substring(1).equals(word.substring(1).toLowerCase());
}
}
二、回文串的定义
question 125(验证回文串)
answer
双指针遍历比较
class Solution {
public boolean isPalindrome(String s) {
int n = s.length();
int left = 0, right = n - 1;
//将字符串转化为字符数组
char[] curr = s.toCharArray();
while (left < right) {
//从左开始查找字符
while (left < right && !Character.isLetterOrDigit(curr[left])) {
++left;
}
//从右查找字符
while (left < right && !Character.isLetterOrDigit(curr[right])) {
--right;
}
//比较是否相等
if (left < right) {
if (Character.toLowerCase(curr[left]) != Character.toLowerCase(curr[right])) {
return false;
}
++left;
--right;
}
}
return true;
}
}
利用StringBuffer
class Solution {
public boolean isPalindrome(String s) {
StringBuffer buff=new StringBuffer();
int len=s.length();
for(int i=0;i<len;i++){
char tag=s.charAt(i);
if(Character.isLetterOrDigit(tag)){
buff.append(Character.toLowerCase(tag));
}
}
StringBuffer buff_reverse =new StringBuffer(buff).reverse();
return (buff.toString()).equals(buff_reverse.toString());
}
}
三、公共前缀
question 434(字符串中的单词数)
answer:
class Solution {
public int countSegments(String s) {
int len=s.length();
//统计每个单词第一个下标
//需要满足两个条件 1:当前下标不为空,2前一个下标为空,或者下标为0
int count=0;
for(int i=0;i<len;i++){
if((i==0||s.charAt(i-1)==' ')&&s.charAt(i)!=' '){
count++;
}
}
return count;
}
}
question 58 (最后一个单词的长度)
answer:从后往前遍历,过滤最后面的空格
class Solution {
public int lengthOfLastWord(String s) {
if(s==null||s.length()==0){
return 0;
}
int len=s.length();
int count=0;
for(int i=len-1;i>=0;i--){
if(s.charAt(i)!=' '){
count++;
//如果当前字符为空 并且count有值 返回count
}else if(count!=0){
return count;
}
}
return count;
}
}
四、字符串的反转
question 344(反转字符串 )
answer:
class Solution {
public void reverseString(char[] s) {
int len=s.length;
int left=0,right=len-1;
while(left<right){
char temp=s[left];
s[left]=s[right];
s[right]=temp;
left++;
right--;
}
}
}
question 541(反转字符串)
answer:
可以翻译为,每2k个字符反转k个,最后不够k,全部反转
class Solution {
public String reverseStr(String s, int k) {
if(k==1){return s;}
int len=s.length();
char[] sa=s.toCharArray();
for(int i=0;i<len;i+=2*k){
reverse(sa,i,Math.min(i+k-1,len-1));
}
return new String(sa);
}
public void reverse(char[] arr,int i,int j){
while(i<j){
char temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
i++;
j--;
}
}
}
question 557(反转字符串中的单词)
answer
class Solution {
public String reverseWords(String s) {
String[] strs = s.split(" ");
int len=strs.length;
StringBuffer buff=new StringBuffer();
for(int i=0;i<len;i++){
buff.append(new StringBuffer(strs[i]).reverse());
buff.append(" ");
}
return buff.toString().trim();
}
}
question 151(颠倒字符串中的单词)
answer 双指针
class Solution {
public String reverseWords(String s) {
int left = 0, right = s.length() - 1;
// 去掉字符串开头的空白字符
while (left <= right && s.charAt(left) == ' ') {
++left;
}
// 去掉字符串末尾的空白字符
while (left <= right && s.charAt(right) == ' ') {
--right;
}
Deque<String> d = new ArrayDeque<String>();
StringBuilder word = new StringBuilder();
while (left <= right) {
char c = s.charAt(left);
if ((word.length() != 0) && (c == ' ')) {
// 将单词 push 到队列的头部
d.offerFirst(word.toString());
word.setLength(0);
} else if (c != ' ') {
word.append(c);
}
++left;
}
d.offerFirst(word.toString());
return String.join(" ", d);
}
}
answer2
class Solution {
public String reverseWords(String s) {
s=s.trim();
String[] str=s.split(" +");
//将数组转化成List集合
List<String> wordList=Arrays.asList(str);
//对集合反转
Collections.reverse(wordList);
用空格连接集合中的两个数
return String.join(" ",wordList);
}
}
五、字符的统计
question 387(字符串中第一个唯一字符)
answer
class Solution {
public int firstUniqChar(String s) {
int len=s.length();
if(len==1){return 0;}
Map<Character,Integer> map = new HashMap<>();
for(int i=0;i<len;i++){
map.put(s.charAt(i),map.getOrDefault(s.charAt(i),0)+1);
}
for(int i=0;i<len;i++){
if(map.getOrDefault(s.charAt(i),0)==1){
return i;
}
}
return -1;
}
}
question 389(找不同)
answer:计数
首先遍历字符串 s,对其中的每个字符都将计数值加 1;然后遍历字符串 t,对其中的每个字符都将计数值减 1。当发现某个字符计数值为负数时,返回字符
class Solution {
public char findTheDifference(String s, String t) {
int[] cnt = new int[26];
for (int i = 0; i < s.length(); ++i) {
char ch = s.charAt(i);
cnt[ch - 'a']++;
}
for (int i = 0; i < t.length(); ++i) {
char ch = t.charAt(i);
cnt[ch - 'a']--;
if (cnt[ch - 'a'] < 0) {
return ch;
}
}
return ' ';
}
}
answer2 求和
将字符串 s,t 中每个字符的 ASCII 码的值求和,求字符差值
class Solution {
public char findTheDifference(String s, String t) {
int acount=0,tcount=0;
for(int i=0;i<s.length();i++){
acount+=s.charAt(i);
}
for(int i=0;i<t.length();i++){
tcount+=t.charAt(i);
}
return (char)(tcount-acount);
}
}
question 383()
answer 计数
class Solution {
public boolean canConstruct(String ransomNote, String magazine) {
if (ransomNote.length() > magazine.length()) {
return false;
}
int[] cnt = new int[26];
for (char c : magazine.toCharArray()) {
cnt[c - 'a']++;
}
for (char c : ransomNote.toCharArray()) {
cnt[c - 'a']--;
if(cnt[c - 'a'] < 0) {
return false;
}
}
return true;
}
}
question 242(有效的字母异位词)
answer
class Solution {
public boolean isAnagram(String s, String t) {
if(s.length()!=t.length()){
return false;
}
char[] srr=s.toCharArray();
char[] trr=t.toCharArray();
int[] count=new int[26];
for(int i=0;i<s.length();i++){
count[srr[i]-'a']++;
}
for(int i=0;i<t.length();i++){
count[trr[i]-'a']--;
if(count[trr[i]-'a']<0){
return false;
}
}
return true;
}
}
question 49(字母异位词分析)
answer:
class Solution {
public List<List<String>> groupAnagrams(String[] strs) {
//将单词排序,排序的单词作为一个键
Map<String,List<String>> map = new HashMap<>();
//遍历数组里的每一个数
for(String str:strs){
//接收遍历到的数组元素
//比如"eat"
char[] cur=str.toCharArray();
//对eat排序 aet
Arrays.sort(cur);
String key=new String(cur);
List<String> list = map.getOrDefault(key,new ArrayList<String>());
list.add(str);
map.put(key,list);
}
//泛型 里面的内容可能不会自动转化。
return new ArrayList<>(map.values());
}
}
question 451(根据字符出现的频率排序)
answer:
class Solution {
public String frequencySort(String s) {
if(s.length()<=1){
return s;
}
Map<Character,Integer> map=new HashMap<>();
char[] array=s.toCharArray();
for(char str:array){
map.put(str,map.getOrDefault(str,0)+1);
}
StringBuilder sb=new StringBuilder();
//每次找数量最大的一个;
while(map.size()>0){
int max=0;
char key=' ';
for(Map.Entry<Character,Integer> entry: map.entrySet()){
if(entry.getValue()>max){
max=entry.getValue();
key=entry.getKey();
}
}
map.remove(key);
for(int i=0;i<max;i++){
sb.append(key);
}
}
return sb.toString();
}
}
question 423(从英文中重建数字)
answer:
class Solution {
public String originalDigits(String s) {
//zero one two three four five six seven eight nine
Map<Character,Integer> map=new HashMap<>();
char[] array=s.toCharArray();
for(char str: array){
map.put(str,map.getOrDefault(str,0)+1);
}
int[] cur=new int[10];
cur[0]=map.getOrDefault('z',0);
cur[2]=map.getOrDefault('w',0);
cur[4]=map.getOrDefault('u',0);
cur[6]=map.getOrDefault('x',0);
cur[8]=map.getOrDefault('g',0);
//h:3,8 f:4,5 s:6,7
cur[3]=map.getOrDefault('h',0)-map.getOrDefault('g',0);
cur[5]=map.getOrDefault('f',0)-map.getOrDefault('u',0);
cur[7]=map.getOrDefault('s',0)-map.getOrDefault('x',0);
//o:0,1,2,4 ; i:5,6,8,9
cur[1]=map.getOrDefault('o',0)-cur[0]-cur[2]-cur[4];
cur[9]=map.getOrDefault('i',0)-cur[5]-cur[6]-cur[8];
StringBuilder sb=new StringBuilder();
for(int i=0;i<10;i++){
if(cur[i]==0){
continue;
}//出现的可能不止一个
for(int j=0;j<cur[i];j++){
sb.append(i);
}
}
return sb.toString();
}
}
question 657(机器人能否返回原点)
answer:
class Solution {
public boolean judgeCircle(String moves) {
//统计RL UD次数 判断是否相等
if(moves.length()==0){return true;}
if(moves.length()%2!=0){return false;}
int x=0,y=0;
char[] array=moves.toCharArray();
for(char str: array){
if(str=='U'){y--;}
else if(str=='D'){y++;}
else if(str=='L'){x--;}
else if(str=='R'){x++;}
}
if(x==0&&y==0){
return true;
}
return false;
}
}
question 551(学生出勤记录1)
answer
class Solution {
public boolean checkRecord(String s) {
if(s.length()<2){return true;}
int len=s.length();
char[] array=s.toCharArray();
int a=0,l=0;
for(int i=0;i<len;i++){
if(array[i]=='A'){
a++;
if(a>=2){
return false;
}
}else if(array[i]=='L'){
//如果当前迟到,判断是否连续三天都迟到
if(i+2<len){
if(array[i+1]=='L'&&array[i+2]=='L'){
return false;
}
}
}
}
return true;
}
}
answer2
class Solution {
public boolean checkRecord(String s) {
int absents = 0, lates = 0;
int n = s.length();
for (int i = 0; i < n; i++) {
char c = s.charAt(i);
if (c == 'A') {
absents++;
if (absents >= 2) {
return false;
}
}
if (c == 'L') {
lates++;
if (lates >= 3) {
return false;
}
} else {
lates = 0;
}
}
return true;
}
}
question 696(计数二进制字串)
answer:
class Solution {
public int countBinarySubstrings(String s) {
List<Integer> list=new ArrayList<>();
char[] array=s.toCharArray();
int pre=0,last=s.length();
while(pre<last){
char cur=array[pre];
int count=0;
while(pre<last&&cur==array[pre]){
pre++;
count++;
}
list.add(count);
}
int res=0;
for(int i=0;i<list.size()-1;i++){
res+=Math.min(list.get(i),list.get(i+1));
}
return res;
}
}
question 467
question 535
六、数字与字符串间转换
question 299(猜数字)
answer
对于奶牛,需要满足数字猜对但是位置不对。我们可以统计secret,guess各个字符的出现次数,记在两个长度为 10 的数组中,数组下标和字符相等,
由于多余的数字无法匹配,对于 0 到 9 的每位数字,应取其在 secret 和 guess 中的出现次数的最小值。将每位数字出现次数的最小值累加,即为奶牛的个数。
class Solution {
public String getHint(String secret, String guess) {
int[] scount=new int[10];
int[] gcount=new int[10];
int bull=0,cow=0;
for(int i=0;i<secret.length();i++){
//位置数字都相等
if(secret.charAt(i)==guess.charAt(i)){
bull++;
}else{
//当不相等时,统计secret guess字符串中字符出现的次数
scount[secret.charAt(i)-'0']++;
gcount[guess.charAt(i)-'0']++;
}
}
//字符与下标对应,取非公牛出现数量最少的字符=>奶牛的个数
for(int i=0;i<10;i++){
cow+=Math.min(scount[i],gcount[i]);
}
return bull+"A"+cow+"B";
}
}
question 412(FIZZ BUZZ)
answer:
class Solution {
public List<String> fizzBuzz(int n) {
List<String> res=new ArrayList<>();
for(int i=1;i<=n;i++){
if(i%3==0&&i%5==0){
res.add("FizzBuzz");
}else if(i%3==0){
res.add("Fizz");
}else if(i%5==0){
res.add("Buzz");
}else{
res.add(String.valueOf(i));
}
}
return res;
}
}
question 506 (相对名词)
class Solution {
public String[] findRelativeRanks(int[] score) {
int len=score.length;
int[] temp=new int[len];
//将分数复制一份
for(int i=0;i<len;i++){
temp[i]=score[i];
}
//将分数排序,顺序排序
Arrays.sort(temp);
//《得分,名次》
Map<Integer,Integer> map=new HashMap<>();
for(int i=0;i<len;i++){
map.put(temp[i],len-i);
}
//res 名词数组
String[] res=new String[len];
for(int i=0;i<len;i++){
int level=map.get(score[i]);
if(level==1){
res[i]="Gold Medal";
}else if(level==2){
res[i]="Silver Medal";
}else if(level==3){
res[i]="Bronze Medal";
}else {
res[i]=String.valueOf(level);
}
}
return res;
}
}
question 539(最小时间差)
answer
class Solution {
public int findMinDifference(List<String> timePoints) {
//对时间点进行排序
//排序后的时间 最小值差值出现在相邻时间或者首位时间中
Collections.sort(timePoints);
int ans = Integer.MAX_VALUE;
int t0Minutes = getMinutes(timePoints.get(0));
int preMinutes = t0Minutes;
for (int i = 1; i < timePoints.size(); ++i) {
int minutes = getMinutes(timePoints.get(i));
ans = Math.min(ans, minutes - preMinutes); // 相邻时间的时间差
preMinutes = minutes;
}
//24:60=1440秒
ans = Math.min(ans, t0Minutes + 1440 - preMinutes); // 首尾时间的时间差
return ans;
}
public int getMinutes(String t) {
return ((t.charAt(0) - '0') * 10 + (t.charAt(1) - '0')) * 60 + (t.charAt(3) - '0') * 10 + (t.charAt(4) - '0');
}
}
question 640(求解方程)
answer:
首先使用 = 将方程左右两边拆分开,然后使用方法 breakIt 分别遍历方程的左右两边,解析出其中的数字和 x,并将结果以数组的形式返回。
对任意一个给定的方程,将其转换为所有的 x 都在 = 左侧,所有的数字都在 = 右侧,例如
x+5-3+x=6+x-2
x+x-x=6-2-5+3
把在原始方程左边的 x 看做正值,右边的 x 看做负值。同理,原始方程左边每个数字都被看做负数,右边每个数字都看作正数。那么 lhs 包含了方程中所有的 x,rhs 包含了方程中所有的数字。
public class Solution {
public String solveEquation(String equation) {
//将等式从=处分割
String[] lr = equation.split("=");
int lhs = 0, rhs = 0;
for (String x: breakIt(lr[0])) {
if (x.indexOf("x") >= 0) {
lhs += Integer.parseInt(coeff(x));
} else
rhs -= Integer.parseInt(x);
}
for (String x: breakIt(lr[1])) {
if (x.indexOf("x") >= 0)
lhs -= Integer.parseInt(coeff(x));
else
rhs += Integer.parseInt(x);
}
if (lhs == 0) {
if (rhs == 0)
return "Infinite solutions";
else
return "No solution";
}
return "x=" + rhs / lhs;
}
//处理等式一边,放到一个集合list中
public List < String > breakIt(String s) {
List < String > res = new ArrayList < > ();
String r = "";
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) == '+' || s.charAt(i) == '-') {
if (r.length() > 0)
res.add(r);
r = "" + s.charAt(i);
} else
r += s.charAt(i);
}
res.add(r);
return res;
}
//处理 x
public String coeff(String x) {
//例如 5x的情况 返回5
if (x.length() > 1 && x.charAt(x.length() - 2) >= '0' && x.charAt(x.length() - 2) <= '9')
return x.replace("x", "");
//如果只有x返回1 -x返回-1
return x.replace("x", "1");
}
}
question 38(外观数列)
answer
每次遍历前一个String 用stringBuilder存中间结果
class Solution {
public String countAndSay(int n) {
String str = "1";
for(int i=2;i<=n;i++){
StringBuilder sb=new StringBuilder();
//哨兵开始位置
int start=0;
//指针走动位置,去遍历前一个string
int pos=0;
while(pos<str.length()){
while(pos<str.length()&&str.charAt(pos)==str.charAt(start)){
pos++;
}
sb.append(Integer.toString(pos-start)).append(str.charAt(start));
start=pos;
}
str=sb.toString();
}
return str;
}
}
question 443(压缩字符串)
class Solution {
public int compress(char[] chars) {
int n = chars.length;
//left 是遍历不同字符的起点,write记录有多少个字符
int write = 0, left = 0;
for (int i = 0; i < n; i++) {
if (i == n - 1 || chars[i] != chars[i + 1]) {
chars[write++] = chars[i];
int count = i - left + 1;
if (count > 1) {
//如果count>9要分割
String str = String.valueOf(count);
for (int j = 0; j < str.length(); j++){
chars[write++] = str.charAt(j);
}
}
left = i + 1;
}
}
return write;
}
}
question 8(字符串转整数)
answer
class Solution {
public int myAtoi(String s) {
//去掉前面空格
s=s.trim();
//把s转化为数组
char[] str=s.toCharArray();
int len=str.length;
if(len==0){
return 0;
}
int flag=1;
int index=0;
//+-号只能存在第一位
if(str[0]=='+'){
flag=1;
index++;
}else if(str[0]=='-'){
flag=-1;
index++;
}
int res=0;
while(index<len&&(str[index]>='0'&&str[index]<='9')){
//res*10+(str[index]-'0')>max
int temp=str[index]-'0';
if(flag==1){
if(res>(Integer.MAX_VALUE-temp)/10){
return Integer.MAX_VALUE;
}
}else if(flag==-1){
//-res*10-(str[index]-'0')<min
if(-res<(Integer.MIN_VALUE+temp)/10){
return Integer.MIN_VALUE;
}
}
res =res*10+temp;
index++;
}
return res*flag;
}
}
question 13(罗马数字转整数)
answer
class Solution {
public int romanToInt(String s) {
char[] str=s.toCharArray();
int index=0,len=str.length;
int res=0;
while(index<len){
int temp=0;
switch(str[index]){
case 'I' : temp=1; break;
case 'V' : temp=5; break;
case 'X' : temp=10; break;
case 'L' : temp=50; break;
case 'C' : temp=100; break;
case 'D' : temp=500; break;
case 'M' : temp=1000; break;
}
if(index+1<len&&(temp==1||temp==10||temp==100)){
if(temp==1&&str[index+1]=='V'){
res+=4;
index+=2;
continue;
}else if(temp==1&&str[index+1]=='X'){
res+=9;
index+=2;
continue;
}else if(temp==10&&str[index+1]=='L'){
res+=40;
index+=2;
continue;
}else if(temp==10&&str[index+1]=='C'){
res+=90;
index+=2;
continue;
}else if(temp==100&&str[index+1]=='D'){
res+=400;
index+=2;
continue;
}else if(temp==100&&str[index+1]=='M'){
res+=900;
index+=2;
continue;
}
}
res+=temp;
index++;
}
return res;
}
}
管解更好
class Solution {
Map<Character, Integer> symbolValues = new HashMap<Character, Integer>() {{
put('I', 1);
put('V', 5);
put('X', 10);
put('L', 50);
put('C', 100);
put('D', 500);
put('M', 1000);
}};
public int romanToInt(String s) {
int ans = 0;
int n = s.length();
for (int i = 0; i < n; ++i) {
int value = symbolValues.get(s.charAt(i));
if (i < n - 1 && value < symbolValues.get(s.charAt(i + 1))) {
ans -= value;
} else {
ans += value;
}
}
return ans;
}
}
question 12(整数转罗马数字)
answer
class Solution {
public String intToRoman(int num) {
int[] arr={1000,900,500,400,100,90,50,40,10,9,5,4,1};
String[] str={"M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I"};
StringBuilder sb=new StringBuilder();
for(int i=0;i<13;i++){
int temp=arr[i];
while(num>=temp){
sb.append(str[i]);
num-=temp;
}
if(num==0){
break;
}
}
return sb.toString();
}
}
七、子序列
question 392(判断子序列)
answer
class Solution {
public boolean isSubsequence(String s, String t) {
if((s==null&&t==null)||(s.length()==0&&t.length()==0)){
return true;
}
if(s==null||t==null||s.length()>t.length()){
return false;
}
int n = s.length(), m = t.length();
int i = 0, j = 0;
while (i < n && j < m) {
if (s.charAt(i) == t.charAt(j)) {
i++;
}
j++;
}
return i == n;
}
}
question 524(通过删除字母匹配到字典里最长单词)
answer
先对字符串排序,再判断是否为子串
class Solution {
public String findLongestWord(String s, List<String> dictionary) {
// 即返回值为正数时,交换数组中正在比较的
// 两个元素的位置,返回值为负数时,不交换。
//比较器
Collections.sort(dictionary,(String word1,String word2)->{
if(word1.length()!=word2.length()){
return word2.length()-word1.length();
}else{
return word1.compareTo(word2);
}
});
//遍历dictionary列表
for(String t:dictionary){
int i=0,j=0;
while(i<t.length()&&j<s.length()){
if(t.charAt(i)==s.charAt(j)){
i++;
}
j++;
}
if(i==t.length()){
return t;
}
}
return "";
}
}
question 522(最长特殊序列)
public class Solution {
//x是否为y的子串
public boolean isSubsequence(String x, String y) {
int j = 0;
int i = 0;
while( i < y.length() && j < x.length() )
{ if (x.charAt(j) == y.charAt(i))
{
j++;
}
i++;
}
return j == x.length();
}
public int findLUSlength(String[] strs) {
int res = -1;
//遍历每一个字符串
for (int i = 0, j; i < strs.length; i++) {
for (j = 0; j < strs.length; j++) {
if (j == i)
continue;
if (isSubsequence(strs[i], strs[j]))
break;
}
//如果str[i]不是其他字符的子序列
if (j == strs.length)
res = Math.max(res, strs[i].length());
}
return res;
}
}
八、高精度运算
question 66(加一)
answer
只有整数为9时,才需要进位
class Solution {
public int[] plusOne(int[] digits) {
int len=digits.length;
for(int i=len-1;i>=0;i--){
digits[i]=(digits[i]+1)%10;
if(digits[i]!=0){
return digits;
}
}
//首位还需进一,扩展数组长度
int res[]=new int[len+1];
res[0]=1;
for(int i=1;i<len+1;i++){
res[i]=digits[i-1];
}
return res;
}
}
question 67(二进制求和)
answer
class Solution {
public String addBinary(String a, String b) {
StringBuffer ans = new StringBuffer();
//carry存储进位数
int n = Math.max(a.length(), b.length()), carry = 0;
for (int i = 0; i < n; ++i) {
carry += i < a.length() ? (a.charAt(a.length() - 1 - i) - '0') : 0;
carry += i < b.length() ? (b.charAt(b.length() - 1 - i) - '0') : 0;
ans.append((char) (carry % 2 + '0'));
carry /= 2;
}
if (carry > 0) {
ans.append('1');
}
ans.reverse();
return ans.toString();
}
}
question 415(字符串相加)
answer
class Solution {
public String addStrings(String num1, String num2) {
//add存储进位
int i = num1.length() - 1, j = num2.length() - 1, add = 0;
StringBuffer ans = new StringBuffer();
while (i >= 0 || j >= 0 || add != 0) {
int x = i >= 0 ? num1.charAt(i) - '0' : 0;
int y = j >= 0 ? num2.charAt(j) - '0' : 0;
int result = x + y + add;
ans.append(result % 10);
add = result / 10;
i--;
j--;
}
// 计算完以后的答案需要翻转过来
ans.reverse();
return ans.toString();
}
}
question 43(字符串相乘)
answer
class Solution {
public String multiply(String num1, String num2) {
//num1,num2有一个为0,返回0
if(num1.equals("0")||num2.equals("0")){
return "0";
}
int len1=num1.length();
int len2=num2.length();
String res="0";
//num2中的每一项,分别×num1,再累加
for(int i=len2-1;i>=0;i--){
StringBuilder sb=new StringBuilder();
//补齐0
for(int j=len2-1;j>i;j--){
sb.append(0);
}
//sum存进位
int sum=0;
int temp=num2.charAt(i)-'0';
for(int d=len1-1;d>=0;d--){
int cur=num1.charAt(d)-'0';
sb.append((sum+cur*temp)%10);
sum=(sum+cur*temp)/10;
}
if(sum!=0){
sb.append(sum);
}
res=addString(res,sb.reverse().toString());
}
return res;
}
//两个字符串相加
public String addString(String s1,String s2){
int m=s1.length()-1;
int n=s2.length()-1;
int add=0;
StringBuilder ans=new StringBuilder();
while(m>=0||n>=0||add!=0){
int temp1= m>=0? s1.charAt(m)-'0' : 0;
int temp2= n>=0? s2.charAt(n)-'0' : 0;
ans.append((temp1+temp2+add)%10);
add=(temp1+temp2+add)/10;
m--;
n--;
}
ans.reverse();
return ans.toString();
}
}
question 306(累加数)
answer
class Solution {
public boolean isAdditiveNumber(String num) {
//当它的第一个数字和第二个数字以及总长度确定后,这整个累加序列也就确定了。
//根据这个性质,我们可以穷举累加序列的第一个数字和第二个数字的所有可能性
int n=num.length();
//第二个数的起始位置,从下标1开始枚举
for(int secondStart=1;secondStart<n-1;secondStart++){
//除数字 0 之外,不能以 0 开头
if(num.charAt(0)=='0'&&secondStart!=1){
break;
}
//第二个数的结束位置,从第二个数的开始位置枚举
for(int secondEnd=secondStart;secondEnd<n-1;secondEnd++){
// 当某个数字长度大于等于 2 时,这个数字不能以 0 开头,
if(num.charAt(secondStart)=='0'&&secondStart!=secondEnd){
break;
}
//判断是否为有效的累加数列
if(valid(secondStart,secondEnd,num)){
return true;
}
}
}
return false;
}
public boolean valid(int secondStart,int secondEnd,String num){
int n=num.length();
//第一个数起止位置
int firstStart=0,firstEnd=secondStart-1;
while(secondEnd<=n-1){
//第三个数的值
String third=stringAdd(num,firstStart,firstEnd,secondStart,secondEnd);
//第三个数起止位置
int thirdStart=secondEnd+1;
int thirdEnd=secondEnd+third.length();
//判断第三个数的值是否与截取下标位置的数相等
if(thirdEnd>=n||!num.substring(thirdStart,thirdEnd+1).equals(third)){
break;
}
if(thirdEnd==n-1){
return true;
}
firstStart=secondStart;
firstEnd=secondEnd;
secondStart=thirdStart;
secondEnd=thirdEnd;
}
return false;
}
//两个字符串的和
public String stringAdd(String s,int firstStart,int firstEnd,int secondStart,int secondEnd){
StringBuffer third=new StringBuffer();
int carry=0,cur=0;
while(firstStart<=firstEnd||secondStart<=secondEnd||carry!=0){
cur=carry;
if(firstStart<=firstEnd){
cur+=s.charAt(firstEnd)-'0';
firstEnd--;
}
if(secondStart<=secondEnd){
cur+=s.charAt(secondEnd)-'0';
secondEnd--;
}
carry=cur/10;
cur=cur%10;
third.append(cur);
}
third.reverse();
return third.toString();
}
}
九、字符串变换
question 482(密钥格式化)
answer
因为第一组长度可以比K短,其余组长度需要等于K,所以从后往前遍历读取
class Solution {
public String licenseKeyFormatting(String s, int k) {
char[] arr=s.toCharArray();
StringBuffer res=new StringBuffer();
int len=arr.length;
int temp=0;
for(int i=len-1;i>=0;i--){
if(arr[i]!='-'){
res.append(Character.toUpperCase(arr[i]));
temp++;
//每K个数插入 -
if(temp%k==0){
res.append("-");
}
}
}
//如果最前面为 ‘-’ ,则删除
if(res.length()>0&&res.charAt(res.length()-1)=='-'){
res.deleteCharAt(res.length()-1);
}
res.reverse();
return res.toString();
}
}
question 6(z字变换)
answer
把字符串一列一列的填充,,2*numRows-2为一组填充的数字(1234 32//123 2 )
class Solution {
public String convert(String s, int numRows) {
int len=s.length();
if(len==1||len<=numRows||numRows==1){return s;}
int r=numRows;
//创建一个buffer数组,保存对应每一行的字符
StringBuffer[] cur=new StringBuffer[r];
for(int i=0;i<r;i++){
cur[i]=new StringBuffer();
}
int tag=2*r-2;
//buffer cur[]的下标
int j=0;
for(int i=0;i<len;i++){
cur[j].append(s.charAt(i));
if((i%tag)<r-1){
j++;
}else{
j--;
}
}
StringBuffer res=new StringBuffer();
for(StringBuffer sb:cur){
res.append(sb);
}
return res.toString();
}
}
question 68*
十、字符串匹配
question 28(实现IndexOf())
answer
class Solution {
public int strStr(String haystack, String needle) {
if(needle==null){return 0;}
int i=0,j=0;
int temp=0;
while(i<haystack.length()&&j<needle.length()){
if(haystack.charAt(i)==needle.charAt(j)){
i++;
j++;
temp++;
}else{
j=0;
i=i-temp+1;
temp=0;
}
}
if(j==needle.length()){
return i-j;
}
return -1;
}
}
KMP更好啦,,,
question 686(重复叠加字符串匹配)
answer
class Solution {
public int repeatedStringMatch(String a, String b) {
StringBuffer arr=new StringBuffer();
int res=0;
//字符长度的最大值,因为一个完整的B可能首部用到A的一部分,尾部用到A的一部分故总长<=2*A+B
int max=2*a.length()+b.length();
while(arr.length()<max){
arr.append(a);
res++;
if(arr.toString().indexOf(b)!=-1){
return res;
}
}
return -1;
}
}
question 459(重复的子字符串)
answer
class Solution {
public boolean repeatedSubstringPattern(String s) {
int n = s.length();
if(n<=1) return false;
Set<String> set = new HashSet<>();
//i枚举子字符串的长度
for(int i=1;i<n;i++){
//len=8 子字符串长度,可能划分2 2 2 2/4 4///3,5,6,7不可能
if(n%i!=0) continue;
set.clear();
for(int j=0;j<=n-i;j+=i){
//把每个子字符串添加到set中
set.add(s.substring(j,j+i));
}
if(set.size()==1) return true;
}
return false;
}
}
question 214*
十一、中心拓展法
question 5(最长回文串)
answer
动态规划
class Solution {
//转移方程
//p(i,i)=true
//p(i,i+1)=(Si==S(i+1))
//p(i,j)=p(i+1,j-1)^(Si==Sj)
public String longestPalindrome(String s) {
int len=s.length();
if(len<2){return s;}
//dp[i][j] 表示(si,sj)之间是否是回文串
boolean[][] dp=new boolean[len][len];
//初始长度为1的子串都是回文串
for(int i=0;i<len;i++){
dp[i][i]=true;
}
int maxLen=1;
int begin=0;
char[] array=s.toCharArray();
//递推开始,枚举子串长度,l:长度
for(int l=2;l<=len;l++){
//i代表左边界
for(int i=0;i<len;i++){
//由ll和i可以确定右边界j,即j-i+1=l
int j=l-1+i;
if(j>=len){
break;
}
//i左边界,j有边界,判断两个字符是否相等
if(array[i]!=array[j]){
dp[i][j]=false;
}else{
//如果长度为2直接设置为true,否则 看dp[i+1][j-1]
if(j-i<3){
dp[i][j]=true;
}else{
dp[i][j]=dp[i+1][j-1];
}
}
//如果dp[i][j]==true,即为回文串,记录回文串长度和起始位置
if(dp[i][j]==true&&l>maxLen){
maxLen=l;
begin=i;
}
}
}
return s.substring(begin,begin+maxLen);
}
}
answer2 中心扩展
class Solution {
public String longestPalindrome(String s) {
if (s == null || s.length() < 1) {
return "";
}
int start = 0, end = 0;
for (int i = 0; i < s.length(); i++) {
//长度奇数偶数
int len1 = expandAroundCenter(s, i, i);
int len2 = expandAroundCenter(s, i, i + 1);
int len = Math.max(len1, len2);
if (len > end - start) {
start = i - (len-1) / 2;
end = i + len / 2;
}
}
return s.substring(start, end + 1);
}
public int expandAroundCenter(String s, int left, int right) {
while (left >= 0 && right < s.length() && s.charAt(left) == s.charAt(right)) {
--left;
++right;
}
return right - left - 1;
}
}
question 647(回文子串)
answer 动态规划
class Solution {
public int countSubstrings(String s) {
int len=s.length();
if(len<2){return len;}
int sum=0;
boolean[][] dp=new boolean[len][len];
//初始化长度为1的子串
for(int i=0;i<len;i++){
dp[i][i]=true;
sum++;
}
//从2开始枚举子串长度
for(int l=2;l<=len;l++){
//枚举左边界
for(int i=0;i<len;i++){
//右边界j j-i+1=len
int j=l-1+i;
if(j>=len){
break;
}
if(s.charAt(i)!=s.charAt(j)){
dp[i][j]=false;
}else{
if(l<3){
dp[i][j]=true;
}else{
dp[i][j]=dp[i+1][j-1];
}
}
if(dp[i][j]==true){
sum++;
}
}
}
return sum;
}
}
answer2 中心扩展
枚举出所有的子串,然后再判断这些子串是否是回文;
枚举每一个可能的回文中心,然后用两个指针分别向左右两边拓展,当两个指针指向的元素相同的时候就拓展,否则停止拓展
class Solution {
public:
int countSubstrings(string s) {
int n = s.size(), ans = 0;
for (int i = 0; i < 2 * n - 1; ++i) {
// 中心有(i,i),(i,i+1)两种
int l = i / 2, r = i / 2 + i % 2;
while (l >= 0 && r < n && s[l] == s[r]) {
--l;
++r;
++ans;
}
}
return ans;
}
};