【洛谷】The Blocks Problem、合并两个有序数组,补充pair(vector相关算法题p2)

发布于:2025-07-22 ⋅ 阅读:(9) ⋅ 点赞:(0)


88.合并两个有序数组

题目描述

在这里插入图片描述

题目解析

这道题有两个思路,一个是开辟一个m+n大小的数组然后遍历两个原数组按大小顺序尾插到新数组中,尾插完后再将新数组的值拷贝回原数组,但是这道题已经在第一个数组里为我们开好空间了,所以我们直接在原数组里操作就行了,思路是分别从两个数组的尾部开始遍历,因为从前遍历会发生数据的覆盖,跳出while循环后若是第二个数组还剩余,就将第二个数组中的数据拷贝到一数组。

代码

class Solution {
public:
    void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
        int mcur = m - 1;
        int ncur = n - 1;
        int rcur = m + n - 1;
        while(mcur >= 0 && ncur >= 0)
        {
            if(nums1[mcur] > nums2[ncur])
            {
                nums1[rcur--] = nums1[mcur--];
            }
            else 
            {
                nums1[rcur--] = nums2[ncur--];
            }
        }
        
        while(ncur >= 0)
        {
            nums1[rcur--] = nums2[ncur--];
        }
    }
};

UVA101 The Blocks Problem

题目描述

在这里插入图片描述

题目解析

这道题会用到pair,所以小编先介绍一下什么是pair,原理不用深究,知道怎么用就行了。

在这里插入图片描述

这道题先理解题意,我们以样例来解释,一共有10个位置,每个位置有一个木块。我们可以把每个位置理解成一个槽,每个槽装着木块,经过一系列操作后每个槽有可能没有木块,也有可能有多个木块垒在一起,示意图如下:

在这里插入图片描述

所以我们需要一个二维数组来存储数据,一维代表槽,二维代表槽中的木块,题目中说最多有25个木块也就是起始最多有25个槽,所以我们创建30个数组妥妥够了。
这道题看似有四个操作,其实总结就是两个,归位和移动,四个操作都有移动,所以我们每次循环都要移动,无非就是判断是否归位,我们分析题目知道当第一个单词为move需要将a上方木块归位,第二个单词为onto需要将b上方木块归位,所以我们需要写两个函数,归位clear和移动move,归位需要遍历a木块上方的所有木块,把木块尾插到木块初始的槽,木块本身的数值就是它其实槽的编号,move就是将a木块上方的木块及a木块全部尾插到b木块所在的槽。
而我们要执行上述两个操作首先需要先找到a b目标木块在哪,所以首先需要写一个find函数,这里find的返回值就需要用到pair,返回木块在哪个槽和在槽的哪个位置,需要注意题目要求当a与b在同一个槽是无需操作,所以我们在循环里需要加上这个判断,若为真就跳过当次循环。
而循环的设置也很有讲究,首先cin一个n读取木块数目,然后后续输入就一直都是 字符串 数字字符串数字的格式了,所以我们可以while(cin >> op1 >> a >> op2 >> b),当最后输入quit时由于不匹配就会跳出循环。
最后还需要依次打印结果。

代码

using namespace std;
#include <iostream>
#include <vector>

const int N = 30;
vector<int> v[N];
int n;

string op1, op2;
int a, b;
typedef pair<int, int> pii;

pii find(int x)
{
	for (int i = 0; i < N; i++)
	{
		for (int j = 0; j < v[i].size(); j++)
		{
			if (v[i][j] == x)
			{
				return { i,j };
			}
		}
	}
}

void clear(int x1, int y1)
{
	//遍历a木块上方所有木块
	for (int i = y1 + 1; i < v[x1].size(); i++)
	{
		//pos是待归位木块在那个槽,也就是木块本身的值是多少
		int pos = v[x1][i];
		v[pos].push_back(pos);
	}
	//并没有真的移除数据,需要resize
	v[x1].resize(y1 + 1);
}

void move(int x1, int y1, int x2)
{
	//遍历目标木块及目标木块上方所有木块
	for (int i = y1; i < v[x1].size(); i++)
	{
		//将目标木块尾插到b木块所在位置
		v[x2].push_back(v[x1][i]);
	}
	v[x1].resize(y1);
}

int main()
{
	cin >> n;
	//初始化vector
	for (int i = 0; i < n; i++)
	{
		v[i].push_back(i);
	}

	while (cin >> op1 >> a >> op2 >> b)
	{
		//先找到a,b的位置
		pii p1 = find(a);
		int x1 = p1.first, y1 = p1.second;
		pii p2 = find(b);
		int x2 = p2.first, y2 = p2.second;

		//a与b在同一堆无需处理
		if (x1 == x2)
			continue;

		if (op1 == "move")
		{
			clear(x1,y1);
		}

		if (op2 == "onto")
		{
			clear(x2, y2);
		}

		move(x1, y1, x2);
	}

	for (int i = 0; i < n; i++)
	{
		cout << i << ':';
		for (int j = 0; j < v[i].size(); j++)
		{
			cout << " " << v[i][j];
		}
		cout << endl;
	}
	return 0;
}

网站公告

今日签到

点亮在社区的每一天
去签到