Weekly Contest 390
Problem A
每个字符最多出现两次的最长子字符串
思路
双指针,使用一个数组记录每个字符的出现次数,当出现次数大于2时l往左收缩 其余情况往右划
代码
class Solution {
public int maximumLengthSubstring(String s) {
int n = s.length();
int[] cnt = new int[26];
int ans = 1;
int l = 0;
int r = 1;
cnt[s.charAt(0)-'a']++;
while(r<n){
char c = s.charAt(r);
cnt[c-'a']++;
while(cnt[c-'a']>2&&l<r){
cnt[s.charAt(l++)-'a']--;
}
ans = Math.max(ans,r-l+1);
r++;
}
return ans;
}
}
Problem B
执行操作使数据元素之和大于等于 K
思路
贪心 最优解为先将初始值增加到一定数值,然后进行复制 贪心枚举增加次数 计算复制次数
不保证正确的证明
假设上述为错的 那在复制后一定存在一个增加的操作 但是在复制后增加一定不如在复制前增加得到的数大。
代码
class Solution {
public int minOperations(int k) {
int ans = k-1;
for(int i = 0;i<k;++i){
int temp = i+1;
int d = k%temp==0?k/temp:k/temp+1;
ans = Math.min(ans,i+d-1);
}
return ans;
}
}
Problem C
最高频率的 ID
思路
数据结构题 优先队列加延迟更新
代码
class Solution {
public long[] mostFrequentIDs(int[] nums, int[] freq) {
Map<Long,Long> map = new HashMap<>();
int n = nums.length;
PriorityQueue<Long []> q = new PriorityQueue<>(new Comparator<Long[]>(){
public int compare(Long[] a,Long[] b){
return b[0].compareTo(a[0]);
}
});
long[] ans = new long[n];
for(int i = 0;i<n;++i){
long l= nums[i];
long r = freq[i];
map.put(l,map.getOrDefault(l,0L)+r);
q.offer(new Long[]{map.get(l),l});
while(!q.isEmpty()){
Long[] temp = q.peek();
if(map.get(temp[1])!=temp[0]){
q.poll();
}
else{
break;
}
}
Long[] temp = q.peek();
ans[i] = temp[0];
}
return ans;
}
}
Problem D
最长公共后缀查询
思路
字典树板子 逆序建立wordsContainer的字典树 然后查询即可 需要更新的点是每次访问到某个节点是要比较下当前字符串和之前字符串的长度
代码
补题代码
class Trie{
private int SIZE=26;
private TrieNode root;
private String[] words;
Trie(String[] word){
root = new TrieNode();
words =word;
}
private class TrieNode{
private int num;
private TrieNode[] son;
private boolean isEnd;
private char val;
TrieNode(){
num = 0;
son = new TrieNode[SIZE];
isEnd = false;
}
}
public void insert(String str,int index){
if(str==null||str.length()==0){
return ;
}
TrieNode node = root;
char[] letters = str.toCharArray();
for(int i = str.length()-1,len =0;i>=len;--i){
int pos = letters[i]-'a';
if(node.son[pos]==null){
node.son[pos] = new TrieNode();
node.son[pos].num = index;
}
if(words[node.num].length()>words[index].length()){
node.num = index;
}
node = node.son[pos];
}
if(words[node.num].length()>words[index].length()){
node.num = index;
}
}
public int getSum(String str){
TrieNode node = root;
char[] letters = str.toCharArray();
for(int i = letters.length-1,len =0;i>=len;--i){
int pos = letters[i]-'a';
if(node.son[pos]==null){
return node.num;
}else{
node = node.son[pos];
}
}
return node.num;
}
}
class Solution {
public int[] stringIndices(String[] wordsContainer, String[] wordsQuery) {
Trie tree = new Trie(wordsContainer);
int n = wordsContainer.length;
int m = wordsQuery.length;
int[] ans = new int[m];
for(int i = 0;i<n;++i){
tree.insert(wordsContainer[i],i);
}
for(int i = 0;i<m;++i){
ans[i] = tree.getSum(wordsQuery[i]);
}
return ans;
}
}
总结
这场比上场简单,因为是伪AK所以先写了这场的题解。 学了下字典树的板子。
过往不恋 未来不迎 当下不负