3.28 3.30 LeetCode 第 286 场周赛

2215. 找出两数组的不同

  • 题目大意
    给定两个列表nums1和nums2,输出num1不存在nums2中的数字,和nums2不存在nums1中的数字。

  • 思路
    开数组map一下,不要直接用map,比较麻烦,容易出各种编译错误!、记得去重。

  • code

class Solution {
public:
    vector<vector<int>> findDifference(vector<int>& nums1, vector<int>& nums2) {
        int n1=nums1.size(),n2=nums2.size();
        int p1[2010]={0},p2[2010]={0};
        int f1[2010]={0},f2[2010]={0};
        map<int,int> mp1,mp2;
        vector<vector<int>> ans(2,vector<int>());
        
        for(int i=0;i<n1;i++) p1[nums1[i]+1000]++;
        for(int i=0;i<n2;i++) p2[nums2[i]+1000]++;
        for(int i=0;i<n1;i++){
            if(p2[nums1[i]+1000]==0 && f1[nums1[i]+1000]==0){
                ans[0].push_back(nums1[i]);
                f1[nums1[i]+1000]=1;
            } 
        }
        for(int i=0;i<n2;i++){
            if(p1[nums2[i]+1000]==0 && f2[nums2[i]+1000]==0){
                ans[1].push_back(nums2[i]);
                f2[nums2[i]+1000]=1;
            }
        }
        return ans;
    }
};

2216. 美化数组的最少删除数

  • 题目大意
    当偶数下标的数字和他后一个技术下标的数字不同时,则认为一个序列是“美丽数组”。你可以每次操作可以删除任意位置的数字,问最少删除多少个数使得现有数组变成美丽数组。
  • 思路
    贪心。
    要注意,删除一个数字后,后面的数字的下标奇偶性都会发生改变。
  • code
class Solution {
public:
    int minDeletion(vector<int>& nums) {
        int n = nums.size();
        int ans = 0;
        for (int i = 0; i + 1 < n; i++) {
            if (nums[i] == nums[i + 1]) ans++;
            else i++;
        }
        if ((n - ans) % 2) ans++;
        return ans;
    }
};

2217. 找到指定长度的回文数

  • 题目大意
    返回给定长度为intLength的第queries[i]个回文数。(其中回文数是由0-9数字组成的)。

  • 思路
    可以发现,回文数的数量和回文数的形态是有规律的:
    第i个回文数就是这个回文数前一半的数字是长度为intLength的自然数后的第几个(一个回文数是由他的前一半完全决定的):前一半 = left + queries[i] - 1。
    然后根据长度的奇偶,在反着把剩下一半找到即可。

  • code

class Solution {
public:
    vector<long long> kthPalindrome(vector<int>& queries, int intLength) {
        int n = queries.size();
        vector<long long> ans(n, -1);
        /* 求出[l,r]的构造区间 */
        int left  = pow(10, (intLength + 1) / 2 - 1);
        int right = left * 10;

        for (int i = 0; i < n; i++) {
            if (queries[i] > right - left) {
                continue;
            }
            /* 根据该回文数的一半, 求出该回文数 */
            int cur = left + queries[i] - 1;
            long long sum = cur;
            int x = (intLength % 2 == 1) ? cur / 10 : cur;
            while (x > 0) {
                sum = sum * 10 + x % 10;
                x /= 10;
            }
            ans[i] = sum;
        }
        return ans;
    }
};

2218. 从栈中取出 K 个硬币的最大面值和

  • 题目大意
    n n n个栈,每个栈里有 p l i e s [ i ] plies[i] plies[i]个硬币,每个硬币的面值为 p i l e s [ i ] [ j ] piles[i][j] piles[i][j],你可以取 k k k次,问最终手里最多有价值多少的硬币。

  • 思路
    经典背包 dp,算是简单dp题了。
    f i , j f_{i, j} fi,j表示考虑到第 i i i个栈,一共已经取出了 j j j 个硬币的最大面值和。有转移方程: f i , j = max ⁡ ( f i − 1 , j − t + s i , t ) f_{i, j} = \max (f_{i - 1, j - t} + s_{i, t}) fi,j=max(fi1,jt+si,t),表示从第 i i i个栈中取出 t t t个硬币( t t t为非负整数,不能超过第 t t t个栈的大小 p i p_i pi​ ), s i , t s_{i, t} si,t 表示第 i i i个栈中前 t t t个硬币的面值和。答案就是 f n , k f_{n, k} fn,k。复杂度 O ( k ∑ i = 1 n p i ) \mathcal{O}(k\sum\limits_{i=1}^n p_i) O(ki=1npi)

  • code

class Solution {
public:
    int maxValueOfCoins(vector<vector<int>>& piles, int k) {
        int n = piles.size();
        int s[1010][2010];
        vector<vector<int>> f(n+1, vector<int>(k+1));
        for(int i=0;i<n;i++)
        {
            s[i][0]=piles[i][0];
            for(int j=1;j<piles[i].size();j++)
                s[i][j]=s[i][j-1]+piles[i][j];
        }
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=k;j++)
            {
                f[i][j]=f[i-1][j];
                int x = piles[i-1].size();
                for(int t=1;t<=min(j,x);t++)
                {
                        f[i][j]=max(f[i-1][j-t]+s[i-1][t-1],f[i][j]);
                }
            }
            
        }

        return f[n][k];
    }
};

你可能感兴趣的:(leetcode,算法,c++)