分为两个部分,使用小根堆+无穷的连续数,又因为小根堆无法去重,我们设置一个vis来保证不重复
优先级队列:PriorityQueue,可以建小根堆Java集合框架:优先级队列、PriorityQueue详解_良月初十♧的博客-优快云博客
class SmallestInfiniteSet {
//两个,一个连续的由idx开始的正无穷连续段;另一个是比idx小的离散集,使用小根堆
//addback:>=idx或者在小根堆中存在(vis[num]为true)不管,<idx添加到小根堆,并将vis[num]设为true
//popSmallest:判断小根堆是否为空,若不为空,poll,并将vis[smallest]设为false如果为空,返回idx,并且idx+1
//vis就是给小根堆去重
boolean[] vis=new boolean[1001];
PriorityQueue<Integer> q=new PriorityQueue<>((a,b)->a-b);
int idx=1;
public SmallestInfiniteSet() {
}
public int popSmallest() {
int ans=-1;
if(!q.isEmpty()){
ans=q.poll();
vis[ans]=false;
}else{
ans=idx++;
}
return ans;
}
public void addBack(int num) {
if(num>=idx||vis[num]){
return;
}else if(num==idx-1){
idx--;
}else{
q.add(num);
vis[num]=true;
}
}
}
/**
* Your SmallestInfiniteSet object will be instantiated and called as such:
* SmallestInfiniteSet obj = new SmallestInfiniteSet();
* int param_1 = obj.popSmallest();
* obj.addBack(num);
*/
先判断字符长度是否相等,不等返回false。然后统计每个字符出现的个数,再比较两者的出现过的现有字符是否一样,如果不一样,返回false。如果一样,直接对统计的个数进行排序,若从小到大个数相等,则返回true
class Solution {
public boolean closeStrings(String word1, String word2) {
if(word1.length()!=word2.length()){
return false;
}
int[] char_word1=new int[26];
int[] char_word2=new int[26];
for(int i=0;i<word1.length();i++){
int num1=word1.charAt(i)-'a';
int num2=word2.charAt(i)-'a';
char_word1[num1]++;
char_word2[num2]++;
}
for(int i=0;i<26;i++){
if((char_word1[i]==0&&char_word2[i]!=0)||(char_word1[i]!=0&&char_word2[i]==0)){
return false;
}
}
Arrays.sort(char_word1);
Arrays.sort(char_word2);
for(int i=0;i<26;i++){
if(char_word1[i]!=char_word2[i]){
return false;
}
}
return true;
}
}
双指针问题:
在做题过程中陷入了误区,光是想着要每次都一步到位,l要向右找到更大的和r向左找到更大的,然后比较,可以实现,而且及时找到了,也不一定是比开始的更大,也要与max进行比较,还不如简化问题,每次移动l、r中较短的。下述代码优雅和简洁。
class Solution {
public int maxArea(int[] height) {
int size=height.length;
int l=0;
int r=size-1;
//每次移动l、r中较短的
int max=0;
while(l<r){
int h=Math.min(height[l],height[r]);
int v=h*(r-l);
max=Math.max(max,v);
if(height[l]<height[r]){
l++;
}else{
r--;
}
}
return max;
}
}