当前位置: 首页 > article >正文

备考蓝桥杯:顺序表相关算法题


目录

询问学号

寄包柜

移动0

颜色分类

合并两个有序数组

物品移动


询问学号

我们的思路:创建一个顺序表存储从1开始依次存放进入教室的学生学号,然后查询

#include <iostream>
#include <vector>
using namespace std;
const int N = 2e6+10;//表示教室最多进入学生个数
int main()
{
  int n,m;
  cin >> n >> m;
  
  vector <int> a1(N);
  for(int i = 1;i<=n;i++)
  {
  	cin >> a1[i];//输入进入学生的学号
  }
  int t;
  for(int i = 0;i<m;i++)
  {
  	cin >> t;
  	cout << a1[t] << endl;//输出查询到的学号
  }
}

寄包柜

一共有n个柜子,每个柜子里又有ai个格子,格子里存放物品

我们需要创建一个二维数组,创建二维数组的方式有两个 一种是a[][]

一种是vector <int> a[] 由于我们这里主要是用vector解决问题,所以我们选择vector

注意:顺序表要定义在主函数外面,不然会有栈溢出的风险

#include <iostream>
#include <vector>
using namespace std;
const int N = 1e5+10;
vector<int> a[N];//这里初始化每个vector<int>的顺序表空间都是0的,所以我们后续存格子需要扩容
int main()
{
	int n,q;
	cin >> n >> q;//输入n个柜子,q次操作
	int k,i,j;//k是物品数,i是第i个柜子,j是第j个格子
	while(q--)
	{
		int op;
		cin >> op >> i >> j;
		if(op ==1)//op为1的时候进行放物品的操作,在第i个柜子第j个格子存放k个物品
		{
			cin >> k;//存放物品个数
			if(a[i].size() <= j)//由于编号是从1开始的,所以存第j个物品的话要有j+1个空间
			{
				a[i].resize(j+1);
			}
			a[i][j] = k;
		}
		else
		{
			cout << a[i][j]<< endl;
		}
	}
	return 0;
}

移动0

方法1:辅助数组

class Solution {
public:
    void moveZeroes(vector<int>& nums) {
        vector <int> nums2(nums.size());
        int j = 0;
        for(int i = 0;i<nums.size();i++)
        {
            if(nums[i] != 0)
            {
                nums2[j] = nums[i];
                j++;
            }
        }
       nums = nums2;
    }
};

方法2,双指针

这种问题就叫数组分块的问题,就是给我们一个条件,让我们把数组左边变为非0右边全变为0,或者左边大于等于某个数,右边小于某个数,这也是快速排序里比较核心的一步,我们可以定义一个cur指针:指向最后一个非零元素,定义一个i指针,扫描数组

[0,cur]永远都是非零元素,[cur+1,i-1]永远都是零元素,[i,n-1]是待扫描区域

那我们遍历顺序表,如果元素是0我们就i++,如果元素是非0那我们就把cur+1并和这个非零元素交换位置,再让i+1扫描下一个元素,最后我们就完成了数组分块操作

class Solution {
public:
    void moveZeroes(vector<int>& nums) {
        for (int i =0,cur = -1;i<nums.size();i++)
        {
            if(nums[i] !=0)
            {
                swap(nums[i],nums[++cur]);
            }
        }
    }
};

颜色分类

y

我们用sort其实也能通过

class Solution {
public:
    void sortColors(vector<int>& nums) {
       sort(nums.begin(),nums.end());
    }
};

虽然sort能通过,我们还是要学会我们三指针的方法

定义一个left 初始化为-1,i负责扫描数组,right 初始化为n

我们要达到的是数组分三块,所以我们有下面几个要求

[0,left]全为0 [left+1,i-1]全为1,[i,right-1]待扫描 [right,n-1]全为2

所以当我们扫描到的元素是2的时候,我们交换right-1和i的元素并让right--

当我们扫描到的元素是0的时候,我们交换left+1和i位置的元素并让left++,i++

当我们扫描到的元素是1的时候,直接让i++

我们脑子里可以有个动态的画面,当i扫描到0的时候,把这个0划分到0到left区间里,i交换到的一定是1或者0到i-1全是0,所以i继续扫描下一个,如果扫描到1的话直接跳过去,因为left+1到i-1的区间里都是1,如果扫描到2的话就把2划到right到n-1的区间里,那就把2和right-1换一下,right左移。一直到最后,0到left就都是0,left到right就都是1,right到n-1就都是2了

class Solution {
public:
    void sortColors(vector<int>& nums) {
       int left = -1,right =nums.size(),i=0;
       while(i<right)
       {
        if(nums[i]==1) i++;
        else if (nums[i] == 2) swap(nums[--right],nums[i]);
        else swap(nums[i++],nums[++left]);
       }
    }
};

合并两个有序数组

方法一,辅助数组

我们建一个辅助数组,然后创建三个指针 cur1 和cur2 和cur都初始化为0

cur1和cur2分别遍历数组1和数组2,比较出小的那个元素放在辅助数组里

直到有一方遍历完,这时候我们再把没遍历完的数组的元素依次拷贝到我们的辅助数组里就好了

