【洛谷】询问学号、寄包柜、移动零、颜色分类(vector相关算法题p1)
文章目录
- P3156询问学号
- 题目描述
- 解题思路
- 代码
- P3613寄包柜
- 题目描述
- 题目解析
- 代码
- 283.移动零
- 题目描述
- 题目解析
- 代码
- 75.颜色分类
- 题目描述
- 题目解析
- 代码
P3156询问学号
题目描述
解题思路
这道题很简单,用一个数组来接受第二行输入的所有学号,然后用第三行输入数据作为数组的下标,返回数组中下标对应的数字就行了。
注意因为第三行的数字代表数组中的第几个数,比如1是代表数组的第一个数,也就是0所对应的下标,我们要把第三行输入的数字和数组下标对应,所以第二输入的数据要从数组第二个下标也就是vector[1]开始接受输入的数据。
2e6+10是代表科学计数法,2e6等于2+10^6,相当于2000000,再加10等于2000010。
代码
using namespace std;
#include <iostream>
#include <vector>int main()
{const int N = 2e6 + 10;int m, n;vector<int> v(N);cin >> n >> m;for (int i = 1; i <= n; i++){cin >> v[i];}while (m--){int x;cin >> x;cout << v[x] << endl;}return 0;
}
P3613寄包柜
题目描述
题目解析
题目描述有n个柜子,每个柜子有ai个格子,每个格子里存放一个数字,这里我们要维护这些数字就需要创建一个二维数组,而我们用c语言的二维数组
int a[][]势必会超出内存,10^5 * 10^5 *4比题目内存限制128MB大得多,所以我们最好用vector,而且这道题我们无法知道有多少个柜子,所以无法动态调整数组第一维的大小,所以无法用vector<vector<int>>,这道题用vector<int>a[]很合适,类似于inta[],开题目要求是最大柜子数个数组,这样数组第一维的大小就固定了,第二维大小根据放数据情况自由改变,若放进柜子的格子数比当前二维数组size大,就扩容到size+1就行了。但是这里的vector最好不要在main函数里面开辟,虽然单个vector占用空间不大,但是我们这里数据太大了,还是很有可能栈溢出,所以最好在全局区开辟把它存到静态区。
这道题思路也很简单,第一行输入的查询次数q就是接下来我们while循环的次数,每次while循环处理一行数据,然后循环内部用判断语句以op的值来判断是存数据还是取数据,如果是存数据还需要再cin一个数据。存数据时存的格子我们可能还没开空间,所以用resize来开空间,开j+1个够存当前数据就行了,取数据时题目规定是合法取的,一定取的是我们存过数据的格子,所以取数据时不用开空间了。
代码
using namespace std;
#include <iostream>
#include <vector>const int N = 1e5 + 10;
vector<int> a[N]; //类似于int a[]int main()
{int n, q;cin >> n >> q;while (q--){int op, i, j, k = 0;cin >> op >> i >> j;if (op == 1) //放数据{cin >> k;if (a[i].size() <= j) //扩容{a[i].resize(j + 1);}a[i][j] = k;}else //拿数据{cout << a[i][j] << endl;}}return 0;
}
283.移动零
题目描述
题目解析
这道题是典型的双指针,一个指针i从头到尾扫描数组,一个指针cur永远指向最后一个非零元素,一开始把cur置为-1。
这道题的思路的数组分块,将一个数组分为非0和0两块,以指针角度来看把数组分为三块,示意图如下:
当i遇到0时,直接i++,这样0就在我们预定的分组区域中了,当i遇到非0数据时,先将cur++,这样cur就指向了0所在区域,(当然也可能i还没遇到0,那么cur就指向了i,接下来的交换操作就是自己和自己换,相当于无事发生,i继续++)将i指向的数据和cur指向的数据交换,然后i++,那么非零数据就被交换到了非零元素的最后一个位置,0也被交换到了0区域的最后一个位置。
代码
class Solution {
public:void moveZeroes(vector<int>& nums) {int cur = -1; //指向已扫描的最后一个非零元素int i = 0; //从头开始扫描数组的指针for (i = 0; i != nums.size(); i++){//若遇到0直接i++,不进ifif (nums[i] != 0){//遇到非零数据swap(nums[++cur], nums[i]);}}}
};
75.颜色分类
题目描述
题目解析
这道题也是数组分块,只不过上一题是分两块,这里是分三块,当然双指针就不够用了,我们这里需要三个指针,还是需要一个i来遍历数组,一个left指向0的最后一个数组,一个right指向2的第一个数据,这样1就在left、right指针之间了,下面是示意图:
一开始left指向-1,right指向nums.size(),i从0开始遍历数组,当遇到2时先right–,然后把i指向的数据和right指向的数据交换,注意交换完后i不能++,因为目前i指向的数据是从待扫描区域交换过来的,它的值是多少还不清楚,所以还需要再经过一轮循环判断。当i遇到0时先left++,然后把i指向的数据和left指向的数据交换,因为交换过来的值是确定的,所以直接i++遍历下一个数据,当i遇到1时直接i++后1就在i的左边到它应该在的位置了。循环的结束条件是i < right,因为i等于right就意味着i已经将数组全部扫描一遍了。
代码
class Solution {
public:void sortColors(vector<int>& nums) {int i = 0;int left = -1;int right = nums.size();while(i < right){if(nums[i] == 0){swap(nums[++left], nums[i]);i++;}else if(nums[i] == 2){swap(nums[--right], nums[i]);}else{i++;}}}
};
以上就是小编分享的全部内容了,如果觉得不错还请留下免费的关注和收藏
如果有建议欢迎通过评论区或私信留言,感谢您的大力支持。
一键三连好运连连哦~~