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 between1
and10
. - Each
{time}
consist of digits, and represent an integer between0
and1000
. - Each
{amount}
consist of digits, and represent an integer between0
and2000
.
// OJ: https://leetcode.com/problems/invalid-transactions/
// Author: github.com/lzl124631x
// Time: O(N^2)
// Space: O(N)
struct Transaction {
string name;
int time;
int amount;
string city;
Transaction(string t) {
istringstream ss(t);
getline(ss, name, ',');
string token;
getline(ss, token, ',');
time = stoi(token);
getline(ss, token, ',');
amount = stoi(token);
ss >> city;
}
};
class Solution {
public:
vector<string> invalidTransactions(vector<string>& A) {
vector<Transaction> B;
unordered_set<int> invalid;
for (int i = 0; i < A.size(); ++i) {
auto t = Transaction(A[i]);
if (t.amount > 1000) invalid.insert(i);
B.push_back(t);
}
for (int i = 0; i < A.size(); ++i) {
for (int j = i + 1; j < A.size(); ++j) {
if (B[i].name == B[j].name && abs(B[i].time - B[j].time) <= 60 && B[i].city != B[j].city) {
invalid.insert(i);
invalid.insert(j);
}
}
}
vector<string> ans;
for (int i : invalid) ans.push_back(A[i]);
return ans;
}
};
// OJ: https://leetcode.com/problems/invalid-transactions/
// Author: github.com/lzl124631x
// Time: O(NlogN)
// Space: O(N)
struct Transaction {
string name;
int time;
int amount;
string city;
Transaction(string t) {
istringstream ss(t);
getline(ss, name, ',');
string token;
getline(ss, token, ',');
time = stoi(token);
getline(ss, token, ',');
amount = stoi(token);
ss >> city;
}
};
class Solution {
public:
vector<string> invalidTransactions(vector<string>& A) {
unordered_map<string, vector<int>> m;
vector<Transaction> B;
unordered_set<int> invalid;
for (int i = 0; i < A.size(); ++i) {
auto t = Transaction(A[i]);
if (t.amount > 1000) invalid.insert(i);
m[t.name].push_back(i);
B.push_back(t);
}
for (auto &[p, ids] : m) {
sort(begin(ids), end(ids), [&](int a, int b) { return B[a].time < B[b].time; });
int i = 0, j = 0, k = 0, N = ids.size();
unordered_map<string, int> cities;
while (j < N) {
while (B[ids[j]].time - B[ids[i]].time > 60) {
auto &c = B[ids[i++]];
if (--cities[c.city] == 0) cities.erase(c.city);
}
if (B[ids[j]].time - B[ids[i]].time <= 60) {
auto &c = B[ids[j++]];
cities[c.city]++;
if (cities.size() > 1) {
for (k = max(k, i); k < j; ++k) invalid.insert(ids[k]);
}
}
}
}
vector<string> ans;
for (int i : invalid) ans.push_back(A[i]);
return ans;
}
};