Leetcode第250场周赛

  • Post author:
  • Post category:其他



https://leetcode-cn.com/contest/weekly-contest-250/



可以输入的最大单词数


https://leetcode-cn.com/problems/maximum-number-of-words-you-can-type/



描述

键盘出现了一些故障,有些字母键无法正常工作。而键盘上所有其他键都能够正常工作。

给你一个由若干单词组成的字符串 text ,单词间由单个空格组成(不含前导和尾随空格);另有一个字符串 brokenLetters ,由所有已损坏的不同字母键组成,返回你可以使用此键盘完全输入的 text 中单词的数目。

  • 1 <= text.length <= 104
  • 0 <= brokenLetters.length <= 26
  • text 由若干用单个空格分隔的单词组成,且不含任何前导和尾随空格
  • 每个单词仅由小写英文字母组成
  • brokenLetters 由 互不相同 的小写英文字母组成


样例
示例 1:
输入:text = "hello world", brokenLetters = "ad"
输出:1
解释:无法输入 "world" ,因为字母键 'd' 已损坏。

示例 2:
输入:text = "leet code", brokenLetters = "lt"
输出:1
解释:无法输入 "leet" ,因为字母键 'l''t' 已损坏。

示例 3:
输入:text = "leet code", brokenLetters = "e"
输出:0
解释:无法输入任何单词,因为字母键 'e' 已损坏。


解题思路

简单的模拟题,记录哪些字母坏了,然后判断每个单词能否能够输入。



AC代码
public int canBeTypedWords(String text, String brokenLetters) {
    // 记录坏掉的字母
    boolean[] flag = new boolean[200];
    for (char ch : brokenLetters.toCharArray()) {
        flag[ch] = true;
    }
    String[] s = text.split(" ");
    int count = 0;
    // 遍历单词
    for (String str : s) {
        boolean check = true;
        for (char c : str.toCharArray()) {
            // 判断单词能否输入
            if (flag[c]) {
                check = false;
                break;
            }
        }
        // 单词能够输入,计数加一
        if (check) {
            ++count;
        }
    }
    return count;
}



新增的最少台阶数


https://leetcode-cn.com/problems/add-minimum-number-of-rungs/



描述

给你一个 严格递增 的整数数组 rungs ,用于表示梯子上每一台阶的 高度 。当前你正站在高度为 0 的地板上,并打算爬到最后一个台阶。

另给你一个整数 dist 。每次移动中,你可以到达下一个距离你当前位置(地板或台阶)不超过 dist 高度的台阶。当然,你也可以在任何正 整数 高度处插入尚不存在的新台阶。

返回爬到最后一阶时必须添加到梯子上的 最少 台阶数。


  • 1 <= rungs.length <= 10

  • 1 <= rungs[i] <= 10

  • 1 <= dist <= 10

  • rungs


    严格递增


样例
示例 1:
输入:rungs = [1,3,5,10], dist = 2
输出:2
解释:
现在无法到达最后一阶。
在高度为 78 的位置增设新的台阶,以爬上梯子。 
梯子在高度为 [1,3,5,7,8,10] 的位置上有台阶。

示例 2:
输入:rungs = [3,6,8,10], dist = 3
输出:0
解释:
这个梯子无需增设新台阶也可以爬上去。

示例 3:
输入:rungs = [3,4,6,7], dist = 2
输出:1
解释:
现在无法从地板到达梯子的第一阶。 
在高度为 1 的位置增设新的台阶,以爬上梯子。 
梯子在高度为 [1,3,4,6,7] 的位置上有台阶。

示例 4:
输入:rungs = [5], dist = 10
输出:0
解释:这个梯子无需增设新台阶也可以爬上去。


解题思路

因为数组是严格递增的,所以我只要考虑从当前台阶上到下一个台阶时需不需要加梯子

  • 当前台阶据下一个台阶不超过 dist :不用加梯子
  • 当前台阶据下一个台阶超过 dist:不断加梯子,知道距离不超过dist


AC代码
public int addRungs(int[] rungs, int dist) {
    // 所需要梯子数
    int tizi = 0;
    // 当前台阶高度
    int height = 0;
    // 遍历台阶
    for (int num : rungs) {
        // 当前台阶不能抵达下一个台阶
        while (num - height > dist) {
            // 计算差距
            int diff = num - height;
            // 计算到达下一个台阶需要多少个梯子
            int x = diff / dist;
            // 差距是 dist 的整数可以少一个梯子
            if (diff % dist == 0) {
                --x;
            }
            // 加上所需的梯子数
            tizi += x;
            // 更新台阶高度
            height = height + x * dist;
        }
        // 可以抵达下一个台阶
        height = num;
    }
    return tizi;
}



扣分后的最大得分


https://leetcode-cn.com/problems/maximum-number-of-points-with-cost/



描述

给你一个 m x n 的整数矩阵 points (下标从 0 开始)。一开始你的得分为 0 ,你想最大化从矩阵中得到的分数。

