1169. Invalid Transactions**

1169. Invalid Transactions**

https://leetcode.com/problems/invalid-transactions/

题目描述

A transaction is possibly invalid if:

  • the amount exceeds $1000, or;
  • if it occurs within (and including) 60 minutes of another transaction with the same name in a different city.
    Each transaction string transactions[i] consists of comma separated values representing the name, time (in minutes), amount, and city of the transaction.

Given a list of transactions, return a list of transactions that are possibly invalid. You may return the answer in any order.

Example 1:

Input: transactions = ["alice,20,800,mtv","alice,50,100,beijing"]
Output: ["alice,20,800,mtv","alice,50,100,beijing"]
Explanation: The first transaction is invalid because the second transaction occurs within a difference of 60 minutes, have the same name and is in a different city. Similarly the second one is invalid too.

Example 2:

Input: transactions = ["alice,20,800,mtv","alice,50,1200,mtv"]
Output: ["alice,50,1200,mtv"]

Example 3:

Input: transactions = ["alice,20,800,mtv","bob,50,1200,mtv"]
Output: ["bob,50,1200,mtv"]

Constraints:

  • transactions.length <= 1000
  • Each transactions[i] takes the form "{name},{time},{amount},{city}"
  • Each {name} and {city} consist of lowercase English letters, and have lengths between 1 and 10.
  • Each {time} consist of digits, and represent an integer between 0 and 1000.
    Each {amount} consist of digits, and represent an integer between 0 and 2000.

C++ 实现 1

此题差评, 描述不清, 另外我看题也不太认真, 浪费了大量时间. 🔥🔥🔥

读懂题意是关键. 这道题要求最后返回的是 invalid 的交易, 而交易被满足如下条件之一就被定义为 invalid:

  • 本次交易的 amount > 1000
  • 在本次交易 A 的股票名字和另一次交易 B 的股票名字相同的情况下, 交易发生的地点(city)不同并且交易时间在 60 分钟之内.

第二点限制条件可以理解为不能在短时间内跑到另一个城市对同一只股票发生交易.

然而, 要真正理解两个限制条件并写出代码, 我们有一些更深层的问题要问, 这可以从题目给出的示例出发. 第 1 个例子中, 由于不满足第二个条件, 所以两个交易都是 invalid 的. 第 2 个例子, 需要特别注意, 这个例子之所以返回 ["alice,50,1200,mtv"] 这个结果, 一方面我们考虑到第一个条件的限制, 而另一方面, 第二个条件也会对结果产生影响, 原因是输入的两个交易 ["alice,20,800,mtv","alice,50,1200,mtv"] 它们发生的交易地点都是 "mtv", 在同一个城市, 所以即使时间上的差值小于 60, "alice,20,800,mtv" 这个交易仍然是有效的. 假设这个示例的输入是 ["alice,20,800,omg","alice,50,1200,mtv"], 此时返回什么 ? !
此时返回 ["alice,20,800,omg","alice,50,1200,mtv"], 原因它们不满足第二个条件, (额外的 "alice,50,1200,mtv" 还不满足第一个条件).

下面代码的逻辑是:

  • parse_transaction 函数中, 使用 record 保存每个访问过的 transaction, res 保存 invalid 的 transaction
    • record 的结构比较复杂, 表示为 record[name][city].push_back({time, amount}), 第一个 map 的 key 是股票的 name, 而 record[name] 中的 map 的 key 对应的是 city, 而 record[name][city] 对应的 vector 保存的是 {time, amount} pair.
    • 对于当前访问的 transaction, 我们看 name 是否已经存在于 record 中. 不存在就放心的加入到 record 中, 因为股票名字 name 不同, 不会影响 invalid transaction 的判断.
    • 如果 record 已经存在了相同的 name, 也就是说, 针对 name 这只股票, 应该有交易发生了. 我们这时候就要判断它是否会违反第二个约束条件. 注意, 这里暂时不考虑第一个约束条件, 因为不管 amount 有没有超过 1000, 该交易都是要存储到 record 中! 这一点需要切记.
    • 遍历 name 这只股票发生交易的所有城市 for (auto &city_record : record[name]), 只有当城市不同的时候, 才需要进行时间上的比较.
    • 使用 invalid 这个 bool 值来判断是否需要将本次交易设置为 invalid 的. 如果上一步的时间比较发现, 存在交易 B 和本次交易 A 发生的地点不同, 但是时间相差不超过 60, 那么不仅需要将交易 B 存入 invalid 交易集合 res 中, 当比较完所有的交易后, 还要记得将本次交易 A 存入 res 中.
    • 之后, 如果 invalid == true 或者本次交易的 amount > 1000, 那么就将本次交易加入 res 中.
    • 最后注意, 访问的每次交易都要存入 record 中!
class Solution {
private:
    void parse_transaction(const string &transaction, unordered_map<string, unordered_map<string, vector<pair<int, int>>>> &record, unordered_set<string> &res) {
    	// 解析 transaction 字符串
        stringstream ss(transaction);
        string name, city;
        int time, amount;
        vector<string> tmp(4, "");
        int i = 0;
        while (getline(ss, tmp[i++], ','));
        name = tmp[0], city = tmp.back();
        time = std::stoi(tmp[1]), amount = std::stoi(tmp[2]);
        
        bool invalid = false;
        if (record.count(name)) { // 处理新 city
            for (auto &city_record : record[name]) {
                auto old_city = city_record.first;
                auto pairs = city_record.second;
                if (city != old_city) { // 只有 city 不相同时才需要比较时间
                    for (auto &q : pairs) {
                        auto tm = q.first;
                        auto money = q.second;
                        if (std::abs(tm - time) <= 60) {
                            invalid = true;
                            res.insert(name + "," + std::to_string(tm) +
                                 "," + std::to_string(money) + "," +
                                 old_city);
                        }
                    }
                }
            }
        }
        if (invalid || amount > 1000) res.insert(transaction); 
        record[name][city].push_back({time, amount}); 
    }
public:
    vector<string> invalidTransactions(vector<string>& transactions) {
        unordered_map<string, unordered_map<string, vector<pair<int, int>>>> record;
        unordered_set<string> tmp;
        for (auto &t : transactions)
            parse_transaction(t, record, tmp);
        vector<string> res(tmp.begin(), tmp.end());
        return res;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值