【专项刷题】— 字符串

1、最长公共前缀 - 力扣(LeetCode)

思路:

  1. 解法一:两两比较字符串
  2. 解法二:比较每一个字符串的同一位
  3. 图解:
  4. 代码:
    class Solution {
        public String longestCommonPrefix(String[] strs) {
            String ret = strs[0];
            for(int i = 1; i < strs.length; i++){
                //调用方法,两两比较
                ret = commonStr(strs[i],ret);
            }
            return ret;
        }
        public String commonStr(String str1, String str2){
            int i = 0;
            //进行比较
            while(i < Math.min(str1.length(),str2.length()) && str1.charAt(i) == str2.charAt(i)){
                i++;
            }
            return str1.substring(0,i);
        }
    }
    
    public String longestCommonPrefix(String[] strs) {
            int n = strs.length;
            for(int i = 0; i < strs[0].length(); i++){
                //以第一组的字符串为基准
                char tmp = strs[0].charAt(i);
                //判断每一组的字符串
                for(int j = 1; j < n; j++){
                    //如果后面的字符串长度刚好等于基准的 i ,或者不相等就返回
                    if(i == strs[j].length() || strs[j].charAt(i) != tmp){
                        //返回截取的基准
                        return strs[0].substring(0,i);
                    }
                }
            }
            //说明基准就是最长公共前缀
            return strs[0];
        }

2、​​​​​​最长回文子串 - 力扣(LeetCode) 

思路:

  1. 从中心开始向右向左遍历,其中需要考虑子串长度为奇数和偶数的情况
  2. 代码:
    public String longestPalindrome(String s) {
            int n = s.length();
            int begin = 0; 
            int len = 0;
            //固定所有的点
            for(int i = 0; i < n; i++){
                //奇数情况
                int left = i;
                int right = i;
                while(left >= 0 && right < n && s.charAt(left) == s.charAt(right)){
                    left--;
                    right++;
                }
                if(right - left - 1 > len){
                    len = right - left - 1;
                    begin = left + 1;
                }
                //偶数情况,i+1
                left = i;
                right = i+1;
                while(left >= 0 && right < n && s.charAt(left) == s.charAt(right)){
                    left--;
                    right++;
                }
                if(right - left - 1 > len){
                    len = right - left - 1;
                    //此时left和right的位置都是不合法的位置,需要各自回退
                    begin = left + 1;
                }
            }
            return s.substring(begin,begin + len);
        }

 3、二进制求和 - 力扣(LeetCode)

思路:

  1. 对两个字符串从后往前相加操作,模2,然后再除2更新t,最后将字符串反转就是结果了
  2. 代码:
    public String addBinary(String a, String b) {
            int len1 = a.length() - 1;
            int len2 = b.length() - 1;
            int t = 0;
            StringBuffer ret = new StringBuffer();
            while(len1 >= 0 || len2 >= 0 || t != 0){
                if(len1 >= 0){
                    //加完就向前一个
                    t += a.charAt(len1--) - '0';
                }
                if(len2 >= 0){
                    t += b.charAt(len2--) - '0';
                }
                //拼接最终结果
                ret.append((char)('0' + (char)(t % 2)));
                //更新t的值
                t /= 2;
            }
            return ret.reverse().toString();
        }

 4、字符串相乘 - 力扣(LeetCode)

思路:

  1. 首先将两个字符翻转,便于模拟乘法操作
  2. 然后再无进位相乘然后再相加,最后处理进位
  3. 其中相加的位置就是 i + j 位置,数组的长度就是 两个字符串的长度减去1(99 * 99,长度就是2+2-1 = 3)
  4. 代码:
    public String multiply(String num1, String num2) {
            int m = num1.length();
            int n = num2.length();
            int[] tmp = new int[m + n - 1];
            //1、翻转字符串
            char[] n1 = new StringBuffer(num1).reverse().toString().toCharArray(); 
            char[] n2 = new StringBuffer(num2).reverse().toString().toCharArray(); 
            //2、进行无进位相乘、相加操作
            for(int i = 0; i < m; i++){
                for(int j = 0; j < n; j++){
                    //每一位循环都相加
                    tmp[i + j] += (n1[i] - '0') * (n2[j] - '0');
                }
            }
            //3、处理进位
            int cur = 0;
            int t = 0;
            StringBuffer ret = new StringBuffer();
            while(cur < m + n - 1 || t != 0){
                if(cur < m + n - 1){
                    t += tmp[cur++];
                }
                ret.append((char)((char)(t % 10) + '0'));
                t /= 10;
            }
            //4、处理前导0
            while(ret.length() > 1 && ret.charAt(ret.length() - 1) == '0'){
                ret.deleteCharAt(ret.length()-1);
            }
            return ret.reverse().toString();
        }
