- 字符串解码
遍历整个数组
数字我直接整体拿到放入数字栈
非]字符我直接入字符栈
]字符我需要拿到字符串,然后拿数字,组合后放入字符栈
最后将栈中元素拼接即可
注意:]字符我需要拿到字符串,时,可以用list,然后调用reverse方法
将list转化为String,可以使用String.join("",list)
java
class Solution {
public String decodeString(String s) {
Deque<String> strStack = new ArrayDeque<>();
Deque<Integer> numStack = new ArrayDeque<>();
for (int i = 0; i < s.length(); i++) {
int num = 0;
while (Character.isDigit(s.charAt(i))) {
num = num * 10 + s.charAt(i) - '0';
i++;
}
if (num != 0)
numStack.offerLast(num);
if (s.charAt(i) != ']') {
strStack.offerLast(s.charAt(i) + "");
} else {
List<String> list=new ArrayList<>(s.length());
while (!strStack.peekLast().equals("[")) {
list.add(strStack.pollLast());
}
Collections.reverse(list);
String str=String.join("",list);
strStack.pollLast();
StringBuilder sb = new StringBuilder();
int cnt = numStack.pollLast();
for (int j = 1; j <= cnt; j++) {
sb.append(str);
}
strStack.offerLast(sb.toString());
}
}
return String.join("",strStack);
}
}
- 每日温度
单调栈,单调递减
java
class Solution {
public int[] dailyTemperatures(int[] temperatures) {
int[] res=new int[temperatures.length];
Deque<Integer> stack=new ArrayDeque<>();
for(int i=0;i<temperatures.length;i++){
while(!stack.isEmpty()&&temperatures[stack.peekLast()]<temperatures[i]){
int index=stack.pollLast();
res[index]=i-index;
}
stack.offerLast(i);
}
return res;
}
}
- 柱状图中最大的矩形
单调栈,维护一个最大栈,每次进来元素,他的left就是栈顶或者-1(栈为空,说明他是前面都比他大),注意right要初始化为n,因为可能不出栈(比如从小到大),此时right的值为0是不对的
java
class Solution {
public int largestRectangleArea(int[] heights) {
int[] left=new int[heights.length];
int[] right=new int[heights.length];
int result=0;
Arrays.fill(right,heights.length);
Deque<Integer> stack=new ArrayDeque<>();
for(int i=0;i<heights.length;i++){
while(!stack.isEmpty()&&heights[stack.peekLast()]>heights[i]){
int index=stack.pollLast();
right[index]=i;
}
if(!stack.isEmpty()) left[i]=stack.peekLast();
else left[i]=-1;
stack.offerLast(i);
}
for(int i=0;i<heights.length;i++){
result=Math.max(result,(right[i]-left[i]-1)*heights[i]);
}
return result;
}
}
- 数组中第K个最大元素
经典快排+选择
java
class Solution {
public int findKthLargest(int[] nums, int k) {
kp(nums,nums.length-k,0,nums.length-1);
return nums[nums.length-k];
}
public void kp(int[] nums,int target,int l,int r){
if(l>=r) return ;
int mid=l+(r-l)/2;
int num=nums[mid];
int start=l-1,end=r+1;
while(start<end){
while(nums[++start]<num) ;
while(nums[--end]>num) ;
if(end<=start) break;
int temp=nums[start];
nums[start]=nums[end];
nums[end]=temp;
}
if(target>end) kp(nums,target,end+1,r);
else kp(nums,target,l,end);
}
}
- 前K个高频元素
还是快排+选择思路
注意最后的结束条件
java
class Solution {
public int[] topKFrequent(int[] nums, int k) {
Map<Integer,Integer> map=new HashMap<>();
List<int[]> list=new ArrayList<>();
for(int num:nums) map.put(num,map.getOrDefault(num,0)+1);
map.forEach((ks,v)->{
list.add(new int[]{v,ks});
});
kp(list,k,0,list.size()-1);
int[] result=new int[k];
for(int i=0;i<k;i++) result[i]=list.get(i)[1];
return result;
}
public void kp(List<int[]> list,int k,int start,int end){
int mid=start+(end-start)/2;
int num=list.get(mid)[0];
int l=start-1,r=end+1;
while(r>l){
while(list.get(++l)[0]>num) ;
while(list.get(--r)[0]<num) ;
if(l>=r) break;
Collections.swap(list,l,r);
}
if(r==k-1) return ;
if(r>k-1) kp(list,k,start,r);
else kp(list,k,r+1,end);
}
}
- 数据流的中位数
记住:
先放min,再min放max,最后平衡
返回:如果前面size大,返回min,否则返回(min+max)/2
java
class MedianFinder {
PriorityQueue<Integer> min;
PriorityQueue<Integer> max;
public MedianFinder() {
min =new PriorityQueue<>((a,b)->b-a);
max=new PriorityQueue<>();
}
public void addNum(int num) {
min.offer(num);
max.offer(min.poll());
if(min.size()<max.size()) min.offer(max.poll());
}
public double findMedian() {
if(min.size()>max.size()) return min.peek();
else return (min.peek()+max.peek())/2.0;
}
}
- 买卖股票的最佳时机
贪心思想:
当我遇到比当前最小值小的值,我在之后卖出能挣的一定多
当我遇到大于最小值的值,我计算利润,更新最大利润
java
class Solution {
public int maxProfit(int[] prices) {
int min=prices[0],res=0;
for(int i=1;i<prices.length;i++){
if(prices[i]<min) min=prices[i];
else{
res=Math.max(res,prices[i]-min);
}
}
return res;
}
}
- 跳跃游戏
更新当前能到的最远位置,如果大于等于n-1,返回true
如果当前i大于最远位置,返回false
java
class Solution {
public boolean canJump(int[] nums) {
int maxLen=0;
for(int i=0;i<nums.length;i++){
if(i<=maxLen){
maxLen=Math.max(maxLen,i+nums[i]);
if(maxLen>=nums.length-1) return true;
}
else return false;
}
return true;
}
}
- 跳跃游戏II
每次都要跟新下一次的最长位置,当走出当前最长位置,我们需要step++,更新nowLen(此时nowLen就是上个区间能到达的最大位置)
注意:走出一定要先更新nowLen(用的是上个区间的),然后更新maxLen
java
class Solution {
public int jump(int[] nums) {
int nowLen=0;
int maxLen=0;
int step=0;
for(int i=0;i<nums.length;i++){
if(i>nowLen){
step++;
nowLen=maxLen;
}
maxLen=Math.max(maxLen,i+nums[i]);
}
return step;
}
}
- 划分字母区间
存储每个字母最后出现的位置(可以用数组存)
每次更新区间尾部,如果区间尾部等于我当前索引,说明我就是结束点
存入长度,更新起点
java
class Solution {
public List<Integer> partitionLabels(String s) {
List<Integer> list=new ArrayList<>();
Map<Character,Integer> map=new HashMap<>();
for(int i=0;i<s.length();i++){
map.put(s.charAt(i),i);
}
int l=0,r=0;
for(int i=0;i<s.length();i++){
r=Math.max(map.get(s.charAt(i)),r);
if(i==r){
list.add(r-l+1);
l=i+1;
}
}
return list;
}
}