算法竞赛小白进阶之路---关于动态顺序表vector的运用的几道算法题目

69 阅读7分钟

1.颜色分类

针对于这个75. 颜色分类 - 力扣(LeetCode)

颜色分类的问题,其实运用的也是我们的这个数组元素分块的这个思想,分成了不同的块,在这个需要扫描的区域上面去进行处理,放到我们的这个对应的区域上面去;

下面的这个图来自于比特算法竞赛课程的板书,非常详细的展示了这个不同的分类讨论的情况

image-20250718201349282

下面的这个是我们的代码,针对于这个不同的分类情况进行处理;

我也是在这个地方发现了一个细节,和上面的这个图示里面不一样的地方,就是我们的这个代码里面进行交换的时候,比如这个right-1和i位置进行交换,在这个代码里面我们可以直接写作这个++left,这样就和我们交换之后的这个指针移动的这个步骤合并了;

然后这个left+1和这个i位置进行交换也是一样的这个道理,我们本来是直接和这个right-1位置的下标进行交换的,然后这个right--,这个时候我们的代码里面也是直接进行了合并;

image-20250718202350875

2.有序数组的合并

这个题目的链接在这个地方:88. 合并两个有序数组 - 力扣(LeetCode)

第一个做法就是辅助数组,进行两个数组的比较,小的放到我们的这个指定的辅助数组里面去;

数组元素都需要放到这个第一个数组里面去,因此我们的这个辅助数组里面的元素需要放置到这个第一个数组里面去;

image-20250718204204639

1)下面的这个里面的第一个解法就是借助我们的辅助数组,这个时候就是从前向后挨个进行比较即可,小的就往我们的这个辅助数组里面直接进行放置,然后我们把这个辅助数组最后直接复制到我们的这个num1里面去即可,因为这个题目的要求就是放到这个num11里面去,而且这个num1数组里面是存在着这个足够大小的这个空间的;

class Solution 
{
public:
    void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) 
    {
        // 解法一:利用辅助数组
        vector<int> tmp(m + n);

        int cur = 0, cur1 = 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 < n + m; i++) nums1[i] = tmp[i];
    }
};


class Solution 
{
public:
    void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) 
    {
        // 解法二:原地合并
        int cur1 = m - 1, cur2 = n - 1, cur = m + 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--];
    }
};

2)上面的这个第二个解法就是原地进行合并,这个是从后向前进行合并的;

为什么是从后向前,因为如果是从前向后,这个比较过程当中在原地转移的时候就会涉及到这个覆盖的情况,类似于我们的这个顺序表里面插入数据之后,其他的位置应该如何进行移动的这个情况,如果移动的这个方式不对,这个原始的数据就会出现被合并的这个情况,因此这个也是需要我们去进行处理的;

从后向前遍历进行比较,因为这个num1数组里面的元素后面是空的,因此我们把这个大数据都放到这个num1后面即可,最后如果出现了没有完全比较完成的情况,我们有需要分情况进行分析;

如果是这个num1里面存在着这个剩余的元素,也就是我们的cur1是大于等于0的,因此这个时候直接不做任何的操作就可以了;

但是如果我们的这个Num2里面存在着这个剩余的元素,这个时候我们需要直接移动过去几个,因为我们的两个数组本来就是有序存放的;

3.关于pair的补充

下面的这个图片来自于比特算法竞赛课程的板书:

我们可以把这个pair按照结构体进行理解,里面有两个成员,定义结构体的变量,存放不同的数据类型,在我们的算法竞赛里面还是比较常用的;

为什么在这个地方需要补充这个pair,是因为我们在下面的这个题目里面会使用到,下面的这个题目是一个

4.英文题目

我在自己的这个学习的过程当中,是很少遇到这种这个英文的题目的,可能在这个atcoder上面做过几次这种英文题目把,后面觉得这个题目太难了,也就放弃了;

在这个洛谷上面,我也是第一次遇到这个对应的英文算法题目,和这个ACM可能都是比较像的把;

这个题目涉及到的这个具体的场景还是非常的复杂的,因此这个代码还是比较复杂的,而且这个出现的情况也很多,因此这个需要我们去进行这个分类;

image-20250718212910772

在这个问题里面具体是如何使用上面介绍的这个pair的就是我们的这个代码里面涉及到了这个find函数,这个时候我们需要去找到这个对应的元素,因此我们需要找到这个数据在具体的那一列里面的哪一个位置,因此这个需要返回两个数据,这个时候就是我们的pair使用到的场景;

具体的代码太长了,我就不放置了,初学者理解起来也比较费劲(说的我自己),在这个里面还了解到了这个UVa相关的这个内容,西班牙的一个非常牛逼的网站,可能就是需要我们去科学上网吧,否则这个题目也是没有办法进行这个正常的评测的;

但是我了解到了这个vjudge这个网站,之前在这个文章里面是见到过的,因此我们可以通过这个网站进行提交;

我们的这个代码提交不上去的时候,我们可以使用这个网站进行处理;这个内容我也是第一次了解到,这个也是我支撑看到最后的这个原因把;

image-20250718213520784

5.一点感想

当我知道这个网站的时候,我忽然想起来了清疏的这个第一次课程里面有这个数学相关的网站,了解到这个一些非常出名的这个数学网站,当我看到这个uva的时候换让联想到了这个相关的内容;

确实该是感慨,每一个领域,每一个学科都有一个非常庞大的这个网站系统,数学如此,计算机也是这样的,我还是感慨,找到自己喜欢的这个方向,都是有无尽的这个资源,前方等这我们去挖掘的,可能这个也是我今天晚上很大的这个感慨吧;

因为我之前也是接触这个atcode之类的比赛,但是我其实并不是非常的喜欢,但是对于热爱算法的同学来讲,这些都是非常不错的,还是希望大家都能早点找到自己的这个热爱把,今天晚上还是有点感慨的;