week33

Week 33 - Leetcode 321 - 330

321 - 拼接最大数

首先把这个问题拆分成如下的子问题:

  • 枚举从第一个数组中选几个数

  • 从一个长度为m的数组中,按顺序选择k个数,使其字典序最大

  • 按顺序合并两个数组,使其字典序最大

总结一下,按顺序选择子序列使其字典序最大这样都是贪心+栈 来删除,这里和316题是一个思路 都是比较大小,能删就删

学习一下这个代码

vector<int> maxArray(vector<int>& nums, int k)
{
    int n = nums.size();
    vector<int> res(k);
    for(int i = 0, j = 0; i < nums.size(); i++)
    {
        int x = nums[i];
        // 这里的逻辑是 如果栈里有元素 且栈顶元素比x小,且弹出后还能凑成k个数的话(能删) 就删
        while(j && res[j - 1] < x && j + n - i > k) j--;
        if(j < k) res[j++] = x; // 如果可以加入就加入 这里学习一下
    }
}

按顺序合并两个子数组使得字典序最大,也是同样的贪心思路,按大的元素合并;

如果两个元素相同的话 则比较后面的元素 选择后面元素大的那一排

代码中利用到了vector的比较大小 这里直接是按照字典序比较的 所以简洁很多 这里学习一下

322 - 零钱兑换

经典的完全背包问题,完全背包就是从小到大遍历体积v,然后注意一下初始状态定义就好了

这里由于要装满 所以f[0] = 0 其余都是无穷大

324 - 摆动排序II

给你一个整数数组 nums,将它重新排列成 nums[0] < nums[1] > nums[2] < nums[3]... 的顺序

没啥可说的 智力题 背一背就好

有这么几个要复习的地方:

*

思路: 将所有数分成三种:小于mid的数、等于mid的数和大于mid的数。 然后对数组排序,使得大于mid的数在最前面,等于mid的数在中间,小于mid的数在最后面。

这一步可以直接利用三数排序,三数排序算法可以参考LeetCode 75. Sort Colors

然后我们将排好序的数组重排,将前半段依次放到奇数位置上,将后半段依次放到偶数位置上。此时就会有: nums[0] < nums[1] > nums[2] < nums[3] ...

这一步重排我们可以在三数排序时做,只需在排序时做一个数组下标映射即可:

i => (1 + 2 * i) % (n | 1) 该映射可以将数组前一半映射到奇数位置上,数组后一半映射到偶数位置上。

这个下标映射显然是硬凑的

然后记得把三路快排直接套上去,这里有个技巧可以直接按照这个映射排序即可;

然后学习一下宏函数

326 - 3的幂

首先 int 范围内最大的3的幂是3 ^ 19 , 看n是否能够整除它

  • 如果可以,那么n的所有质因子一定都为3 是3的幂

  • 如果不可以,则一定存在非3质因子,不是3的幂

327 - 区间和的个数

宇宙无敌经典的树状数组题了

avatar

保序离散化 + 树状数组查询区间 代码里还是有不少细节的 建议多看看

此外记得提前把0加进去 s[0] = 0;

然后边界问题 记得区间长度用long long来存

328 - 奇偶链表

按照奇偶位数重排成两个链表然后拼在一起就可以了 记住要置nullptr

329 - 矩阵中的最长递增路径

上下左右四个方向是连通的, 要找到最长的递增路径(严格递增)

实际上是用记忆化搜索实现的动态规划问题,要想动态规划必须保证的前提是没有环形依赖

这里由于限制了严格递增,肯定是没有环形路径存在的,所以可以动态规划来解,但是方向是从上下左右,这里用记忆化搜索来实现

剩下的就是一个标准的矩阵搜索模板了

330 - 按要求补齐数组

其实是个贪心题 贪心题就记一记方法就好

avatar

所以是贪心选更大的数就好(nums已经是有序的了)

Last updated