[补题记录] 基于日志的系统故障预测


某通讯设备系统定义了一系列系统事件,当事件发生时会将该事件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;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值