Problem A - 移除字母异位词后的结果数组
思路
按照题目意思模拟,实现判断是否是异位词的函数,用两个长度26的数组统计。
代码
class Solution {
public List<String> removeAnagrams(String[] words) {
List<String> res = new ArrayList<>();
String last = words[0];
res.add(last);
int n = words.length;
for(int i=1;i<n;i++){
if(!isAnagram(last,words[i])){
res.add(words[i]);
last = words[i];
}
}
return res;
}
private boolean isAnagram(String s, String t) {
if(s.length() != t.length())
return false;
int[] alpha = new int[26];
for(int i = 0; i< s.length(); i++) {
alpha[s.charAt(i) - 'a'] ++;
alpha[t.charAt(i) - 'a'] --;
}
for(int i=0;i<26;i++)
if(alpha[i] != 0)
return false;
return true;
}
}
Problem B - 不含特殊楼层的最大连续楼层数
思路
思路1、遍历special,维护一个begin和ans
思路2、
把 bottom - 1 和 top + 1 也看作特殊楼层加入 special 中,然后将 special 排序。答案就是 special 中相邻元素之差的最大值减一。
作者:TsReaper
链接:https://leetcode.cn/circle/discuss/sKLBSg/
代码
思路1
class Solution {
public int maxConsecutive(int bottom, int top, int[] special) {
int res = 0;
int begin=bottom;
Arrays.sort(special);
for(int s:special){
if(s!=begin && begin<=top){
res = Math.max(res,s-begin);
}
begin = s+1;
}
if(begin<=top){
res = Math.max(res,top-begin+1);
}
return res;
}
}
思路2
public int maxConsecutive(int bottom, int top, int[] special) {
int n = special.length;
int[] s = new int[n+2];
for(int i=0;i<n;i++){
s[i] = special[i];
}
s[n] = bottom-1;
s[n+1] = top+1;
Arrays.sort(s);
int ans = 0;
for(int i=1;i<n+2;i++){
ans = Math.max(ans,s[i]-s[i-1]-1);
}
return ans;
}
Problem C - 按位与结果大于零的最长组合
思路
自己没想到,统计32位每一位1的总数,哪一位的总数最大就是最长的组合。
代码
class Solution {
public int largestCombination(int[] candidates) {
int[] res = new int[32];
for (int c : candidates) {
for (int i = 0; i < 32; i++) {
if ((c & (1 << i)) != 0) {
res[i]++;
}
}
}
int ret = 0;
for(int i=0;i<32;i++){
ret = Math.max(ret,res[i]);
}
return ret;
}
}
不用辅助数组:
public int largestCombination(int[] candidates) {
//30位 >10^9
int ans = 0;
for(int i=0;i<30;i++){
int oneCount = 0;
for(int c:candidates){
if((c & (1<<i)) != 0){
oneCount++;
}
}
ans = Math.max(ans,oneCount); //第i位的1的个数
}
return ans;
}
Problem D - 统计区间中的整数数目
解法
使用
floorEntry()方法和ceilingEntry()方法相对,找到第一个小于或等于指定key的Map.Entry
想到要使用logn的查找方法去区间合并,但是没有想清楚如何合并
对JAVA的一些api的掌握不够熟练,
循环找可以合并的区间
找到小于right的第一个left然后开始合并,合并的时候修改count,并且移除旧区间,
同时更新合并后的区间,最后再更新count,加入新区间
例:
第一次合并
第二次合并
代码
class CountIntervals {
private TreeMap<Integer,int[]> intervals;
private int count;
public CountIntervals() {
//按照right排序
intervals = new TreeMap<>();
count = 0;
}
public void add(int left, int right) {
int L = left, R=right;
Map.Entry<Integer,int[]> tmp = intervals.floorEntry(right);
while(tmp!=null && tmp.getValue()[1]>=L){
L = Math.min(L,tmp.getValue()[0]);
R = Math.max(R,tmp.getValue()[1]);
//合并区间 减去原来的区间
count -= (tmp.getValue()[1]-tmp.getValue()[0]+1); //更新count
intervals.remove(tmp.getKey()); //更新treemap
tmp = intervals.floorEntry(right);
}
count += (R-L+1);
intervals.put(L,new int[]{L,R});
}
public int count() {
return count;
}
}