刷题总结记录

目录

目录

一、单调栈

1.1 单调栈介绍

1.2 代表题目

LeetCode496:下一个元素(进阶:LeetCode503)

LeetCode84:柱状图中的最大矩形

LeetCode739:每日温度

LeetCode85:最大矩形

LeetCode42:接雨水

LeetCode962:最大坡度

二、滑动窗口

一、单调栈

1.1 单调栈介绍

刷题笔记6(浅谈单调栈) - 知乎

单调栈的主要介绍参考以上文章,其典型应用是在数组中寻找第一个比自己大或者小的数,其经典代码如下所示:

//从数组input中寻找每个元素的下一个更大元素的坐标
vector<int> nextExceed(vector<int> &input) {
	vector<int> result (input.size(), -1);//存坐标
	stack<int> monoStack;
	for(int i = 0; i < input.size(); ++i) {	
		while(!monoStack.empty() && input[monoStack.top()] < input[i]) {
			result[monoStack.top()] = i;
			monoStack.pop();
		}
		monoStack.push(i);
	}
	return result;
}

1.2 代表题目

LeetCode496:下一个元素(进阶:LeetCode503)

题目:力扣

题目给定两个数组nums1与nums2,nums1是nums2的子集,需要找出nums1找那个元素在nums2中所在位置右侧第一个比自己大的数。此题是单调栈的简单应用:本人题解如下:

class Solution {
public:
    vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {
        int m=nums1.size(),n=nums2.size();

        unordered_map<int,int> nexBiger;//键值对分别为num2的值与其下一个更大值,初始化为-1
        for(int i=0;i<n;i++){
            nexBiger[nums2[i]]=-1;
        }
        
        stack<int> maxstack;//单调递减栈,存下一个更大的值的坐标
        for(int i=0;i<n;i++){
            while(!maxstack.empty() && nums2[i]>nums2[maxstack.top()]){
                nexBiger[nums2[maxstack.top()]]=nums2[i];//把值放到哈希表
                maxstack.pop();
            }
            maxstack.push(i);
        }
        vector<int> ans(m,-1);
        for(int i=0;i<m;i++){
            ans[i]=nexBiger[nums1[i]];
        }
        return ans;
    }
};

LeetCode84:柱状图中的最大矩形

​​​​​​力扣:只要找到数字当前元素左右两边第一个比自己小的元素,就可以得到以当前元素为高的矩形的最大宽度。因此需要用两次单调栈

题解:

class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
        //经典单调栈模型,一堆数中找到第一个比自己小/大的
        int ans=0,n=heights.size();
        stack<int> minStack;
        vector<int> right(n,n),left(n,-1);//表示第一个小的数的坐标,初始化为右边n,左边-1
        
        //右边第一个比自己小的数的坐标
        for(int i=0;i<n;i++){
            while(!minStack.empty() && heights[i]< heights[minStack.top()]){                
                right[minStack.top()]=i;                
                minStack.pop();
            }
            minStack.push(i);            
        }

        minStack=stack<int>();//重新清空栈

        //左边第一个比自己小的数的坐标
        for(int i=n-1;i>=0;i--){
            while(!minStack.empty() && heights[i]< heights[minStack.top()]){                
                left[minStack.top()]=i;                
                minStack.pop();
            }
            minStack.push(i);            
        }

        for(int i=0;i<n;i++){
            ans=max(ans,heights[i]*(right[i]-left[i]-1));
        }        
        return ans;
    }
};

LeetCode739:每日温度

LeetCode85:最大矩形

LeetCode42:接雨水

LeetCode962:最大坡度

二、滑动窗口

基本介绍:Leetcode刷题总结之滑动窗口法(尺取法) - 知乎

滑动窗口本质上是一种循环优化手段,是双指针的一种特殊情况。

以LeetCode 3 :无重复字符的最长子串 为例:力扣。其经典写法如下:

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        int n=s.size();
        int ans=0,rp=0;
        unordered_set<char> hash;
        for(int i=0;i<n;i++){       //左指针
            if(i)                   //左指针右移后需要在集合中去掉相应元素
                hash.erase(s[i-1]);
            while(rp<n && !hash.count(s[rp])){  //根据题目设置循环条件
                ans=max(ans,rp-i+1);
                hash.insert(s[rp]);
                rp++;
            }
        }
        return ans;
    }
};

LeetCode1208:尽可能是字符串相等  力扣

这题与上题基本相同,只是在初始时需要转化一下,根据题目要求使用vector记录每个位置的差值。

class Solution {
public:
    int equalSubstring(string s, string t, int maxCost) {
        int n=s.length();
        //用一个数组记录每个位置的差值绝对值
        vector<int> cost(n,0);
        for(int i=0;i<n;i++){
            cost[i]=abs(s[i]-t[i]);
        }
        //在差值满足要求的情况下使得长度最长  参考滑动窗口的代码模板
        int ans=0,right=0,sum=0;
        for(int i=0;i<n;i++){
            if(i)
                sum-=cost[i-1];
            while(right<n && sum<=maxCost){
                sum+=cost[right];
                if(sum<=maxCost){
                    ans=max(ans,right-i+1);                               
                }               
                right++;              
            }
        }
        return ans;
    }
};

LeetCode209 :长度最小的子数组 力扣

还是可以参考经典代码做修改

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int n=nums.size();
        int sum=0,ans=100001,right=0;   
        for(int i=0;i<n;i++){
            sum+=nums[i];
        }
        if(sum<target)  //判断一下特殊情况
            return 0;
        sum=0;

        //这里是要最小的满足条件的连续子数组,处理有些不一样
        for(int i=0;i<n;i++){
            if(i)
                sum-=nums[i-1];
            while(right<n && sum<target){ //条件这样设置使得可以找到第一个满足条件的子数组
                sum+=nums[right];
                if(sum>=target){                 
                    ans=min(ans,right-i+1);
                    sum-=nums[right];  //防止right出的重复计算
                    break;
                }
                right++;
            }
        }
        
        return ans;
    }
};

leetcode 1004:最大连续1的个数 力扣

直接套模板就行了

class Solution {
public:
    int longestOnes(vector<int>& nums, int k) {
        //翻译一下就是,找含有k个0的最长子数组
        int n=nums.size();
        int sum=0,right=0,ans=0;//sum表示0的个数
        for(int i=0;i<n;i++){
            if(i && nums[i-1]==0)
                sum--;
            while(right<n && sum<=k){
                if(nums[right]==0)
                    sum++;
                if(sum<=k)
                    ans=max(ans,right-i+1);
                right++;
            }
        }
        return ans;
    }
};

三、字符串

字符串介绍

字符串类型的题目很杂,啥都有

LeetCode 5 :最长回文子串5. 最长回文子串 - 力扣(LeetCode)

以下是动态规划解法

class Solution {
public:
    string longestPalindrome(string s) {
        int n=s.size();
        vector<vector<int>> dp(n,vector<int> (n)); //表示[i,j]是否为回文串
        string ans;
        for(int len=0;len<n;len++){      //len=length
            for(int i=0;i+len<n;i++){    //左边界
                int j=i+len;
                if(len==0)
                    dp[i][j]=1;     //长度为1 则必定回文
                else if(len==1)
                    dp[i][j]= (s[i]==s[j]);  //长度为2,则比较两字符是否相等
                else
                    dp[i][j]= (s[i]==s[j] && dp[i+1][j-1]);   //与头尾是否相等,前一位是否相等             
                if(dp[i][j] && len+1>ans.size()) //满足条件且长度大于现有ans,则更新答案
                    ans=s.substr(i,len+1);
            }
        }
        return ans;
    }
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值