你的得分方式为:每一行 中选取一个格子,选中坐标为 (r, c) 的格子会给你的总得分 增加 points[r][c] 。

然而,相邻行之间被选中的格子如果隔得太远,你会失去一些得分。对于相邻行 r 和 r + 1 (其中 0 <= r < m – 1),选中坐标为 (r, c1) 和 (r + 1, c2) 的格子,你的总得分 减少 abs(c1 – c2) 。

请你返回你能得到的 最大 得分。

abs(x) 定义为:

  • 如果 x >= 0 ,那么值为 x 。
  • 如果 x < 0 ,那么值为 -x 。
  • m == points.length
  • n == points[r].length
  • 1 <= m, n <= 105
  • 1 <= m * n <= 105
  • 0 <= points[r][c] <= 105


样例

在这里插入图片描述



解题思路

开始想了一个动规方程

f[i][j] = Math.

max

(f[i][j], f[i – 1][k] – Math.

abs

(j – k)) + points[i][j]

然后

在这里插入图片描述

最后一个超时。因为没有优化,动规是O(nmm),m是一行的长度;碰上最大数据,妥妥地超时。然后一直想怎么优化优化优化~。然后就时间到了。。渣渣如我

赛后打开题解:https://leetcode-cn.com/problems/maximum-number-of-points-with-cost/solution/dp-you-hua-ji-qiao-chai-xiang-qian-hou-z-5vvc/

把我上面的动规方程中的 | j – k | 去掉绝对值就可以发现一片新天地啊!!

在这里插入图片描述

这样只要能够知道 max(f[i – 1][k] + k) (k <= j),max(f[i – 1][k] – k)(k > j) 就可以在O(1)的时间内获取结果,时间复杂度就降到了O(nm)。

所以我们先记录上一层的 f[i – 1][k] + k,f[i – 1][k] – k;然后因为是遍历数组,所以 k <= j 是可以在遍历的时候得出来max(f[i – ][k] + k),所以用辅助数组计算上一层的 max(f[i – 1][k] – k),就可以在O(1)的时间内得到结果啦。

灵老师yyds。



AC代码
public long maxPoints(int[][] points) {
    // 记录
    long ans = 0;
    int n = points.length, m = points[0].length;
    // 记录当前层的 f[i - 1][k] + k 和 f[i - 1][k] - k 值。
    long[][] f = new long[m][2];
    // 记录max( f[i - 1][k] - k;
    long[] help = new long[m];

    for (int i = 0; i < n; ++i) {
        if (i == 0) {
            // 初始化第一行
            for (int j = 0; j < m; j++) {
                int x = points[i][j];
                ans = Math.max(ans, x);
                f[j][0] = x + j;
                f[j][1] = x - j;
            }
        } else {
            // 记录 max( f[i - 1][k] + k )
            long preMax = Integer.MIN_VALUE;
            // 动规过程
            for (int j = 0; j < m; j++) {
                // 更新preMax
                preMax = Math.max(preMax, f[j][0]);
                int x = points[i][j];                
                long now = Math.max(x - j + preMax, x + j + help[j]);
                // 更新答案
                ans = Math.max(ans, now);
                f[j][0] = now + j;
                f[j][1] = now - j;
            }
        }
        // 辅助函数记录max(f[i - 1][k] - k)
        help[m - 1] = f[m - 1][1];
        for (int j = m - 2; j >= 0; --j) {
            help[j] = Math.max(help[j + 1], f[j][1]);
        }
    }
    return ans;
}



查询最大基因差


https://leetcode-cn.com/problems/maximum-genetic-difference-query/



描述

给你一棵 n 个节点的有根树,节点编号从 0 到 n – 1 。每个节点的编号表示这个节点的 独一无二的基因值 (也就是说节点 x 的基因值为 x)。两个基因值的 基因差 是两者的 异或和 。给你整数数组 parents ,其中 parents[i] 是节点 i 的父节点。如果节点 x 是树的 根 ,那么 parents[x] == -1 。

给你查询数组 queries ,其中 queries[i] = [nodei, vali] 。对于查询 i ,请你找到 vali 和 pi 的 最大基因差 ,其中 pi 是节点 nodei 到根之间的任意节点(包含 nodei 和根节点)。更正式的,你想要最大化 vali XOR pi 。

请你返回数组 ans ,其中 ans[i] 是第 i 个查询的答案。

2 <= parents.length <= 105

对于每个 不是 根节点的 i ,有 0 <= parents[i] <= parents.length – 1 。

  • parents[root] == -1
  • 1 <= queries.length <= 3 * 104
  • 0 <= nodei <= parents.length – 1
  • 0 <= vali <= 2 * 105


样例

在这里插入图片描述



解题思路

渣渣洲还不会。有空再做。题解都是离线+字典树



版权声明:本文为weixin_42183401原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。