给定一个放有字母和数字的数组,找到最长的子数组,且包含的字母和数字的个数相同。
返回该子数组,若存在多个最长子数组,返回左端点下标值最小的子数组。若不存在这样的数组,返回一个空数组。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/find-longest-subarray-lcci/description/
由于给的数组只有字母和数字两种,于是我们可以将字母和数字进行转化,遇到数字算 +1 ,遇到字母算 -1 ,然后来计算前缀和。我们用哈希表来记录某前缀和最早出现的位置,当某前缀和再次出现时就用当前的位置减去他最早出现的位置,即可得到子数组长度,我们采用 maxLen 来存储当前最大的子数组长度,更新maxLen时,同时更新最大子数组的起始坐标,最后返回即可。
class Solution {
public:
vector<string> findLongestSubarray(vector<string>& array) {
int size = array.size();
int prefix[size];
int start=-1;
int maxLen=0;
vector<string> ans;
unordered_map<int,int> map;
map[0] = -1;
prefix[0] = array[0][0]>='0'&&array[0][0]<='9'?1:-1;
for(int i=1;i<size;i++){
if(array[i][0]>='0'&&array[i][0]<='9')
prefix[i] = prefix[i-1]+1;
else
prefix[i] = prefix[i-1]-1;
}
for(int i=0;i<size;i++){
if(map.count(prefix[i])){
if(maxLen<i-map[prefix[i]]){
maxLen = i-map[prefix[i]];
start = map[prefix[i]];
}
}else
map[prefix[i]] = i;
}
ans.assign(array.begin()+start+1,array.begin()+start+maxLen+1);
return ans;
}
};
和我的思路差不多,但是写法仍然有值得学习的地方
class Solution {
public:
vector<string> findLongestSubarray(vector<string>& array) {
unordered_map<int, int> indices;
indices[0] = -1;
int sum = 0;
int maxLength = 0;
int startIndex = -1;
int n = array.size();
for (int i = 0; i < n; i++) {
if (isalpha(array[i][0])) {
sum++;
} else {
sum--;
}
if (indices.count(sum)) {
int firstIndex = indices[sum];
if (i - firstIndex > maxLength) {
maxLength = i - firstIndex;
startIndex = firstIndex + 1;
}
} else {
indices[sum] = i;
}
}
if (maxLength == 0) {
return {};
}
return vector<string>(array.begin() + startIndex, array.begin() + startIndex + maxLength);
}
};