Medium

Invalid TransactionsC++

Full explanation · Time O(nlogn) · Space O(n)

// Time:  O(nlogn)
// Space: O(n)

class Solution {
public:
    vector<string> invalidTransactions(vector<string>& transactions) {
        static const int AMOUNT = 1000;
        static const int MINUTES = 60;
        vector<tuple<string, int, int, string>> trans;
        for (const auto& transaction : transactions) {
            const auto& t = split(transaction, ',');
            trans.emplace_back(t[0], stoi(t[1]), stoi(t[2]), t[3]);
        }
        sort(trans.begin(), trans.end(),
             [](const auto& a, const auto& b) {
                 return get<1>(a) < get<1>(b);
             });
        unordered_map<string, vector<int>> trans_indexes;
        for (int i = 0; i < trans.size(); ++i) {
            trans_indexes[get<0>(trans[i])].emplace_back(i);
        }
        vector<string> result;
        for (const auto& [name, indexes] : trans_indexes) {
            int left = 0, right = 0;
            for (int i = 0; i < indexes.size(); ++i) {
                const auto& t = trans[indexes[i]];
                if (get<2>(t) > AMOUNT) {
                    result.emplace_back(to_str(t));
                    continue;
                }
                while (left + 1 < indexes.size() &&
                       get<1>(trans[indexes[left]]) < get<1>(t) - MINUTES) {
                    ++left;
                }
                while (right + 1 < indexes.size() &&
                       get<1>(trans[indexes[right + 1]]) <= get<1>(t) + MINUTES) {
                    ++right;
                }
                for (int i = left; i <= right; ++i) {
                    if (get<3>(trans[indexes[i]]) != get<3>(t)) {
                        result.emplace_back(to_str(t));
                        break;
                    }
                }
            }
        }
        return result;
    }

private:
    vector<string> split(const string& s, const char delim) {
        vector<string> result;
        auto end = string::npos;
        do {
            const auto& start = end + 1;
            end = s.find(delim, start);
            result.emplace_back(s.substr(start, end - start));
        } while (end != string::npos); 
        return result;
    }
    
    template<typename T>
    string to_str(const T& t) {
        stringstream ss;
        ss << get<0>(t) << "," << get<1>(t) << ","
           << get<2>(t) << "," << get<3>(t);
        return ss.str();
    }
};