优选算法的寻踪契合:字符串专题

专栏:算法的魔法世界

个人主页:手握风云

目录

一、例题讲解

[1.1. 最长公共前缀](#1.1. 最长公共前缀)

[1.2. 最长回文子串](#1.2. 最长回文子串)

[1.3. 二进制求和](#1.3. 二进制求和)

[1.4. 字符串相乘](#1.4. 字符串相乘)


一、例题讲解

1.1. 最长公共前缀

给你一个字符串数组,找出最长公共前缀。

解法一:两两比较字符串,找出最长公共前缀。利用指针从头开始遍历字符串,如果遇到相同的字符,指针向后移动。当指针越界时,停止。

完整代码实现:

java 复制代码
class Solution {
    public String longestCommonPrefix(String[] strs) {
        int len = strs.length;
        if (strs == null || len == 0) {
            return "";
        }
        if (strs.length == 1) {
            return strs[0];
        }

        // 初始化公共前缀为第一个字符串
        String prefix = strs[0];

        // 遍历数组中的其他字符串,依次比较
        for (int i = 1; i < len; i++) {
            // 找出当前字符串与prefix的公共前缀
            prefix = commonPrefix(prefix, strs[i]);
            // 如果公共前缀为空,提前结束循环
            if (prefix.isEmpty()) {
                break;
            }
        }
        return prefix;
    }

    public String commonPrefix(String s1, String s2) {
        int minLen = Math.min(s1.length(), s2.length());
        int i = 0;
        while (i < minLen && s1.charAt(i) == s2.charAt(i)) {
            i++;
        }
        return s1.substring(0, i);
    }
}

解法二:统一比较。也是利用指针遍历每一个字符串,如果都相同就像后移动,如果不同或者发生越界,停止移动。

完整代码实现:

java 复制代码
class Solution {
    public String longestCommonPrefix(String[] strs) {
        int len = strs.length;
         if (strs == null || len == 0) {
            return "";
        }
        
        // 遍历第一个字符串的每个字符
        for (int i = 0; i < strs[0].length(); i++) {
            char c = strs[0].charAt(i);
            
            // 检查其他字符串的相同位置
            for (int j = 1; j < len; j++) {
                // 如果其他字符串已经到达末尾,或者字符不匹配,返回当前的前缀
                if (i >= strs[j].length() || strs[j].charAt(i) != c) {
                    return strs[0].substring(0, i);
                }
            }
        }
        
        // 如果第一个字符串是所有字符串的前缀,返回第一个字符串
        return strs[0];
    }
}

1.2. 最长回文子串

本题采用的是中心扩展。定义两个指针left和right,从回文串的中心分别向左右,当遇到不相同的字符或者两个指针越界时停止。要注意:如果子串长度为奇数,left=right;如果子串长度为偶数,right=left+1。

完整代码实现:

java 复制代码
class Solution {
    public String longestPalindrome(String s) {
        int n = s.length(), start = 0, end = 0;
        for (int i = 0; i < n; i++) {
            // 奇数长度回文串
            int len1 = expandCenter(s, i, i);
            // 偶数长度回文串
            int len2 = expandCenter(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);
    }

    private int expandCenter(String s, int left, int right) {
        // 从中心向两边扩展,直到不是回文串
        while (left >= 0 && right < s.length() && s.charAt(left) == s.charAt(right)) {
            left--;
            right++;
        }

        // 返回回文串长度
        return right - left - 1;
    }
}

1.3. 二进制求和

给定两个仅由字符'0'或'1'组成的二进制字符串a和b,以二进制字符串的形式返回两数之和。

本题就是一个模拟手算加法的过程。初始化一个进位carry为 0,结果字符串ret为空。从两个字符串的末尾开始向前遍历,计算当前位上的和,满2向前进1位。遍历结束后,如果还有进位,将进位添加到结果字符串的前面。

完整代码实现:

java 复制代码
class Solution {
    public String addBinary(String a, String b) {
        StringBuilder ret = new StringBuilder();
        int i = a.length() - 1, j = b.length() - 1, carry = 0;

        // 当至少还有一个字符串未遍历完时,继续循环
        while (i >= 0 || j >= 0) {
            int aBit = (i >= 0) ? a.charAt(i--) - '0' : 0;
            int bBit = (j >= 0) ? b.charAt(j--) - '0' : 0;

            // 计算当前位的和
            int sum = aBit + bBit + carry;

            // 将当前位的结果添加到结果中
            ret.append(sum % 2);

            // 更新进位
            carry = sum / 2;
        }

        // 处理最后的进位
        if (carry > 0) {
            ret.append(carry);
        }

        return ret.reverse().toString();
    }
}

1.4. 字符串相乘

给定两个以字符串形式表示的非负整数num1和num2,计算它们的乘积,并将结果以字符串形式返回,不能直接将输入的字符串转换为整数。

本题考查的是模拟列竖式相乘:利用其中一个字符串的最后一位开始向前遍历,与另一个字符串每一位进行相乘,满10向前进一位,最后相加得到结果。这里需要注意:高位相乘需要在后面补0,为了方便我们可以将字符串num1、num2,最后的返回结果也得逆序;还需要处理前导"0",比如"123"*"0"="0"(清除前面的"0")。

上面的代码写起来太长,我们可以进行一些优化。我们还是将其中一个字符串的最后一位开始向前遍历,与另一个字符串每一位进行相乘,乘出来的结果不进行进位,最后再相加进位。

因为乘出来的结果暂时不进位,所以不知道有多少数位,我们可以用一个数组来存储。

完整代码实现:

java 复制代码
class Solution {
    public String multiply(String num1, String num2) {
        if (num1.equals("0") || num2.equals("0")) {
            return "0";
        }

        int m = num1.length(), n = num2.length();
        int[] res = new int[m + n];

        // 从个位数开始逐位相加
        for (int i = m - 1; i >= 0; i--) {
            for (int j = n - 1; j >= 0; j--) {
                int mul = (num1.charAt(i) - '0') * (num2.charAt(j) - '0');
                int p1 = i + j; // 高位
                int p2 = i + j + 1; // 地位
                int sum = mul + res[p2];

                res[p2] = sum % 10; // 低位直接赋值
                res[p1] += sum / 10; // 高位加进位
            }
        }
        
        // 结果数组转为字符串
        StringBuffer buffer = new StringBuffer();
        for (int digit : res) {
            if (buffer.length() != 0 || digit !=0) {
                buffer.append(digit);
            }
        }

        return buffer.toString();
    }
}
相关推荐
闭着眼睛学算法2 小时前
【华为OD机考正在更新】2025年双机位A卷真题【完全原创题解 | 详细考点分类 | 不断更新题目 | 六种主流语言Py+Java+Cpp+C+Js+Go】
java·c语言·javascript·c++·python·算法·华为od
IT古董2 小时前
【第五章:计算机视觉-项目实战之目标检测实战】2.目标检测实战:中国交通标志检测-(2)中国交通标志检测数据格式转化与读取
算法·目标检测·计算机视觉
MobotStone3 小时前
LLM 采样入门到进阶:理解与实践 Top-K、Top-P、温度控制
算法
杨小码不BUG3 小时前
CSP-J/S初赛知识点精讲-图论
c++·算法·图论··编码·csp-j/s初赛
LeaderSheepH4 小时前
常见的排序算法
数据结构·算法·排序算法
周杰伦_Jay5 小时前
【图文详解】强化学习核心框架、数学基础、分类、应用场景
人工智能·科技·算法·机器学习·计算机视觉·分类·数据挖掘
violet-lz6 小时前
Linux静态库与共享库(动态库)全面详解:从创建到应用
算法
贝塔实验室6 小时前
ADMM 算法的基本概念
算法·数学建模·设计模式·矩阵·动态规划·软件构建·傅立叶分析
235166 小时前
【LeetCode】3. 无重复字符的最长子串
java·后端·算法·leetcode·职场和发展