leetcode---数组系列-- 面试题 17.05. 字母与数字(前缀和+哈希)

leetcode—数组系列–面试题 17.05. 字母与数字(前缀和+哈希)

题目描述

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

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

示例 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”]
输出: []

我们可以把字母抽象成-1 ,数字抽象成1,那么子数组的总和含义就是数字个数与字母个数的差值。假设子数组 [l,r) 是满足字母个数和数字个数相等的,那么这段子数组总和必然是0。那么我们不难发现两个零之间的序列即为字符与数字个数相等的序列,则保留这部分序列的左右下标:left,right

使用下例讲解一下操作流程:

输入: [“A”,“1”,“B”,“C”,“D”,“2”,“3”]
输出:[“1”,“B”,“C”,“D”,“2”,“3”]

我们采用前缀序列和的方式以及哈希表。使用unordered_map<int,int> mp, mp.first存储前缀和,mp.second存储对应的位置。首先要注意的是mp[0]应该设置为-1。因为前缀和为0的第一个位置应该在整个数组之前,"A"作为数组的第一个元素,在这之前的即为-1。因此在该例中,我们可以得到mp存储的值如下:

mp[0]=-1; //整个数组之前
mp[-1]=0; //"A"位置为0,前缀和为-1(字符抽象为-1)。
mp[0] // "1"前缀和为0,mp[0]已存在,为了保留最长子串,此处不改动。更新left,right。
mp[-1] //"B"前缀和为-1,此处不改动mp[-1],原因同上。更新left,right。
mp[-2]=3; //"C"前缀和为-2,存储到mp中。
mp[-3]=4; //"D"前缀和为-3,存储到mp中。
mp[-2] //"2"前缀和为-2, 计算 i (当前位置)-mp[-2]。更新left,right。
mp[-1] //"3"前缀和为-1。计算 i (当前位置)-mp[-1] ,更新left,right。

c++代码如下:

    vector<string> findLongestSubarray(vector<string>& array) 
    {
        int n = array.size();
        unordered_map<int, int> mp;
        mp[0] = -1;
        int cnt = 0, l = 0, r = 0;
        for (int i = 0; i < n; ++i) 
        {
            cnt += isdigit(array[i][0]) ? 1 : -1;//isdigit():检查参数c是否为阿拉伯数字0到9
            if (mp.find(cnt) != mp.end()) 
            {
                if (r-l < i-mp[cnt]) 
                {
                    l = mp[cnt] + 1;
                    r = i + 1;
                }
            } 
            else 
                mp[cnt] = i;
        }
        return vector<string>(array.begin()+l, array.begin()+r);//包含l不包含r
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值