单调栈 leetcode整理(一)

目录

    • 单调栈知识
    • 402. 移掉K位数字
    • 1673. 找出最具竞争力的子序列
    • 316. 去除重复字母(1081. 不同字符的最小子序列)
    • 321. 拼接最大数

单调栈知识

单调栈就是一个内部元素有序的栈(大->小 or 小->大),但是只用到它的一端。
核心代码:摘自C++ | 图解算法 | 这个单调栈不一般!

insert x
while (!sta.empty() && sta.top()<x)sta.pop()
sta.push(x)

单调栈只能在栈顶操作.
单调栈可以解决的问题:
1、找到一个序列的字典序最小的序列(序列元素位置不可移动)
2、最基础的应用就是给定一组数,针对每个数,寻找它和它右边第一个比它大的数之间有多少个数。
3、给定一序列,寻找某一子序列,使得子序列中的最小值乘以子序列的长度最大。
4、给定一序列,寻找某一子序列,使得子序列中的最小值乘以子序列所有元素和最大。

参考有关文章:
一招吃遍力扣四道题,妈妈再也不用担心我被套路啦~
单调栈的介绍以及一些基本性质
下面是刷题代码:

402. 移掉K位数字

402. 移掉K位数字

class Solution {
public:string removeKdigits(string num, int k) {vector<char> st;string result;for(int i = 0; i < num.size(); i++){while(st.size() > 0 && st.back() > num[i] && k > 0){st.pop_back();k--;}//否则,进行st.push_back(num[i]);}//考虑到所有情况之后,还有k剩余,但是此时字符是单调递减的,需要将末尾的字符进行去除while(k > 0){st.pop_back();k--;}//去除前导0int j;for(j=0; j < st.size(); j++){if(st[j] != '0') break;}for(int i = j; i < st.size() ; i++){result += st[i];}//如果最后结果为空,返回0即可if(result.size() == 0) return "0";return result;}
};

1673. 找出最具竞争力的子序列

1673. 找出最具竞争力的子序列

class Solution {
public:vector<int> mostCompetitive(vector<int>& nums, int k) {vector<int> st;int remain = nums.size() - k;for(int i = 0; i < nums.size(); i++){while(st.size() > 0 && st.back() > nums[i] && remain > 0){st.pop_back();remain--;}//否则,进行st.push_back(nums[i]);}while(remain > 0){st.pop_back();remain--;}return st;}
};

316. 去除重复字母(1081. 不同字符的最小子序列)

316. 去除重复字母
错误代码,没考虑包含text中所有不同的字符一次。
所以出现结果只是不含相同字符的字典序最小的子序列

class Solution {
public:string smallestSubsequence(string s) {vector<char > st;int hash[26]={0};for(int i = 0; i < s.size(); i++){//如果元素大于栈顶元素,并且这个元素没有出现过,则插入if(st.size() == 0 || (st.back() < s[i] && hash[s[i]-'a'] == 0)){st.push_back(s[i]);hash[s[i]-'a'] = 1;//cout << st.back() <<endl;}else{//如果这个元素小于栈顶元素,并且这个元素没有出现过,那么我们就删除栈顶元素,插入这个元素while(st.size() > 0 && s[i] < st.back() && hash[s[i]-'a'] == 0){//被删除的栈顶元素对应的hash也需要清除hash[st.back()-'a'] = 0;st.pop_back();//cout << st.back() <<endl;}st.push_back(s[i]);hash[s[i]-'a'] = 1;}//如果这个元素已经出现过了,那么不做任何操作}string result;//将vector元素转化为stringfor(int i = 0; i < st.size(); i++){result += st[i];}return result;}
};

正确代码:

class Solution {
public:string smallestSubsequence(string s) {vector<char > st;int hash[26]={0};int cnt_s[26]={0};for(int i = 0; i < s.size() ; i++){cnt_s[s[i] - 'a'] += 1;}for(int i = 0; i < s.size(); i++){cnt_s[s[i] - 'a'] -= 1;if(hash[s[i] - 'a'] == 1) continue;while(st.size() > 0){if(st.back() > s[i] && cnt_s[st.back() - 'a'] > 0){hash[st.back() - 'a'] = 0;st.pop_back();}elsebreak;}st.push_back(s[i]);hash[s[i] - 'a'] = 1;}string result;//将vector元素转化为stringfor(int i = 0; i < st.size(); i++){result += st[i];}return result;}
};

321. 拼接最大数

321. 拼接最大数
1、将k拆分为x,y,格子找nums1,nums2对应的x,y长度的最有竞争力的子序列(如果x,y大于任意数组长度,则pass这个解法)
2、对x+y=k的对应的两个子序列进行合并
3、对合并后的每个子序列,进行比较,找到最终结果.
4、补充一下比较的规则,从序列的第一个开始比较,返回对应位的较小的序列。
5、合并的规则也需要注意,并不能用简单的双指针比较,需要注意到当前数相同的情况,还要往后比较,才能选择出我们我们送入的数
哪个大取哪个,当前位置相同就继续比较下一位。这个比较的过程和比较函数有重复的操作,所以我们需要将比较函数做一下修改,保证在合并比较的时候也能使用。

compare函数从两个index开始对比,如果nums1顺位大于nums2,返回值大于0。
有个序列是另一个序列的子序列,这时我们选择较长的序列。

int compare(vector<int>& nums1,int index1, vector<int>& nums2,int index2){int n = nums1.size();int m = nums2.size();while(index1 < n && index2 < m){int difference = nums1[index1] - nums2[index2];//如果不相同,返回nums1与nums2的差值if (difference != 0) {return difference;}//如果相同,比较下一位index1++;index2++;}//如果比较到这个时候还没结果,说明有个序列是另一个序列的子序列,这时我们选择较长的序列return (n - index1) - (m - index2);}

合并函数
每次将顺位比较中较大的nums中对应的index送入result数组中。

    vector<int> merge(vector<int>& nums1, vector<int>& nums2){int x = nums1.size();int y = nums2.size();vector<int> result(x + y,0);int index1 = 0, index2 = 0;if(x == 0) return nums2;else if( y == 0) return nums1;//此时需要进行比较,从头开始比较for(int i = 0; i < x + y; i++){if(compare(nums1,index1,nums2,index2) > 0){result[i] = nums1[index1];index1++;}else{result[i] = nums2[index2];index2++;}}return result;}

最终代码:

class Solution {
private://function1:找出最具竞争力的子序列/*给你一个整数数组 nums 和一个正整数 k ,返回长度为 k 且最具 竞争力 的 nums 子序列。*/vector<int> mostCompetitive(vector<int>& nums, int k) {vector<int> st;int remain = nums.size() - k;for(int i = 0; i < nums.size(); i++){while(st.size() > 0 && st.back() < nums[i] && remain > 0){st.pop_back();remain--;}//否则,进行st.push_back(nums[i]);}while(remain > 0){st.pop_back();remain--;}return st;}vector<int> merge(vector<int>& nums1, vector<int>& nums2){int x = nums1.size();int y = nums2.size();vector<int> result(x + y,0);int index1 = 0, index2 = 0;if(x == 0) return nums2;else if( y == 0) return nums1;//此时需要进行比较,从头开始比较for(int i = 0; i < x + y; i++){if(compare(nums1,index1,nums2,index2) > 0){result[i] = nums1[index1];index1++;}else{result[i] = nums2[index2];index2++;}}return result;}int compare(vector<int>& nums1,int index1, vector<int>& nums2,int index2){int n = nums1.size();int m = nums2.size();while(index1 < n && index2 < m){int difference = nums1[index1] - nums2[index2];//如果不相同,返回nums1与nums2的差值if (difference != 0) {return difference;}//如果相同,比较下一位index1++;index2++;}//如果比较到这个时候还没结果,说明有个序列是另一个序列的子序列,这时我们选择较长的序列return (n - index1) - (m - index2);}
public:vector<int> maxNumber(vector<int>& nums1, vector<int>& nums2, int k) {int n = nums1.size();int m = nums2.size();//用来放最终结果vector<int> maxSubsequence(k,0);vector<int> cur_maxSubsequence(k,0);//【1】将k拆分为x,y,格子找nums1,nums2对应的x,y长度的最有竞争力的子序列for(int x = 0; x <= n; x++){int y = k - x;//如果x,y大于任意数组长度,则pass这个解法)if(y > m || y < 0 || x < 0 || x > n) continue;vector<int> maxSubsequence1 = mostCompetitive(nums1,x);vector<int> maxSubsequence2 = mostCompetitive(nums2,y);//【2】对x+y=k的对应的两个子序列进行合并cur_maxSubsequence = merge(maxSubsequence1,maxSubsequence2);//【3】if(compare(cur_maxSubsequence,0,maxSubsequence,0) > 0)maxSubsequence = cur_maxSubsequence;}return maxSubsequence;}
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/377583.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数字签名 那些密码技术_密码学中的数字签名

数字签名 那些密码技术A signature is usually used to bind signatory to the message. The digital signature is thus a technique that binds a person or the entity to the digital data. This binding ensures that the person sending the data is solely responsible …

七、torch.nn

一、神经网络模块 进入到PyTorch的torch.nnAPI学习页面 PyTorch提供了很多的神经网络方面的模块&#xff0c;NN就是Neural Networks的简称 二、Containers torch.nn下的Containers 一共有六个模块&#xff0c;最常用的就是Module模块&#xff0c;看解释可以知道&#xff0c…

Java多线程初学者指南(8):从线程返回数据的两种方法

本文介绍学习Java多线程中需要学习的从线程返回数据的两种方法。从线程中返回数据和向线程传递数据类似。也可以通过类成员以及回调函数来返回数据。原文链接 从线程中返回数据和向线程传递数据类似。也可以通过类成员以及回调函数来返回数据。但类成员在返回数据和传递数据时有…

【C++进阶】 遵循TDD原则,实现平面向量类(Vec2D)

目录1、明确要实现的类的方法以及成员函数2、假设已经编写Vec2D&#xff0c;根据要求&#xff0c;写出测试代码3、编写平面向量类Vec2D,并进行测试4、完整代码5、最终结果1、明确要实现的类的方法以及成员函数 考虑到效率问题&#xff0c;我们一般将函数的参数设置为引用类型。…

Keilc的中断号计算方法

中断号码 (中断向量-3)/8转载于:https://www.cnblogs.com/yuqilihualuo/p/3423634.html

md5模式 签名_MD的完整形式是什么?

md5模式 签名医师&#xff1a;医学博士/常务董事 (MD: Doctor of Medicine / Managing Director) 1)医学博士&#xff1a;医学博士 (1) MD: Doctor of Medicine) MD is an abbreviation of a Doctor of Medicine degree. In the field of Medicine, it is the main academic de…

八、卷积层

一、Conv2d torch.nn.Conv2d官网文档 torch.nn.Conv2d(in_channels, out_channels, kernel_size, stride1, padding0, dilation1, groups1, biasTrue, padding_modezeros, deviceNone, dtypeNone) 参数解释官网详情说明in_channels输入的通道数&#xff0c;如果是彩色照片通道…

HTMl5结构元素:header

页眉header 页眉将是页面加载的第一个元素&#xff0c;包含了站点的标题、logo、网站导航等。<header> <div class"container_16"> <div class"logo"> <h1><a href"index.html"><strong>Real</st…

【C++grammar】左值、右值和将亡值

目录C03的左值和右值C11的左值和右值将亡值在C03中就有相关的概念 C03的左值和右值 通俗的理解&#xff1a; (1) 能放在等号左边的是lvalue (2) 只能放在等号右边的是rvalue (3) lvalue可以作为rvalue使用 对于第三点可以举个例子&#xff1a; int x ; x 6; //x是左值&#…

scala字符串的拉链操作_在Scala中对字符串进行操作

scala字符串的拉链操作Scala字符串操作 (Scala strings operation) A string is a very important datatype in Scala. This is why there are a lot of operations that can be done on the string object. Since the regular operations like addition, subtraction is not v…

九、池化层

一、Pooling layers Pooling layers官网文档 MaxPool最大池化层下采样 MaxUnpool最大池化层上采样 AvgPool最大池化层平均采样 例如&#xff1a;池化核为(3,3)&#xff0c;输入图像为(5,5)&#xff0c;步长为1&#xff0c;不加边 最大池化就是选出在池化核为单位图像中的最大…

[分享]SharePoint移动设备解决方案

老外写的一个PPT&#xff0c;讲SharePoint在移动领域的应用&#xff0c;2012年最新的&#xff0c;有iPad哟。/Files/zhaojunqi/SharePoint2010andMobileDevices.pdf 转载于:https://www.cnblogs.com/zhaojunqi/archive/2012/04/12/2444712.html

十、非线性激活函数

一、ReLU torch.nn.ReLU(inplaceFalse)官网提供的API 其中inplace表示是否在对原始数据进行替换 由函数图可以看出&#xff0c;负数通过ReLU之后会变成0&#xff0c;正数则不发生变化 例如&#xff1a;input -1&#xff0c;若inplace True&#xff0c;表示对原始输入数据进…

最短公共子序列_最短公共超序列

最短公共子序列Problem statement: 问题陈述&#xff1a; Given two strings, you have to find the shortest common super sequence between them and print the length of the super sequence. 给定两个字符串&#xff0c;您必须找到它们之间最短的公共超级序列&#xff0c…

单调栈 leetcode整理(二)

目录为什么单调栈的时间复杂度是O(n)496. 下一个更大元素 I方法一&#xff1a;暴力方法二:单调栈哈希表739. 每日温度单调栈模版解优化503. 下一个更大元素 II单调栈循环遍历为什么单调栈的时间复杂度是O(n) 尽管for 循环里面还有while 循环&#xff0c;但是里面的while最多执…

Android中引入第三方Jar包的方法(java.lang.NoClassDefFoundError解决办法)

ZZ&#xff1a;http://www.blogjava.net/anchor110/articles/355699.html1、在工程下新建lib文件夹&#xff0c;将需要的第三方包拷贝进来。2、将引用的第三方包&#xff0c;添加进工作的build path。3、&#xff08;关键的一步&#xff09;将lib设为源文件夹。如果不设置&…

QTP自传之web常用对象

随着科技的进步&#xff0c;“下载-安装-运行”这经典的三步曲已离我们远去。web应用的高速发展&#xff0c;改变了我们的思维和生活习惯&#xff0c;同时也使web方面的自动化测试越来越重要。今天&#xff0c;介绍一下我对web对象的识别&#xff0c;为以后的对象库编程打下基础…

leetcode中使用c++需要注意的点以及各类容器的初始化、常用成员函数

目录1、传引用2、vector使用初始化方法常用成员函数3、字符串string初始化方法常用成员函数4、哈希表 unordered_map初始化常用成员函数示例&#xff1a;计数器5、哈希集合 unordered_set初始化常用成员函数6、队列 queue初始化成员函数7、栈stack初始化常用成员函数7、emplace…

Linq list 排序,Dictionary 排序

C# 对List成员排序的简单方法 http://blog.csdn.net/wanzhuan2010/article/details/6205884 LINQ之路系列博客导航 http://www.cnblogs.com/lifepoem/archive/2011/12/16/2288017.html 用一句Linq把一个集合的属性值根据条件改了&#xff0c;其他值不变 list去重 list.Where((x…

javascript Ajax 同步请求与异步请求的问题

先来看以下代码&#xff1a; var flagtrue; var index0; $.ajax({url: "http://www.baidu.com/",success: function(data){flagfalse;} }); while(flag){index; } alert(index); 请问最后alert的index的结果是多少&#xff1f; 可能有人会说0呗。实际上却没那么简单…