AcWing 3302. 表达式求值 - AcWing
栈
该题是双指针算法与栈的应用,通过遍历一次原始字符串即可完成计算
首先创立两个栈,一个存数字,一个存符号,还要创立一个无向图存储符号的优先级
计算函数:取数字栈顶的两个数,再取符号栈顶的一个符号,根据符号来对这两个数进行计算。
遍历一次原始数组,if判断四种情况
s[i]是数字:计算这个数字串的值 x = x * 10 + s[i] - '0',再将其压入nums栈内
s[i]是左括号:直接加入符号op栈内
s[i]是右括号:遇到右括号说明必定存在左括号与其对应,我们需要先计算括号里的内容,因此这时候开始对符号进行出栈操作,直到符号栈的top是左括号为止
s[i]是符号:如果符号栈顶的符号优先级大于当前s[i]的符号,先计算s[i]之前的内容,直到栈顶的符号优先级小于当前s[i]的符号,将该符号直接进栈。如果符号栈已清空,则直接将s[i]入栈
最后计算剩下符号,将符号数组清空
详细解析:AcWing 3302. 表达式求值:多图讲解运算符优先级+详细代码注释 - AcWing
830. 单调栈 - AcWing题库
单调栈
这道题比较简单,没啥好说的,要点在于进栈和出栈的判断,当即将入栈的数大于栈顶元素,则直接入栈,即将入栈元素小于的话就while循环直到不小于栈顶元素,或者将栈清空。
此时栈顶元素就是左侧第一个小于的数。
y总说这个基本用不到,但是还是学一下。
AcWing 830. 单调栈--图解,详细注释 - AcWing
154. 滑动窗口 - AcWing题库
单调队列
用暴力应该会超时,但是我没试过。
这道题的关键在于要知道滑动窗口内两个数的关系:
以取滑动窗口最大值为例:滑动窗口内假设两个数分别为a和b,a在b的左边,即a下标小于b下标,但是b的值大于a的值,这时会发现,a永远都不可能是最大值。
以此为基础,我们新建一个队列,从下标为0开始从小到大遍历数组里面的每一个数,其中分为四种操作
1.while循环队列:当队列不为空且即将入队列的数大于队尾时,我们将队尾推出。
2.while循环结束后我们将即将入队的元素推入队尾
3.判断此时的队首是否滑出窗口:可以根据遍历数i与滑动窗口长度k来判断(这里i初始为0和1会有区别),利用i-k的关系来判断当前的窗口长度是否已经大于k,并且如果队首值恰好是滑出窗口的数,则将队首推出
4.判断是否已经形成窗口:如果形成窗口,则输出最大值
个人理解比较难的是下标和窗口的长度之间的关系,即为第三步,我们要清楚因为遍历是从小到大的,所以下标必定是将要入队列的数会大于已经入队列的数,这时就满足了滑动窗口两个数的关系的其中一个,第二个就需要我们判断了:是否即将入队列的数会大于/小于队尾的元素,如果是,则可以完全删除队尾的元素。
AcWing 154. 滑动窗口---海绵宝宝来喽 - AcWing
831. KMP字符串 - AcWing题库
KMP对于我来说太难了,早上看了两个小时只是略懂,好多不是很懂的,不瞎说了
AcWing 831. KMP字符串 - AcWing
835. Trie字符串统计 - AcWing题库
trie字符串统计,我觉得主要是两个问题,1:记录一个字符串有哪些字符。2:记录这个字符串出现的次数
1:如何记录一个字符串存在哪些字符?首先我们要明确在字符串的字符有哪些信息:下标和字母,我们需要根据下标和字符来精准的确定字符的唯一性,所以我们开辟一个二维数组t[N][26],N的意思是下标,26的意思是二十六个字母。因为下标的长度是1e5,所以是N,而字母只有26个,我们开27个也无伤大雅(算上0)。
2:如何记录这个字符串出现的次数?这就是trie数组我觉得最难的地方,trie数组是一个跟树一样的数组,它根据前一个点的值推出下一个点的信息。对于这道模板题,我们可以新开一个变量idx来进行承上启下的工作,idx是全局变量,对于idx的每次改变都是全局性的,在input函数中,我们用它赋给新点值,并把他的值作为p的下一个值(p是二维数组t的第一个参数,起到下标的作用),其实简而言之idx就是下标值,我们给每个input的字符串的每个字母赋予的下标值。最后我们cnt数组直接记录最后一个字符的下标idx出现的次数即可
我觉得我说的有点乱,但是意思就是那个意思,不如看小黄人的解析
AcWing 835. Trie树图文详解 - AcWing
昨天打训练赛去了
143. 最大异或对 - AcWing题库
这个是trie数组的例题
写了一遍,再细想一下,之前对于trie数组的理解挺多不正确的,带入了几个例子去看的话会清晰很多,所以很多时候代入法会更好理解。
上次对于idx的理解还不够深,idx是下标,每一个值对应的idx都是不同的,以上次那找集合的题为例,ab和ba,他们idx是不同的,但是abc和ab,他们的ab是相同的。
回归到这个最大异或对,首先数据范围是2^31次方,用int可以解决;其次代码其实和上一题的代码很像,思路不一样而已,这个是求最大值。
insert函数:插入函数,输入一个数,然后对于每一个位在trie数组中赋值,for循环要从30开始,因为我们后续求值是一直乘以二嵌套的。其他和上一题的insert一样
search函数:寻找最大值,对于我们输入的每一个数,都去匹配看看是否存在另一个数,使其成为异或对的最大值。由于我们是按照位数来进行计算的,所以我们要用一个sum变量来记录最后的整数值,根据输入的数x的各个位,我们根据trie数组寻找,如果这个位的否存在(!x),则可以对sum进行加一处理,并且将下标指针指向这个否值的下一个数,即为p=t[p][!x]。如果这个位不存在,则不对sum加一,并且将下标指针指向这个值的下一个数,即为p=t[p][x]。
我觉得比较关键的几点:第一因为是从30开始的,所以先匹配到的永远比后匹配到的优先级高。第二,每个t值如果存在,则其必存在前驱结点。
AcWing 143. 最大异或对---Trie详解 - AcWing