<think>好的,我现在需要处理用户关于华为OD模式思路的查询。首先,用户提到了他们想了解华为OD机试的解思路,涉及技术面试和算法。我需要结合提供的引用内容来构建一个结构化的回答,确保符合系统级指令,比如使用正确的LaTeX格式和引用标识。 首先,我得整理用户提供的引用内容。引用[1]详细介绍了华为OD机试的相关信息,包括系统的优点、面试流程、薪资待遇等,还提到了在线OJ系统的使用方法。引用[2]则强调了高频手撕代码,使用多种编程语言解答,注重时间复杂度和通过率,以及解思路的详细分析。这些信息需要被整合到回答中,以支持各个要点。 接下来,用户需要的是解思路,特别是针对华为OD机试。我应该分步骤来回答,例如分阶段准备、算法重点、代码优化、模拟面试等。每个部分需要引用对应的引用内容来增强可信度。比如,在分阶段准备中,引用[1]提到的由浅入深练习和针对性练习可以作为阶段一和阶段二的依据。 然后,算法重点部分需要列举常考型,如动态规划、字符串处理等,并给出例子。这里可能需要使用LaTeX格式的数学表达式,比如动态规划的状态转移方程,如$dp[i][j] = \min(dp[i-1][j], dp[i][j-1]) + grid[i][j]$,并确保用$$...$$包裹独立公式。同时,要引用[2]中提到的高频目和多种语言解答。 代码优化部分需要强调时间复杂度和空间复杂度,这里可以举例说明如何优化,比如快速排序的平均复杂度是$O(n \log n)$,而最坏情况是$O(n^2)$。引用[1]中的在线OJ系统可以帮助测试不同数据规模下的表现,因此需要提及。 技术面试准备部分,引用[2]中的手撕真和八股文面试应该被引用,说明需要熟悉常见问,并解释代码思路。 最后,模拟实战和资源推荐部分,引用[1]的在线OJ系统和引用[2]的手撕真库是重要的资源,需要正确标注引用标识。 在生成相关问的时候,需要围绕用户的需求,可能涉及机试高频型、优化代码的方法、面试准备、在线OJ系统的使用以及转正要求等,确保问与回答内容相关,并引导用户进一步探索。 需要注意所有行内数学表达式使用$...$,独立公式使用$$...$$,并且正确的中文回答结构。同时,检查每个引用是否在适当的位置添加,如分阶段练习部分引用[1],算法重点引用[2]等。 现在,确保回答结构清晰,分点明确,引用正确,并且语言自然流畅。最后生成的相关问要覆盖用户可能关心的其他方面,如高频型、代码优化技巧、面试流程等。</think># 华为OD机试与解思路详解 ## 一、分阶段准备 1. **基础算法巩固** 建议从简单目入手,掌握排序(如快速排序、归并排序)、查找(二分法)、递归等基础算法。例如快速排序的核心代码: ```python def quick_sort(arr): if len(arr) <= 1: return arr pivot = arr[0] left = [x for x in arr[1:] if x < pivot] right = [x for x in arr[1:] if x >= pivot] return quick_sort(left) + [pivot] + quick_sort(right) ``` 引用[1]提到**“由浅到深进行练习”**,可优先练习100分目[^1]。 2. **高频专项突破** - **动态规划**:如背包问、最长公共子序列。状态转移方程示例: $$dp[i][j] = \max(dp[i-1][j], dp[i-1][j-w_i] + v_i)$$ - **字符串处理**:KMP算法、回文判断。 - **图论**:DFS/BFS遍历、最短路径算法(Dijkstra)[^2]。 --- ## 二、算法核心要点 ### 1. 时间复杂度优化 - 例如,二叉树遍历的递归实现复杂度为$O(n)$,而暴力解法可能达到$O(n^2)$。需优先选择时间复杂度更优的算法。 - 引用[2]强调**“实现最低时间复杂度”**,如用哈希表($O(1)$查询)替代线性查找($O(n)$)。 ### 2. 边界条件处理 - 输入为空、数值溢出(如32位整数范围)、特殊字符等情况需单独处理。 - 示例:二分查找时需验证`left <= right`循环条件。 --- ## 三、代码优化技巧 | 技巧 | 示例 | 优化效果 | |------|------|----------| | 空间换时间 | 使用哈希表存储中间结果 | 查询时间从$O(n)$降至$O(1)$ | | 剪枝策略 | 在回溯算法中提前终止无效分支 | 减少递归深度 | | 尾递归优化 | 将递归转换为循环 | 避免栈溢出 | --- ## 四、技术面试准备 1. **手撕代码** - 需在20分钟内完成编码,并解释思路。例如: ```python def two_sum(nums, target): hash_map = {} for i, num in enumerate(nums): if target - num in hash_map: return [hash_map[target - num], i] hash_map[num] = i return [] ``` 引用[2]提到**“每个目使用五种语言解答”**,需熟悉多语言实现[^2]。 2. **八股文问** - 常见考点:进程 vs 线程、TCP三次握手、数据库索引原理。 --- ## 五、模拟实战与资源 1. **在线OJ系统使用** - 引用[1]推荐通过在线系统**“测试不同数据规模下的表现”**,例如10^3 vs 10^6数据量的差异[^1]。 2. **真训练** - 2024年E卷目包含字符串编解码、二叉树重构等高频型。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值