──是啊。我留下了美梦般的回忆,不过时间到了。

t2设计题不错,不过放水了, t3的构造题考验思维,t4经典的状压DP
整体还不错,^_^
一般求第K大的题都挺麻烦的,幸好这题是t1.
这边用了slot桶,然后贪心倒序求第二大。
时间复杂度为
class Solution {
public int secondHighest(String s) {
int[] hash = new int[10];
for (char c: s.toCharArray()) {
if (c >= '0' && c <= '9') {
hash[c - '0']++;
}
}
int seen = 0;
for (int i = 9; i >= 0; i--) {
if (hash[i] > 0) {
seen++;
if (seen == 2) {
return i;
}
}
}
return -1;
}
}这题一度想用树状数组维护 没过期的token数了,不过数据范围实在太大了.
最后用了Brute Force Algorithm.
值得一提的是,这边用了 LinkedHashMap, 就是那个著名的LRU底层数据结构。
class AuthenticationManager {
// 数据太大,不能用BIT
private int timeToLive;
LinkedHashMap<String, Integer> tokenMap = new LinkedHashMap<String, Integer>();
public AuthenticationManager(int timeToLive) {
this.timeToLive = timeToLive;
}
public void generate(String tokenId, int currentTime) {
tokenMap.put(tokenId, currentTime + this.timeToLive);
}
public void renew(String tokenId, int currentTime) {
long at = tokenMap.getOrDefault(tokenId, -1);
if (at > currentTime) {
tokenMap.put(tokenId, currentTime + timeToLive);
}
}
public int countUnexpiredTokens(int currentTime) {
int ans = 0;
Iterator<Map.Entry<String, Integer>> iter = tokenMap.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry<String, Integer> e = iter.next();
if (e.getValue().intValue() <= currentTime) {
iter.remove();
} else {
ans++;
}
}
return ans;
}
}非常不错的思维题,然后联想到集合的扩展,类似并查集在数组中扩展过程。
想到了贪心解, 满足条件的集合 尝试 扩展自己的边界,需要满足 集合, 那这个n可以合并到这个集合中去.
class Solution {
public int getMaximumConsecutive(int[] coins) {
Arrays.sort(coins);
int acc = 0;
for (int i = 0; i < coins.length; i++) {
if (acc + 1 >= coins[i]) {
acc += coins[i];
} else {
return acc + 1;
}
}
return acc + 1;
}
}这题的N范围, 数组最多为14,所以很容易联想到暴力dfs, 或者状压DP
最终采用状压DP,也没写记忆化搜索。
class Solution {
int gcd(int a, int b) {
return b == 0 ? a : gcd(b, a % b);
}
// 状压DP
public int maxScore(int[] nums) {
// 经典状压题
int m = nums.length;
int range = (1 << m);
int[] opt = new int[range];
Arrays.fill(opt, -Integer.MAX_VALUE / 4);
opt[0] = 0;
for (int i = 1; i < range; i++) {
List<Integer> arr = new ArrayList<>();
for (int j = 0; j < m; j++) {
if ((i & (1 << j)) != 0) {
arr.add(j);
}
}
if (arr.size() % 2 == 1) continue;
int last = 0;
for (int j = 0; j < arr.size(); j++) {
for (int k = j + 1; k < arr.size(); k++) {
last = (1 << arr.get(j)) | (1 << arr.get(k));
int other = i - last;
opt[i] = Math.max(
opt[i],
opt[other] + arr.size() / 2 * gcd(nums[arr.get(j)], nums[arr.get(k)])
);
}
}
}
return opt[range - 1];
}
}