20240410
1.接雨水
方法一,动态规划,时间复杂度O(n^2),空间复杂度O(n)
public int trap(int[] height) { int n=height.length; if(n==0){ return 0; } int[] leftMax=new int[n]; leftMax[0]=height[0]; for(int i=1;i<n;++i){ leftMax[i]=Math.max(leftMax[i-1],height[i]); } int[] rightMax=new int[n]; rightMax[n-1]=height[n-1]; for(int i=n-2;i>=0;--i){ rightMax[i]=Math.max(rightMax[i+1],height[i]); } int ans=0; for(int i=0;i<n;++i){ ans+=Math.min(leftMax[i],rightMax[i])-height[i]; } return ans; }
方法二、栈
时间复杂度O(n),空间复杂度O(n)
public int trap(int[] height) { int ans=0; Deque<Integer> stack=new LinkedList<Integer>(); int n=height.length; for(int i=0;i<n;++i){ while(!stack.isEmpty()&&height[i]>height[stack.peek()]){ int top=stack.pop(); if(stack.isEmpty()){ break; } int left=stack.peek(); int currWidth=i-left-1; int currHeight=Math.min(height[left],height[i])-height[top]; ans+=currWidth*currHeight; } stack.push(i); } return ans; }
方法三.双指针法
时间复杂度O(n),空间复杂度O(1)
public int trap(int[] height) { int ans=0; int left=0,right=height.length-1; int leftMax=0,rightMax=0; while(left<right){ leftMax=Math.max(leftMax,height[left]); rightMax=Math.max(rightMax,height[right]); if(height[left]<height[right]){ ans+=leftMax-height[left]; ++left; }else{ ans+=rightMax-height[right]; --right; } } return ans; }
20240411
滑动窗口
1.无重复字符的最长子串
public int lengthOfLongestSubstring(String s) { Set<Character> occ=new HashSet<Character>(); int n=s.length(); int rk=-1,ans=0; for(int i=0;i<n;i++){ if(i!=0){ occ.remove(s.charAt(i-1)); } while(rk+1<n&&!occ.contains(s.charAt(rk+1))){ occ.add(s.charAt(rk+1)); ++rk; } ans=Math.max(ans,rk-i+1); } return ans; }
时间复杂度O(n),感觉有点累死字符串匹配算法
2.找到字符串中所有字母异味词
public List<Integer> findAnagrams(String s, String p) { int sLen=s.length(),pLen=p.length(); if(sLen<pLen){ return new ArrayList<Integer>(); } List<Integer> ans=new ArrayList<Integer>(); int[] sCount=new int[26]; int[] pCount=new int[26]; for(int i=0;i<pLen;++i){ ++sCount[s.charAt(i)-'a']; ++pCount[p.charAt(i)-'a']; } if(int i=0;i<sLen-pLen;++i){ --sCount[s.charAt(i)-'a']; ++sCount[s.charAt(i+pLen)-'a']; if(Arrays.equals(sCount,pCount)){ ans.add(i+1); } } return ans; }
int sLen=s.length();
int pLen=p.length();
if(sLen<pLen){
return ans;
}
//建立两个数组存放字符串中字母出现的词频,并以此作为标准比较
int [] scount=new int[26];
int [] pcount=new int[26];
//当滑动窗口的首位在s[0]处时 (相当于放置滑动窗口进入数组)
for(int i=0;i<pLen;i++){
++scount[s.charAt(i)-'a'];
//记录s中前pLen个字母的词频
++pcount[p.charAt(i)-'a'];
//记录要寻找的字符串中每个字母的词频(只用进行一次来确定)
}
//判断放置处是否有异位词 (在放置时只需判断一次)
if(Arrays.equals(scount,pcount)){ ans.add(0); }
//开始让窗口进行滑动
for(int i=0;i<sLen-pLen;i++){
//i是滑动前的首位
--scount[s.charAt(i) -'a'];
//将滑动前首位的词频删去
++scount[s.charAt(i+pLen) -'a'];
//增加滑动后最后一位的词频(以此达到滑动的效果)
//判断滑动后处,是否有异位词
if(Arrays.equals(scount,pcount)){
ans.add(i+1);
}
}
return ans;
}
560.和为K的子数组
前缀和+哈希表优化
public int subarraySum(int[] nums, int k) {
int count=0,pre=0;
HashMap<Integer,Integer> mp=new HashMap<>();
mp.put(0,1);
for(int i=0;i<nums.length;i++){
pre+=nums[i];
if(mp.containsKey(pre-k)){
count+=mp.get(pre-k);
}
mp.put(pre,mp.getOrDefault(pre,0)+1);
}
return count;
}
20240412
239.滑动窗口最大值
https://leetcode.cn/problems/sliding-window-maximum/description/?envType=study-plan-v2&envId=top-100-liked
1.优先队列
public int[] maxSlidingWindow(int[] nums, int k) { int n=nums.length; PriorityQueue<int[]> pq = new PriorityQueue<int[]>(new Comparator<int[]>() { public int compare(int[] pair1, int[] pair2) { return pair1[0] != pair2[0] ? pair2[0] - pair1[0] : pair2[1] - pair1[1]; } }); for(int i=0;i<k;++i){ pq.offer(new int[]{nums[i],i}); } int[] ans=new int[n-k+1]; ans[0]=pq.peek()[0]; for(int i=k;i<n;++i){ pq.offer(new int[]{nums[i],i}); while(pq.peek()[1]<=i-k){ pq.poll(); } ans[i-k+1]=pq.peek()[0]; } return ans; }
2.单调队列
class MyQueue{ Deque<Integer> deque=new LinkedList<Integer>(); void poll(int val){ if(!deque.isEmpty()&&val==deque.peek()){ deque.poll(); } } void add(int val){ while(!deque.isEmpty()&&val>deque.getLast()){ deque.removeLast(); } deque.add(val); } int peek(){ return deque.peek(); } } public class TwoNum { public int[] maxSlidingWindow(int[] nums,int k){ if(nums.length==1){ return nums; } int len= nums.length-k+1; int[] res=new int[len]; int num=0; MyQueue myQueue=new MyQueue(); for(int i=0;i<k;i++){ myQueue.add(nums[i]); } res[num++]= myQueue.peek(); for(int i=k;i<nums.length;i++){ myQueue.poll(nums[i-k]); myQueue.add(nums[i]); res[num++]=myQueue.peek(); } return res; } }