A transaction is possibly invalid if:
$1000
, or;60
minutes of another transaction with the same name in a different city.You are given an array of strings transaction
where transactions[i]
consists of comma-separated values representing the name, time (in minutes), amount, and city of the transaction.
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
transactions[i]
takes the form "{name},{time},{amount},{city}"
{name}
and {city}
consist of lowercase English letters, and have lengths between 1
and 10
.{time}
consist of digits, and represent an integer between 0
and 1000
.{amount}
consist of digits, and represent an integer between 0
and 2000
.This problem involves identifying invalid transactions based on two criteria: exceeding a transaction amount limit and proximity to another transaction with the same name but a different city. The optimal solution leverages a hash table (dictionary in Python) for efficient lookups.
Data Structure: We use a dictionary (d
in Python, Map
in Java, etc.) to store transactions keyed by the name of the person involved in the transaction. The value associated with each name is a list of tuples (or similar structures). Each tuple contains:
time
: The transaction time.city
: The city where the transaction occurred.index
: The index of the transaction in the input array.Iteration and Checking: We iterate through the transactions
array. For each transaction:
Result: After processing all transactions, we collect all transactions marked as invalid and return them.
Time Complexity: The nested loop structure leads to a time complexity of O(n^2) in the worst case, where n is the number of transactions. This is because we potentially compare each transaction with every other transaction with the same name.
Space Complexity: The space complexity is O(n) because, in the worst-case scenario, the dictionary could store all transactions.
Python:
from collections import defaultdict
class Solution:
def invalidTransactions(self, transactions: List[str]) -> List[str]:
d = defaultdict(list)
invalid = set()
for i, transaction in enumerate(transactions):
name, time, amount, city = transaction.split(",")
time, amount = int(time), int(amount)
if amount > 1000:
invalid.add(i)
d[name].append((time, city, i))
for name, transactions_for_name in d.items():
for i in range(len(transactions_for_name)):
for j in range(i+1, len(transactions_for_name)):
time1, city1, index1 = transactions_for_name[i]
time2, city2, index2 = transactions_for_name[j]
if city1 != city2 and abs(time1 - time2) <= 60:
invalid.add(index1)
invalid.add(index2)
result = [transactions[i] for i in invalid]
return result
Java: (Uses a similar approach, replacing defaultdict
with HashMap
and sets with HashSet
)
import java.util.*;
class Solution {
public List<String> invalidTransactions(String[] transactions) {
Map<String, List<Transaction>> map = new HashMap<>();
Set<Integer> invalid = new HashSet<>();
for (int i = 0; i < transactions.length; i++) {
String[] parts = transactions[i].split(",");
String name = parts[0];
int time = Integer.parseInt(parts[1]);
int amount = Integer.parseInt(parts[2]);
String city = parts[3];
if (amount > 1000) invalid.add(i);
map.computeIfAbsent(name, k -> new ArrayList<>()).add(new Transaction(time, city, i));
}
for (List<Transaction> transList : map.values()) {
for (int i = 0; i < transList.size(); i++) {
for (int j = i + 1; j < transList.size(); j++) {
Transaction t1 = transList.get(i);
Transaction t2 = transList.get(j);
if (!t1.city.equals(t2.city) && Math.abs(t1.time - t2.time) <= 60) {
invalid.add(t1.index);
invalid.add(t2.index);
}
}
}
}
List<String> result = new ArrayList<>();
for (int index : invalid) {
result.add(transactions[index]);
}
return result;
}
class Transaction {
int time;
String city;
int index;
Transaction(int time, String city, int index) {
this.time = time;
this.city = city;
this.index = index;
}
}
}
Other languages (C++, Javascript, Go, etc.) would follow a very similar structure. Remember to handle potential errors like invalid input formats appropriately in a production setting.