【数据结构机试复习3】积水 & 用递归函数和栈操作逆序栈
2018-01-05 21:51
239 查看
EX1:积水
给定n个非负整数来表示一个高度图,这个高度图中的每一个障碍的宽度为1,请计算下雨后积水的量,积水后的高度图如下图所示:
例如,给定[0,1,0,2,1,0,1,3,2,1,2,1],输出6.
这道题应该是TA在LeetCode上找的,附上原题链接
https://leetcode.com/problems/trapping-rain-water/description/
先用left指向最左边的障碍,right指向最右边的障碍,在两者相遇之前,执行以下过程:
第1种情况:如果左边比右边低,先看左边部分
第(1)种情况,左边出现的障碍h[left]比maxLeft高,把这个障碍的高度赋给maxLeft
第(2)种情况,左边出现的障碍h[left]比maxLeft低,答案就加上(maxLeft-h[left])
left指针右移。
第2种情况:如果右边比左边低,先看右边部分
第(1)种情况,右边出现的障碍h[right]比maxRight高,把这个障碍的高度赋给maxRight
第(2)种情况,左边出现的障碍h[right]比maxRight低,答案就加上(maxRight-h[right])
right指针左移。
Note:
1、全局变量的数组范围比局部变量大,如果把int h[1000050]作为局部变量,会发生溢出。
2、积水面积的计算那里,我一开始理解不了,后来想明白了,因为我们总是处理比较“低”的那半边,
所以大胆地用这部分的最高值减去当前值就可以得到需要增加的面积,因为另外一边肯定有更高的障碍物“挡”着。
EX2:
用递归函数和栈操作逆序栈
一个栈依次压入1,2,3,4,5那么从栈顶到栈底分别为5,4,3,2,1。将这个栈转置后,从栈顶到栈底为1,2,3,4,5,也就是实现了栈中元素的逆序,请设计一个算法实现逆序栈的操作,但是只能用递归函数来实现,而不能用另外的数据结构。
给定一个栈Stack以及栈的大小top,请返回逆序后的栈。
测试样例:
输入:[1,2,3,4,5]
返回:[5,4,3,2,1]
主要就是Push这个递归函数啦
举个例子:输入的a数组如下,则top=5
递归执行过程
Push(1)--->Push(2)--->Push(3)--->Push(4)--->Push(5)--->Push(6) 执行到这一步,
因为x=6>top=5,所以return了,也就是Push(6)执行完毕。
紧接着就执行下一条语句ans.push_back(a[x]),注意上一条语句是Push(x+1),也就是说x+1=6,那么x=5,
所以这里是把a[5],也就是栈顶元素6加到了ans中。--->Push(5)执行完毕--->x+1=5,即x=4,
所以下一条语句把a[4]加入ans中。--->Push(4)执行完毕--->x+1=4,x=3,
……………
直到Push(2)执行完毕--->x+1=2,x=1,接着就把a[1]加入到ans中了。--->Push(1)执行完毕,
整个递归过程结束。
给定n个非负整数来表示一个高度图,这个高度图中的每一个障碍的宽度为1,请计算下雨后积水的量,积水后的高度图如下图所示:
例如,给定[0,1,0,2,1,0,1,3,2,1,2,1],输出6.
这道题应该是TA在LeetCode上找的,附上原题链接
https://leetcode.com/problems/trapping-rain-water/description/
#include<iostream> using namespace std; int h[1000050], n; int main() { while (cin >> n) { int ans = 0, left = 0, right = n - 1, maxLeft = -1, maxRight = -1; for (int i = 0; i < n; i++) cin >> h[i]; while (left < right) { if (h[left] < h[right]) { if (h[left] > maxLeft) maxLeft = h[left]; else ans += maxLeft - h[left]; left++; } else { if (h[right] > maxRight) maxRight = h[right]; else ans += maxRight - h[right]; right--; } } cout << ans << endl; } return 0; }学习别人的算法,非常巧妙、简单。
先用left指向最左边的障碍,right指向最右边的障碍,在两者相遇之前,执行以下过程:
第1种情况:如果左边比右边低,先看左边部分
第(1)种情况,左边出现的障碍h[left]比maxLeft高,把这个障碍的高度赋给maxLeft
第(2)种情况,左边出现的障碍h[left]比maxLeft低,答案就加上(maxLeft-h[left])
left指针右移。
第2种情况:如果右边比左边低,先看右边部分
第(1)种情况,右边出现的障碍h[right]比maxRight高,把这个障碍的高度赋给maxRight
第(2)种情况,左边出现的障碍h[right]比maxRight低,答案就加上(maxRight-h[right])
right指针左移。
Note:
1、全局变量的数组范围比局部变量大,如果把int h[1000050]作为局部变量,会发生溢出。
2、积水面积的计算那里,我一开始理解不了,后来想明白了,因为我们总是处理比较“低”的那半边,
所以大胆地用这部分的最高值减去当前值就可以得到需要增加的面积,因为另外一边肯定有更高的障碍物“挡”着。
EX2:
用递归函数和栈操作逆序栈
一个栈依次压入1,2,3,4,5那么从栈顶到栈底分别为5,4,3,2,1。将这个栈转置后,从栈顶到栈底为1,2,3,4,5,也就是实现了栈中元素的逆序,请设计一个算法实现逆序栈的操作,但是只能用递归函数来实现,而不能用另外的数据结构。
给定一个栈Stack以及栈的大小top,请返回逆序后的栈。
测试样例:
输入:[1,2,3,4,5]
返回:[5,4,3,2,1]
#include<iostream> #include <vector> using namespace std; int a[1000050], top; vector <int> ans; void Push(int x) { if (x > top) return; Push(x + 1); ans.push_back(a[x]); } int main() { while (cin >> top) { ans.clear(); for (int i = 1; i <= top; i++) cin >> a[i]; Push(1); for (int i = 0; i < top; i++) cout << ans[i]; cout << endl; } return 0; }思路:
主要就是Push这个递归函数啦
举个例子:输入的a数组如下,则top=5
下标 | 1 | 2 | 3 | 4 | 5 |
内容 | 8 | 3 | 1 | 2 | 6 |
Push(1)--->Push(2)--->Push(3)--->Push(4)--->Push(5)--->Push(6) 执行到这一步,
因为x=6>top=5,所以return了,也就是Push(6)执行完毕。
紧接着就执行下一条语句ans.push_back(a[x]),注意上一条语句是Push(x+1),也就是说x+1=6,那么x=5,
所以这里是把a[5],也就是栈顶元素6加到了ans中。--->Push(5)执行完毕--->x+1=5,即x=4,
所以下一条语句把a[4]加入ans中。--->Push(4)执行完毕--->x+1=4,x=3,
……………
直到Push(2)执行完毕--->x+1=2,x=1,接着就把a[1]加入到ans中了。--->Push(1)执行完毕,
整个递归过程结束。
相关文章推荐
- 【数据结构机试复习7】 二叉树 & 二叉树最大路径
- 【数据结构机试复习1】 字符串反转 & 字符流中第一个不重复的字符
- 【数据结构机试复习10】 求和 & 最短前缀
- 【数据结构机试复习8】 最短路径1 & 最短路径 2
- 【数据结构机试复习5】 顺时针打印矩阵 & 24点
- 【数据结构机试复习9】 二维数组中的查找 & 二分查找 & 寻找字符串
- 【数据结构机试复习6】 最长句子 & 回家过年
- 在线编程--用递归函数和栈操作逆序栈
- 数据结构复习之二叉树:遍历、搜索节点&路径、查找、与单链表互转、逐层打印
- 【留坑】 POJ2503 注意输入输出&&几种数据结构的复习、比较(线性表建立的字典 || 树建立的字典_即Trie || hash || map)
- 如何实现用递归函数和栈操作逆序栈
- 数据结构--查找&&排序(快速复习)
- 嗯,那些待我挑战的一些东西(在完成《数据结构》这本书后当做复习&提升的目录)
- 用递归函数和栈操作逆序栈(递归)
- 数据结构复习--java实现单链表基本操作
- 数据结构复习之用两个栈模拟队列操作
- 数据结构复习之单链表:基本操作及逆序打印、逆转、合并等
- 数据结构复习-线性表的定义和基本操作
- 数据结构--树状数组&&线段树--基本操作
- 用递归函数和栈操作逆序栈