算法通关村第十二关—字符串冲刺题(黄金)

发布时间:2023年12月17日

???????????字符串冲刺题

一、最长公共前缀

?LeetCode14 编写一个函数来查找字符串数组中的最长公共前缀。如果不存在公共前缀,返回空字符串""

示例1:
输入:strs=["flower","fLow","flight"]
输出:"fL"
示例2:
输入:strs=["dog","racecar'","car"]
输出:""
解释:输入不存在公共前缀。

image.png
?根据题目内容,可以很明显看出两种思路,一种是纵向比较,一种是横向比较。
?先看第一种的实现方法,竖着比较。纵向扫描时,从前往后遍历所有字符串的每一列,比较相同列上的字符是否相同,如果相同则继续对下一列进行比较,如果不相同则当前列不再属于公共前缀,当前列之前的部分为最长公共前缀。

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;
    }
}
文章来源:https://blog.csdn.net/m0_73709096/article/details/135046969
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。