• [Leetcode Weekly Contest]286


    链接:LeetCode

    [Leetcode]2215. 找出两数组的不同

    给你两个下标从 0 开始的整数数组 nums1 和 nums2 ,请你返回一个长度为 2 的列表 answer ,其中:

    answer[0] 是 nums1 中所有 不 存在于 nums2 中的 不同 整数组成的列表。
    answer[1] 是 nums2 中所有 不 存在于 nums1 中的 不同 整数组成的列表。
    注意:列表中的整数可以按 任意 顺序返回。。

    哈希表,遍历即可。

    class Solution {
        public List<List<Integer>> findDifference(int[] nums1, int[] nums2) {
            List<List<Integer>> res = new ArrayList<>();
            for(int i=0;i<2;++i) res.add(new ArrayList<Integer>());
            Set<Integer> s1 = new HashSet<>();
            Set<Integer> s2 = new HashSet<>();
    
            for(var n1:nums1) s1.add(n1);
            for(var n2:nums2) s2.add(n2);
    
            for(var n1:s1) {
                if(!s2.contains(n1)) res.get(0).add(n1);
            }
            for(var n2:s2) {
                if(!s1.contains(n2)) res.get(1).add(n2);
            }
    
            return res;
        }
    }
    

    [Leetcode]2216. 美化数组的最少删除数

    给你一个下标从 0 开始的整数数组 nums ,如果满足下述条件,则认为数组 nums 是一个 美丽数组 :

    nums.length 为偶数
    对所有满足 i % 2 == 0 的下标 i ,nums[i] != nums[i + 1] 均成立
    注意,空数组同样认为是美丽数组。

    你可以从 nums 中删除任意数量的元素。当你删除一个元素时,被删除元素右侧的所有元素将会向左移动一个单位以填补空缺,而左侧的元素将会保持 不变 。

    返回使 nums 变为美丽数组所需删除的 最少 元素数目。

    遍历即可,可以设置一个标志位判断下标。

    class Solution {
        public int minDeletion(int[] nums) {
            int res = 0;
            int n = nums.length;
            boolean flag = true;
            for(int i=0;i<n-1;++i) {
                if(flag && nums[i] == nums[i+1]) {
                     res ++;
                }
                else flag = !flag;
            }
            if(flag) res ++;
            return res;
        }
    }
    

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

    给你一个整数数组 queries 和一个 正 整数 intLength ,请你返回一个数组 answer ,其中 answer[i] 是长度为 intLength 的 正回文数 中第 queries[i] 小的数字,如果不存在这样的回文数,则为 -1 。

    回文数 指的是从前往后和从后往前读一模一样的数字。回文数不能有前导 0 。

    只看回文数的左半部分,可以发现左半部分是从 \(1000\cdots0\) 开始,逐渐增加的。反转这个数,拼到左半部分之后即为第 q 个长为 intLength 的回文数。

    class Solution {
        public long[] kthPalindrome(int[] queries, int intLength) {
            int k = (intLength+1) / 2;
            int maxK = (int)(9 * Math.pow(10 , k-1));
            int n = queries.length;
            long[] res = new long[n];
            for(int i=0;i<n;++i) {
                int query = queries[i];
                res[i] = query > maxK ? -1 : getKthPalindrome(query, intLength, k);
            }
            return res;
        }
    
        public long getKthPalindrome(int query, int intLength, int k) {
            char[] res = new char[intLength];
            query --;
            for(int i=0;i<k;++i) {
                if(i == 0) res[i] = (char)(query / Math.pow(10, k-1)+'1');
                if(i !=0 ) res[i] = (char)(query / Math.pow(10, k-i-1)+'0');
                query = (int)(query % Math.pow(10, k-i-1));
            }
            int j = 0;
            for(int i=intLength-1;i>=k;--i) {
                res[i] = res[j];
                j++;
            }
            long result = 0L;
            for (var ch:res) {
                result = result * 10 + (ch-'0');
            }
            return result;
        }
    }
    

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

    一张桌子上总共有 n 个硬币 栈 。每个栈有 正整数 个带面值的硬币。

    每一次操作中,你可以从任意一个栈的 顶部 取出 1 个硬币,从栈中移除它,并放入你的钱包里。

    给你一个列表 piles ,其中 piles[i] 是一个整数数组,分别表示第 i 个栈里 从顶到底 的硬币面值。同时给你一个正整数 k ,请你返回在 恰好 进行 k 次操作的前提下,你钱包里硬币面值之和 最大为多少 。

    朴素的,通过三维DP可以解答,但我们可以发现再每次循环时都需要对getCoinValue进行累加,这在同一个栈的循环中是浪费的,因为我们对于同一个i的栈,都需要计算其前缀。

    class Solution {
        public int maxValueOfCoins(List<List<Integer>> piles, int k) {
            int n = piles.size();
            int[][] dp = new int[n][k+1];
            for(int i = 0;i<n;++i) {
                for(int j=0;j<k+1;++j) {
                    if(j==0) dp[i][0] = 0;
                    else if(i==0) dp[0][j] = piles.get(0).subList(0, Math.min(piles.get(0).size(), j)).stream().collect(Collectors.summingInt(Integer::intValue));
                    else {
                        int getCoinValue = 0;
                        for(int getCoin = 0; getCoin <= Math.min(j, piles.get(i).size()); ++ getCoin) {
                            if(getCoin !=0 ) getCoinValue += piles.get(i).get(getCoin-1);
                            dp[i][j] = Math.max(dp[i][j], dp[i-1][j-getCoin] + getCoinValue);
                        }
                    }
                }
            }
            return dp[n-1][k];
        }
    }
    

    因此,我们可以先对每个栈求其前缀和 \(\textit{sum}\)\(\textit{sum}\) 的第 \(j\) 个元素视作一个体积为 \(j\),价值为 \(\textit{sum}[j]\) 的物品。
    问题转化成求从 n 个物品组里面取物品体积和为 k 的物品,且每组至多取一个物品时的物品价值最大和,即分组背包模型。

    class Solution {
        public int maxValueOfCoins(List<List<Integer>> piles, int k) {
            var f = new int[k + 1];
            var sumN = 0;
            for (var pile : piles) {
                var n = pile.size();
                for (var i = 1; i < n; ++i)
                    pile.set(i, pile.get(i) + pile.get(i - 1)); // pile 前缀和
                sumN = Math.min(sumN + n, k); // 优化:j 从前 i 个栈的大小之和开始枚举(不超过 k)
                for (var j = sumN; j > 0; --j)
                    for (var w = 0; w < Math.min(n, j); ++w)
                        f[j] = Math.max(f[j], f[j - w - 1] + pile.get(w)); // w 从 0 开始,物品体积为 w+1
            }
            return f[k];
        }
    }
    

    Leetcode

  • 相关阅读:
    第七章
    第五章
    第六章
    Git使用入门
    源代码的下载和编译
    向中国最牛的前端群-鬼群致敬
    Normalize.css做了哪些事情--看代码
    谷歌浏览器:书签被误删了怎么办
    2013/8月读书计划
    Limu:JavaScript的那些书
  • 原文地址:https://www.cnblogs.com/hellojamest/p/16290376.html
Copyright © 2020-2023  润新知