面试题 17.05. 字母与数字

给定一个包含字母和数字的数组,文章提出了一个问题:找到字母和数字数量相同的最长子数组。通过使用前缀和和哈希表,可以有效地解决这个问题。在C++和Python中,分别提供了实现代码,以找到满足条件的子数组并返回其内容。
摘要由CSDN通过智能技术生成

题目链接

面试题 17.05. 字母与数字 mid

题目描述

给定一个放有字母和数字的数组,找到最长的子数组,且包含的字母和数字的个数相同。

返回该子数组,若存在多个最长子数组,返回左端点下标值最小的子数组。若不存在这样的数组,返回一个空数组。

示例 1:

输入: [“A”,“1”,“B”,“C”,“D”,“2”,“3”,“4”,“E”,“5”,“F”,“G”,“6”,“7”,“H”,“I”,“J”,“K”,“L”,“M”]
输出: [“A”,“1”,“B”,“C”,“D”,“2”,“3”,“4”,“E”,“5”,“F”,“G”,“6”,“7”]

示例 2:

输入: [“A”,“A”]
输出: []

提示:
  • a r r a y . l e n g t h ≤ 100000 array.length \leq 100000 array.length100000

分析:前缀和 + 哈希表

我们可以将 字母看作是 +1,数字看作是 -1,那么原问题就转换为 求最长的一段和 sum = 0的子数组

我们用一个哈希表 m来记录遍历过的 前缀和 s[i]和它对应的下标 i

如果当前遍历到了 s[j],并且 m存在 s[j]这个键。由此,我们可以得到 i = m[s[j]]。那么 (i , j]这一段就是和为 0

的子数组,我们就将答案更新即可。

我们用 idx代表最长的那段子数组的起始下标,用 len表示最长的那段子数组的长度。

最后返回 array的这一段 [idx , idx + len]即可。

时间复杂度: O ( n ) O(n) O(n)

C++代码:

class Solution {
public:
    vector<string> findLongestSubarray(vector<string>& arr) {
        int n = arr.size();
        unordered_map<int,int> m{{0,-1}};

        int idx = 0 , len  = 0;
        for(int j = 0 ,s = 0;j < n;j++){
            s += (arr[j][0] >= 'A' ? 1 : -1);
            if(m.count(s)){
                int i = m[s];
                if(j - i > len){
                    len = j - i;
                    idx = i + 1;
                }
            }
            else m[s] = j;
        }
        return vector<string> (arr.begin() + idx,arr.begin() + idx + len);
    }
};

Python代码:


class Solution:
    def findLongestSubarray(self, arr: List[str]) -> List[str]:
        m = {0:-1}
        s = idx = len = 0
        for j,str in enumerate(arr):
            s += 1 if str.isalpha() else -1
            if s in m:
                i = m[s]
                if len < j - i:
                    idx = i + 1
                    len = j - i
            else:
                 m[s] = j    
        
        return arr[idx:idx+len]

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值