Leetcode42 接雨水
题目:
方法1: 求每一列的,遍历每个列,当前列只和她左边的最大值以及右边的最大值有关系,因为木桶效应。
class Solution {
public int trap(int[] height) {
//两端一定没水,因为他们
int res=0;
for(int i=1;i<height.length-1;i++){
//找左边的最大高度
int left=i-1;
int maxL=0;
while(left>=0){
maxL=Math.max(maxL,height[left--]);
}
//求右边的最大值
int maxR=0;
int right=i+1;
while(right<height.length){
maxR=Math.max(maxR,height[right++]);
}
int max=Math.min(maxR,maxL);
res=res+(max-height[i]>0?max-height[i]:0);
}
return res;
}
}
方法2:动态规划,或者说是数组预处理
class Solution {
public int trap(int[] height) {
int res=0;
//动态规划||或者叫数组初始化
//初始化左高数组 最左边和最右边的left和right值都是0,因为没有了,因为初始化就是0,所以i从1开始就额可以
int[] left=new int[height.length];
for(int i=1;i<height.length;i++){
left[i]=Math.max(height[i-1],left[i-1]);
}
//初始化右高数组
int[] right=new int[height.length];
for(int i=height.length-2;i>=0;i--){
right[i]=Math.max(right[i+1],height[i+1]);
}
for(int i=1;i<height.length-1;i++){
int temp=Math.min(left[i],right[i]);
res=res+((temp-height[i])>0?(temp-height[i]):0);
}
return res;
}
}
方法3:单调栈,单调栈就是可以on找左右的最靠近的最大值和最小值(基本作用),但是这个题不是哦,,,
class Solution {
public int trap(int[] height) {
if(height==null||height.length==0||height.length==1){
return 0;
}
int res=0;
//单调栈法,首先分析是维护单调递减栈还是单调递增栈
//这个题无论从左还是右都要维护单调递减栈
Stack<Integer> stack=new Stack();
int cur=1;
stack.push(0);
while(!stack.isEmpty()&&cur<height.length){
while(height[cur]>height[stack.peek()]){
int h=height[stack.peek()];
stack.pop();
if(stack.isEmpty()){
break;
}
res=res+(Math.min(height[stack.peek()],height[cur])-h)*(cur-stack.peek()-1);
}
stack.push(cur);
cur++;
}
return res;
}
}
Leetcode46:下一个更大元素
其实就是建立一个单调递减栈,这样遇到大的就弹,弹的时候,标记他的右最大就是遇到这个
class Solution {
public int[] nextGreaterElement(int[] nums1, int[] nums2) {
Map<Integer, Integer> map = new HashMap<>();
Deque<Integer> stack = new ArrayDeque<>();
int[] greater = new int[nums1.length];
for (int num : nums2) {
while (!stack.isEmpty() && stack.peek() < num)
map.put(stack.pop(), num);
stack.push(num);
}
while (!stack.isEmpty())
map.put(stack.pop(), -1);
for (int i = 0; i < nums1.length; i++)
greater[i] = map.get(nums1[i]);
return greater;
}
}
leetcode 503下一个最大元素2:和1 的不同就是在于循环数组的处理,其他都一样
方法1,69ms,很慢,但是我确实是on时间复杂度
class Solution {
public int[] nextGreaterElements(int[] nums) {
Map<Integer,Integer> map=new HashMap();//这个存放的是下标和对应的右边最大值
int n=nums.length;
Stack<Integer> st=new Stack();
int[] res=new int[nums.length];
for(int i=0;i<=nums.length*2-1;i++){
//构建一个单调递减的站
while(!st.isEmpty()&&nums[i%n]>nums[st.peek()]){
map.putIfAbsent(st.pop(),nums[i%n]);
}
st.push(i%n);
}
while(!st.isEmpty()){
map.putIfAbsent(st.pop(),-1);
}
for(int i=0;i<n;i++){
res[i]=map.get(i);
}
return res;
}
}
方法2:暴力法,注意越界问题
class Solution {
public int[] nextGreaterElements(int[] nums) {
//暴力法,就是从头找
int[] res=new int[nums.length];
for(int i=0;i<nums.length;i++){
int j=(i+1)%nums.length;
while(j!=i){
if(nums[j]>nums[i]){
res[i]=nums[j];
break;
}
j=(j+1)%nums.length;//这里注意
}
if(j%nums.length==i){
res[i]=-1;
}
}
return res;
}
}
leetcode739 每日温度
//原始版本,魔板套用版
class Solution {
public int[] dailyTemperatures(int[] T) {
//很简单就是维护一个单调递减栈
Stack<Integer> st=new Stack();
int[] res=new int[T.length];
int[] res1=new int[T.length];
for(int i=0;i<T.length;i++)
{
while(!st.isEmpty()&&T[i]>T[st.peek()]){
res[st.pop()]=i;
}
st.push(i);
}
while(!st.isEmpty()){
res[st.peek()]=st.pop();
}
for(int i=0;i<T.length;i++){
res1[i]=res[i]-i;
}
return res1;
}
}
魔板‘:
class Solution {
public int[] dailyTemperatures(int[] T) {
//很简单就是维护一个单调递减栈
Stack<Integer> st=new Stack();
int[] res=new int[T.length];//存放每个下标对应的左边的第一个最大值的数组
for(int i=0;i<T.length;i++)
{
//魔板话语句start
while(!st.isEmpty()&&T[i]>T[st.peek()]){
res[st.pop()]=i;
}
st.push(i);
}
while(!st.isEmpty()){
res[st.peek()]=st.pop();
}
//魔板结束,致辞已经把所有的点的第一个大于他的元素弄好了
return res1;
}
}
改进:
我不知道为什么明明少了for,为什么时间还多了?????,上面是40ms多
这个是50多ms,我也是醉了。。。
class Solution {
public int[] dailyTemperatures(int[] T) {
//很简单就是维护一个单调递减栈
Stack<Integer> st=new Stack();
int[] res=new int[T.length];
for(int i=0;i<T.length;i++)
{
while(!st.isEmpty()&&T[i]>T[st.peek()]){
res[st.peek()]=i-st.peek();
st.pop();
}
st.push(i);
}
return res;
}
}