某通讯设备系统定义了一系列系统事件,当事件发生时会将该事件ID记录到日志中,该日志的数据全集称为原始事件序列
。根据经验,当某些特征事件
出现时,往往预示着系统存在需要解决的潜在问题。
现给定一组原始事件序列 events
(元素可以重复),以及一个特征序列 traits
(元素不重复)
请在 events 中从左往右按匹配规则找到一个匹配特征序列的最短连续子序列;如果存在多个最短的,则返回最早匹配到的连续子序列。
匹配规则:对于 events
中的某个连续子序列,当从中去除
n
n
n 个(n >= 0)元素后、且不破坏余下元素的相对位置所形成的新序列和特征序列 traits
相同时,则该连续子序列是匹配特征序列的。
注:输入保证至少存在一个匹配的连续子序列。
输入
第一个参数是数组 events,代表原始事件序列,1 < events.length <= 1000
第二个参数是数组 traits,代表特征序列,1 <= traits.length <= 20
0 <= events[i], traits[i] <= 1000
输出
一个连续子序列
样例1
输入:
[4, 8, 4, 3, 6, 6, 8] [4, 6, 8]
输出:
[4, 3, 6, 6, 8]
解释:
如 event 中的一个连续子序列 [4, 3, 6, 6, 8] ,去除其中元素 3 和 任一个 6 后、且余下元素保持相对顺序不变,所形成的新序列 [4, 6, 8] 和特征序列相同,因此所选择的连续子序列 [4, 3, 6, 6, 8] 是匹配特征序列的。
O(n) 做法
在遍历 events
的过程中,一定是不断地出现 traits
中的元素。而只要我们在遇到 traits
中的元素时,让对应的 traits
的元素,指向它的前一个元素在 events
中的位置(pos[ traits[i] ] = pos[ traits[i-1] ]
),直到使得 pos[ traits[m] ]
也有所指向,就说明完成了一次合法答案。
代码
#include <vector>
using namespace std;
class Solution {
public:
vector<int> MatchLogTrait(const vector<int>& events, const vector<int>& traits)
{
std::vector<int> latest(1001, -1), traits_to_pos(1001, -1);
for (int i = 0; i < traits.size(); ++i) {
traits_to_pos[traits[i]] = i;
}
int l = 0, r = events.size() - 1;
for (int i = 0; i < events.size(); ++i) {
int cur = events[i];
int pos = traits_to_pos[cur];
if (pos == -1) {
continue;
}
if (pos == 0) {
latest[0] = i;
} else {
latest[pos] = latest[pos - 1];
}
if (pos == traits.size() - 1) {
if (latest[pos] != -1 && i - latest[pos] + 1 < r - l + 1) {
l = latest[pos];
r = i;
}
}
}
vector<int> ans;
for (int i = l; i <= r; ++i) {
ans.push_back(events[i]);
}
return ans;
}
};
O(n^2) 做法
对于 events
中的每个位置,去直接匹配 traits
即可。
代码
#include <vector>
using namespace std;
class Solution {
public:
vector<int> MatchLogTrait(const vector<int>& events, const vector<int>& traits)
{
std::vector<int> ans;
int ansSize = 1e9;
int n = events.size(), m = traits.size();
for (int i = 0; i < n; ++ i) {
int j = i, k = 0;
std::vector<int> tmp;
if (events[i] != traits[0]) continue;
for (; j < n && k < m; ++ j) {
if (events[j] == traits[k]) {
k ++;
}
}
std::cout << "k = " << k << "\n";
if (k == m - 1 && tmp.size() < ansSize) {
ans.clear();
for (auto &x : tmp) ans.push_back(x);
ansSize = tmp.size();
}
}
return ans;
}
};