【子数组/子串】相关类型题目整理

一、力扣560.和为k的子数组

  • 给定一个整数数组和一个整数 k,你需要找到该数组中和为 k 的连续的子数组的个数。
  • 输入:nums = [1,1,1], k = 2
  • 输出: 2 , [1,1] 与 [1,1] 为两种不同的情况。

(一)暴力枚举(双重循环)

  • 枚举数组中所有的子数组,统计出和为k的子数组的个数。
  • 双重循环的思想比较简单,但是会超出题目限制。代码如下:
int subarrySum(vector<int>& nums, int k)
    {
   
        int sum = 0, count = 0;
        for (int i = 0; i < nums.size(); i++)
        {
   
            for (int j = i; j < nums.size(); j++)
            {
   
                sum += nums[j];
                if (sum == k)
                {
   
                    count++;
                }
            }
            sum = 0;
        }
        return count;
    }
  • 解析:

在这里插入图片描述

(二)前缀和思想+哈希优化

  • 所谓前缀和,就是对于一个给定的数列A,它的前缀和数列S是通过递推能求出来的部分和。
  • 举个例子如下:

在这里插入图片描述

  • 假设我们要获取nums[2]到nums[4]这个区间的和,可以用下图所示方法得到:

在这里插入图片描述

  • 思路:

在这里插入图片描述

  • 代码如下:
int subarrySum(vector<int>& nums, int k)
{
   
    unordered_map<int, int> mp;//哈希表
    int count = 0;//统计前缀和出现的次数
    int pre = 0;//计算前缀和
    mp[0] = 1;
    for (auto& x : nums)
    {
   
        pre += x;
        if (mp.find(pre - k) != mp.end())//寻找出现过的前缀和,如果找到了就给count加上它出现过的次数。
        {
   
            count += mp[pre - k];
        }
        mp[pre]++;
    }
    return count;
}

二、力扣974.和可被k整除的子数组

  • 给定一个整数数组 A,返回其中元素之和可被 K 整除的(连续、非空)子数组的数目。
  • 输入:A = [4,5,0,-2,-3,1], K = 5
  • 输出:7
  • 解释:有 7 个子数组满足其元素之和可被 K = 5 整除:
    [4, 5, 0
<think>好的,用户想了解关于String类型题目,也就是字符串相关的编程题。首先,我需要确定用户的需求。他们可能是刚开始学习编程,或者正在准备面试,需要掌握常见的字符串题目类型解决方法。 首先,我得整理字符串题目的常见类型。常见的包括回文判断、子串查找、字符串转换、括号匹配、异位词分组、最长公共前缀、字符串相乘、编辑距离、字符串排列分割问题等。这些都是面试中常考的问题,用户可能需要了解这些题目的基本思路解决方法。 然后,要确保每个类型都有例子,这样用户更容易理解。比如回文判断可以用双指针法,子串查找用滑动窗口,异位词分组用哈希表统计字符频率。需要详细但简洁地解释每个题型的解决思路,并给出代码示例。这里要注意代码的语法正确性,比如Python中的字符串操作,索引的使用等。 另外,用户可能希望知道如何高效解决这些问题,比如时间复杂度的优化。比如在最长回文子串问题中,动态规划中心扩展的区别,或者编辑距离的动态规划解法。需要强调这些方法的关键点,比如状态转移方程。 还要注意用户可能的误区,比如字符串的不可变性导致拼接时的效率问题,或者处理Unicode字符时的注意事项。这些都是实际编程中容易出错的地方,需要提醒用户。 最后,确保回答结构清晰,分点列出每个题型,说明解决思路示例代码。这样用户能够逐步学习,逐个击破不同类型题目。同时,要保证语言通俗易懂,避免过于专业的术语,但也要准确无误。</think>关于字符串(String)类型的编程题目,以下是常见题型解决思路的整理: 一、基础操作类 1. 回文判断 - 问题:判断字符串是否对称 - 解法:双指针法 - 示例:判断"abcba" ```python def is_palindrome(s): left, right = 0, len(s)-1 while left < right: if s[left] != s[right]: return False left += 1 right -= 1 return True ``` 2. 字符串反转 - 问题:反转字符串/反转单词顺序 - 解法:Python切片或双指针 - 时间复杂度:$O(n)$ 二、子串/子序列问题 1. 最长回文子串 - 解法:动态规划(状态转移方程:$dp[i][j] = (s[i]==s[j]) \land dp[i+1][j-1]$)或中心扩展法 - 时间复杂度:$O(n^2)$ 2. 最长无重复子串 - 解法:滑动窗口 + 哈希表 - 关键点:维护窗口[start, end] - 示例代码: ```python def lengthOfLongestSubstring(s): char_index = {} max_len = start = 0 for end, char in enumerate(s): if char in char_index and char_index[char] >= start: start = char_index[char] + 1 max_len = max(max_len, end - start + 1) char_index[char] = end return max_len ``` 三、字符串转换 1. 整数转换(atoi) - 关键处理:处理前导空格、正号、溢出检测 - 边界案例:" -42", "4193 with words" 2. 罗马数字转整数 - 解法:逆向扫描 + 值比较 - 规则:IV=4, IX=9, XL=40等特殊组合 四、模式匹配问题 1. 正则表达式匹配(LeetCode 10) - 解法:动态规划 - 状态转移方程处理'.''*'的情况 2. 通配符匹配(LeetCode 44) - 解法:二维动态规划 - 处理'?''*'的匹配逻辑 五、高频难题 1. 编辑距离(LeetCode 72) - 解法:动态规划 - 状态方程: $$dp[i][j] = \begin{cases} dp[i-1][j-1] & \text{if } s[i]=t[j] \\ 1 + \min(dp[i-1][j], dp[i][j-1], dp[i-1][j-1]) & \text{otherwise} \end{cases}$$ 2. 字符串相乘(LeetCode 43) - 解法:模拟竖式乘法 - 关键点:处理进位位置偏移 六、特殊结构问题 1. 括号匹配(LeetCode 20) - 解法:栈结构 - 处理三种括号类型:()[]{} 2. 异位词分组(LeetCode 49) - 解法:哈希表 + 字符排序 - 示例:将["eat","tea","tan"]分组为[["eat","tea"],["tan"]] 练习建议: 1. 先掌握双指针、滑动窗口等基础技巧 2. 注意字符串的不可变性(Python中拼接用join代替+) 3. 处理Unicode字符时考虑编码问题 4. 多画图理解动态规划的状态转移过程 常见优化方向: - 用数组代替哈希表提升速度(如固定26字母的情况) - 预处理字符串(如#a#b#c#处理回文问题) - KMP算法优化字符串匹配(时间复杂度$O(n+m)$)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值