A password detection system for HackerRank accounts detects a password as similar if the number of vowels is equal to the number of consonants in the password.
Passwords consist of lowercase English characters only, and vowels are ('a', 'e', 'i', 'o', 'u').
To check the strength of a password and how easily it can be hacked, some manipulations can be made to the password. In one operation, any character of the string can either be incremented or decremented. For example, 'f' can be incremented to 'g', or decremented to 'e'. Note that character 'a' cannot be decremented and 'z' cannot be incremented.
Find the minimum number of operations in which the password can be made similar.
Function Description
Complete the function countMinimumOperations in the editor below.
countMinimumOperations has the following parameter:
string password: the password Returns int: the minimum number of operations
Constraints
1 ≤ password.length ≤ 10^5password仅由小写英文字母组成
解法
设元音数 v、辅音数 c,差 d = v - c。需要把 |d|/2 个字符在元音/辅音之间互转。对每个待转字符计算最近的相反类型字符的距离(如 v -> nearest consonant in alphabet),贪心选 |d|/2 个最小成本即可。时间复杂度 O(n log n)。
def countMinimumOperations(password: str) -> int:
vowels = set('aeiou')
v_chars = [c for c in password if c in vowels]
c_chars = [c for c in password if c not in vowels]
diff = len(v_chars) - len(c_chars)
if diff == 0: return 0
# Convert from larger group to smaller group |diff|/2 characters
if diff > 0:
candidates = v_chars; target_set = set('bcdfghjklmnpqrstvwxyz')
else:
candidates = c_chars; target_set = vowels
def min_dist(ch):
return min(abs(ord(ch) - ord(t)) for t in target_set)
costs = sorted(min_dist(c) for c in candidates)
return sum(costs[:abs(diff) // 2])class Solution {
int countMinimumOperations(String password) {
Set<Character> vowels = new HashSet<>(Arrays.asList('a','e','i','o','u'));
List<Character> vChars = new ArrayList<>(), cChars = new ArrayList<>();
for (char c : password.toCharArray()) (vowels.contains(c) ? vChars : cChars).add(c);
int diff = vChars.size() - cChars.size();
if (diff == 0) return 0;
List<Character> cands; Set<Character> targets;
if (diff > 0) {
cands = vChars;
targets = new HashSet<>();
for (char c = 'a'; c <= 'z'; c++) if (!vowels.contains(c)) targets.add(c);
} else {
cands = cChars; targets = vowels;
}
List<Integer> costs = new ArrayList<>();
for (char c : cands) {
int best = Integer.MAX_VALUE;
for (char t : targets) best = Math.min(best, Math.abs(c - t));
costs.add(best);
}
Collections.sort(costs);
int total = 0;
for (int i = 0; i < Math.abs(diff) / 2; i++) total += costs.get(i);
return total;
}
}class Solution {
public:
int countMinimumOperations(string password) {
set<char> vowels = {'a','e','i','o','u'};
vector<char> vChars, cChars;
for (char c : password) (vowels.count(c) ? vChars : cChars).push_back(c);
int diff = (int)vChars.size() - (int)cChars.size();
if (diff == 0) return 0;
vector<char>& cands = diff > 0 ? vChars : cChars;
set<char> targets;
if (diff > 0) for (char c = 'a'; c <= 'z'; c++) { if (!vowels.count(c)) targets.insert(c); }
else targets = vowels;
vector<int> costs;
for (char c : cands) {
int best = INT_MAX;
for (char t : targets) best = min(best, abs(c - t));
costs.push_back(best);
}
sort(costs.begin(), costs.end());
int total = 0;
for (int i = 0; i < abs(diff) / 2; i++) total += costs[i];
return total;
}
};A company wants to track the usage of its mobile app by recording users' login times and dates. The company stores the login information in a 2D array of strings, logs, which contains data in the format ["/username<user_id>","login_time","login_date"].
They need a function to process the logs and output a 2D array of strings, sorted lexicographically, that displays the number of times each user logs in per day in the format ["/username<user_id>","login_date","login_count"]. It must filter invalid data in the input array rather than write it to the output array.
Users should be sorted in lexicographic order based on their user_id. Each user's information should be sorted by the login date in ascending order. The date and time are provided in YYYY-MM-DD and HH:MM:SS format, and the username has the format "userX" where X is an integer.
Function Description
Complete the function countUserLogins in the editor.
countUserLogins has the following parameter:
String[][] logs: a 2D array of strings containing the login data Returns String[][]: a 2D array of strings containing the user login counts per day, sorted lexicographically
Constraints
1 ≤ n (size of logs) ≤ 10⁵2000 ≤ YYYY ≤ 30000 ≤ MM, DD, HH, SS ≤ 99- YYYY, MM, DD, HH, and SS are all integers.
- All usernames are of the format "user" appended with some integer (user_id).
Example 1
Input:
logs = [["user1","09:00:00","2021-01-01"],["user1","13:00:00","2021-01-01"],["user2","14:00:00","2021-01-01"],["user1","20:00:00","2021-01-02"],["user2","21:00:00","2021-01-01"]]
Output:
[["user1","2021-01-01","2"],["user1","2021-01-02","1"],["user2","2021-01-01","2"]]
Explanation:
The function should output the login counts for each user per day, sorted lexicographically, resulting in a 2-d array of strings in the format [["user1","2021-01-01","3"],["user1","2021-01-02","1"],["user2","2021-01-01","1"]].
Example 2
Input:
logs = [["user1","09:00:00","2021-01-01"],["user1","13:00:00","2021-01-01"],["user2","14:00:00","2021-01-01"],["user1","20:00:00","2021-01-01"],["user2","21:00:00","2021-01-01"], ["user3","25:00:00","2021-01-01"], ["user4","22:00:00","2021-02-29"]]
Output:
[["user1","2021-01-01","3"],["user2","2021-01-01","2"]]
Explanation:
- user1 logs into the system 3 times on 2021-01-01
- user2 logs into the system 3 times on 2021-01-01
- entry 6 in the logs has an invalid time, 25:00:00.
- entry 7 in the logs has an invalid data, 2021-02-29.
解法
校验时间 HH < 24, MM < 60, SS < 60;日期合法(含闰年/月天数)。按 (user, date) 计数,再按字典序输出。时间复杂度 O(n log n)。
from typing import List
from collections import defaultdict
from datetime import datetime
def countUserLogins(logs: List[List[str]]) -> List[List[str]]:
counter = defaultdict(int)
for user, t, d in logs:
try:
h, m, s = map(int, t.split(':'))
if not (0 <= h < 24 and 0 <= m < 60 and 0 <= s < 60): continue
datetime.strptime(d, "%Y-%m-%d")
except ValueError:
continue
counter[(user, d)] += 1
keys = sorted(counter.keys())
return [[u, d, str(counter[(u, d)])] for u, d in keys]class Solution {
String[][] countUserLogins(String[][] logs) {
Map<String, Integer> counter = new TreeMap<>();
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("uuuu-MM-dd").withResolverStyle(java.time.format.ResolverStyle.STRICT);
for (String[] row : logs) {
try {
String[] tp = row[1].split(":");
int h = Integer.parseInt(tp[0]), m = Integer.parseInt(tp[1]), s = Integer.parseInt(tp[2]);
if (h < 0 || h >= 24 || m < 0 || m >= 60 || s < 0 || s >= 60) continue;
java.time.LocalDate.parse(row[2], fmt);
} catch (Exception e) { continue; }
counter.merge(row[0] + "\t" + row[2], 1, Integer::sum);
}
List<String[]> out = new ArrayList<>();
for (Map.Entry<String, Integer> e : counter.entrySet()) {
String[] kp = e.getKey().split("\t");
out.add(new String[]{kp[0], kp[1], String.valueOf(e.getValue())});
}
return out.toArray(new String[0][]);
}
}class Solution {
public:
vector<vector<string>> countUserLogins(vector<vector<string>>& logs) {
map<pair<string, string>, int> counter;
for (auto& row : logs) {
int h, m, s;
if (sscanf(row[1].c_str(), "%d:%d:%d", &h, &m, &s) != 3) continue;
if (h < 0 || h >= 24 || m < 0 || m >= 60 || s < 0 || s >= 60) continue;
int yy, mm, dd;
if (sscanf(row[2].c_str(), "%d-%d-%d", &yy, &mm, &dd) != 3) continue;
if (mm < 1 || mm > 12 || dd < 1) continue;
int dim[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
bool leap = (yy % 4 == 0 && yy % 100 != 0) || yy % 400 == 0;
if (mm == 2 && leap) dim[1] = 29;
if (dd > dim[mm - 1]) continue;
counter[{row[0], row[2]}]++;
}
vector<vector<string>> out;
for (auto& [k, v] : counter) out.push_back({k.first, k.second, to_string(v)});
return out;
}
};Given an array price[1-n] and m (discount), find the minimum price to spend to buy all the items.
Use the following formula to apply the coupon: price[i] / 2^x, where x is the number of coupons used, and i is the index of the item in the array.
Function Description
Complete the function findMinimumPriceToSpend in the editor.
findMinimumPriceToSpend has the following parameters:
-
int[] price: an array of integers representing the price of each item
-
int m: the number of discounts available Returnsint: the minimum price to spend
Example 1
Input:
price = [1, 2, 3]
m = 2
Output:
3
Explanation:
解法
贪心 + 大顶堆:每张优惠券都用在当前价格最大的商品上(半价后放回)。注意 floor 整除,价格为 0 后不再受益。时间复杂度 O((n + m) log n)。
import heapq
from typing import List
def findMinimumPriceToSpend(price: List[int], m: int) -> int:
h = [-p for p in price]
heapq.heapify(h)
while m > 0 and -h[0] > 0:
top = -heapq.heappop(h)
heapq.heappush(h, -(top // 2))
m -= 1
return -sum(h)class Solution {
long findMinimumPriceToSpend(int[] price, int m) {
PriorityQueue<Long> pq = new PriorityQueue<>(Comparator.reverseOrder());
for (int p : price) pq.add((long) p);
while (m > 0 && pq.peek() > 0) {
long top = pq.poll();
pq.add(top / 2);
m--;
}
long sum = 0;
for (long v : pq) sum += v;
return sum;
}
}class Solution {
public:
long long findMinimumPriceToSpend(vector<int>& price, int m) {
priority_queue<long long> pq;
for (int p : price) pq.push(p);
while (m > 0 && pq.top() > 0) {
long long top = pq.top(); pq.pop();
pq.push(top / 2);
m--;
}
long long sum = 0;
while (!pq.empty()) { sum += pq.top(); pq.pop(); }
return sum;
}
};