class Solution {
public:
    void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
        vector <int> tmp(m+n);
        int cur1 =0,cur=0,cur2=0;
        while(cur1<m && cur2<n)
        {
            if(nums1[cur1] <= nums2[cur2])  tmp[cur++]=nums1[cur1++];
            else tmp[cur++]=nums2[cur2++];
        }
        while(cur1<m) tmp[cur++] = nums1[cur1++];
        while(cur2<n) tmp[cur++] = nums2[cur2++];
        for(int i = 0;i<tmp.size();i++) nums1[i] = tmp[i];
    }
    

};

方法二:原地合并

原地合并的话,我们还是定义cur,cur1,cur2,然后我们遍历数组1和数组2,如果数组1的元素比数组2的元素小的话就cur1++,cur++,如果数组2的元素小,那就把cur2下标的值给cur,cur++,cur2++,但是这种正序遍历会导致数组1原来的值被覆盖,所以我们还要改变一下策略

我们选择反向遍历,cur指向第一个数组的size的最大位置,也就是合并完的最后一个位置,cur1指向第一个数组的当前有效元素的最大位置,cur2指向数组2的最大位置

遍历数组1和数组2,把大的元素赋值给cur所在的位置

如果有一个数组遍历完了,我们要看还有没有哪个数组没遍历完,如果1数组没遍历完就不用管了,因为我们本来就是在1数组的基础上进行的原地合并,如果2数组的元素没遍历完,我们要再写一个循环把2数组的元素依次插进来

我们来实现一下代码

class Solution {
public:
    void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
        int cur = nums1.size()-1;
        int cur1 = m-1;
        int cur2 = n-1;
        while(cur1>=0 && cur2>=0)
        {
            if(nums1[cur1] >= nums2[cur2]) nums1[cur--] = nums1[cur1--];
            else nums1[cur--] = nums2[cur2--];
        }
        while(cur2>=0)
        {
            nums1[cur--] = nums2[cur2--];
        }
    }
    

物品移动

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
typedef pair<int,int> PII;
const int N = 30;
int n;
vector <int> p[N];//创建n个放木块的槽
PII find(int x)
{
	for(int i = 0;i<n;i++)
	{
		for(int j =0;j<p[i].size();j++)
		{
			if(p[i][j] == x)
			return {i,j};
	    }
	}
}
void clean(int x1,int y1)
{
	int t;
	for(int j = y1+1;j<p[x1].size();j++)
	{
		t = p[x1][j];
		p[t].push_back(t);
	}
	p[x1].resize(y1+1);
	
}
void move(int x1,int y1,int x2)//把x1,y1及其以上的木块放在x2上 
{
	for(int i = y1;i<p[x1].size();i++)
	{
		p[x2].push_back(p[x1][i]);
	}
	p[x1].resize(y1);
}
int main()
{ 
//初始化 
  cin >> n;
  string op1,op2;
  int a,b;
  for(int i =0;i<n;i++)
  {
  	p[i].push_back(i);
  }  
  while(cin >> op1 >> a >> op2 >> b)
  {
  	PII pa = find(a);
  	int x1 = pa.first,y1 = pa.second;
  	PII pb = find(b);
  	int x2 = pb.first,y2 = pb.second;
  	if(x1 == x2)
  	continue;
  	if (op1 == "move")
  	{
  		clean(x1,y1);
	  }
	if(op2 == "onto")
	  {
	  	clean(x2,y2);
	  }
	  move(x1,y1,x2);
  	
  }
  for (int i = 0;i<n;i++)
  {
  	cout << i << ":";
  	for(int j = 0;j<p[i].size();j++)
  	{
  		cout << " " << p[i][j]; 
	  }
	  cout << endl;
  }
  
  	
  }


http://www.kler.cn/a/473453.html

相关文章:

  • 接口测试-postman(使用postman测试接口笔记)
  • nodejs的降级
  • unity 播放 序列帧图片 动画
  • Elasticsearch分片数量是什么意思?
  • 分享3个国内使用正版GPT的网站【亲测有效!2025最新】
  • AnaConda下载PyTorch慢的解决办法
  • 软件工程实验-实验2 结构化分析与设计-总体设计和数据库设计
  • 数据库第一次作业-----数据库的多种部署方式
  • 代码随想录 day59 第十一章 图论part09
  • SQL Server中可以通过扩展事件来自动抓取阻塞
  • 攻防世界 ics-07
  • 51单片机——定时器中断(重点)
  • 全天候高效响应,中关村科金智能客服机器人优化客户体验
  • Hive部署内嵌模式、本地模式、远程模式
  • 现场展示deepseek VS openAI o1模型大对比
  • BI结合数据分析系统,为企业发展提供坚实的保障
  • WD5105同步降压转换器:9.2V-95V宽电压输入,4.5A大电流输出,95%高效率,多重保护功能
  • Java 注解详解:RetentionPolicy 与 ElementType
  • [Git] git pull --rebase / git rebase origin/master
  • 用VS C#构建Windows服务【纯操作版,附带项目地址】
  • python_excel列表单元格字符合并、填充、复制操作
  • 基于64QAM的载波同步和定时同步性能仿真,包括Costas环和gardner环
  • docker一键安装脚本(docker安装)
  • 基于 Python 自动化接口测试(踩坑与实践)
  • 【ROS2】从零开始使用URDF构建机器人
  • java之Collection