这周本质上就2题,我就放两个题解了。

100192. Minimum Number of Pushes to Type Word II

给你一个字符串 word,由 不同 小写英文字母组成。

电话键盘上的按键与 不同 小写英文字母集合相映射,可以通过按压按键来组成单词。例如,按键 2 对应 ["a","b","c"],我们需要按一次键来输入 "a",按两次键来输入 "b",按三次键来输入 "c"。

现在允许你将编号为 2 到 9 的按键重新映射到 不同 字母集合。每个按键可以映射到 任意数量 的字母,但每个字母 必须 恰好 映射到 一个 按键上。你需要找到输入字符串 word 所需的 最少 按键次数。

返回重新映射按键后输入 word 所需的 最少 按键次数。

下面给出了一种电话键盘上字母到按键的映射作为示例。注意 1,*,# 和 0 不 对应任何字母。

测试样例:

输入:word = "aabbccddeeffgghhiiiiii"

输出:24

解释:"a" -> 在按键 2 上按一次

  • "b" -> 在按键 3 上按一次
  • "c" -> 在按键 4 上按一次
  • "d" -> 在按键 5 上按一次
  • "e" -> 在按键 6 上按一次
  • "f" -> 在按键 7 上按一次
  • "g" -> 在按键 8 上按一次
  • "h" -> 在按键 9 上按两次
  • "i" -> 在按键 9 上按一次

总成本为 1 2 + 1 2 + 1 2 + 1 2 + 1 2 + 1 2 + 1 2 + 2 2 + 6 * 1 = 24 。可以证明不存在其他成本更低的映射方案。

解答:计算一下每个数字的出现次数,然后出现次数多的数字尽量少按(贪婪)。

class Solution {
    public int minimumPushes(String word) {
        int[] count = new int[26];
        for (int i = 0; i < word.length(); ++i) {
            count[word.charAt(i) - 'a'] += 1;
        }
        Arrays.sort(count);
        int res = 0, mul = 1, remain = 8;
        for (int i = 25; i >= 0; --i) {
            --remain;
            if (remain < 0) {
                remain = 7;
                ++mul;
            }
            res += mul * count[i];
        }
        return res;
    }
}

100213. Count the Number of Houses at a Certain Distance II

给你三个 正整数 n 、x 和 y 。

在城市中,存在编号从 1 到 n 的房屋,由 n 条街道相连。对所有 1 <= i < n ,都存在一条街道连接编号为 i 的房屋与编号为 i + 1 的房屋。另存在一条街道连接编号为 x 的房屋与编号为 y 的房屋。

对于每个 k(1 <= k <= n),你需要找出所有满足要求的 房屋对 [house1, house2] ,即从 house1 到 house2 需要经过的 最少 街道数为 k 。

返回一个下标从 1 开始且长度为 n 的数组 result ,其中 result[k] 表示所有满足要求的房屋对的数量,即从一个房屋到另一个房屋需要经过的 最少 街道数为 k 。

注意,x 与 y 可以 相等 。

测试样例:

输入:n = 3, x = 1, y = 3

输出:[6,0,0]

解释:让我们检视每个房屋对

  • 对于房屋对 (1, 2),可以直接从房屋 1 到房屋 2。
  • 对于房屋对 (2, 1),可以直接从房屋 2 到房屋 1。
  • 对于房屋对 (1, 3),可以直接从房屋 1 到房屋 3。
  • 对于房屋对 (3, 1),可以直接从房屋 3 到房屋 1。
  • 对于房屋对 (2, 3),可以直接从房屋 2 到房屋 3。
  • 对于房屋对 (3, 2),可以直接从房屋 3 到房屋 2。

解答:这道题目主要是细心。题目本身考察区间更新。我们可以按照x和y,把数组切分成三块。第一块和第三块因为x和y短接,必然能够减少路程。第一块和第二块,第三块和第二块,以及第二块内部需要通过不等式计算获取哪些范围会发生更新。发生更新的区域,它的diff必然一致(有兴趣可以自己手动推导一下)。

class Solution {
    public long[] countOfPairs(int n, int x, int y) {
        long[] res = new long[n];
        for (int i = 0; i < res.length; ++i) {
            res[i] = (n - i - 1L) * 2;
        }
        if (Math.abs(x - y) > 1) {
            int l = Math.min(x, y) - 1, r = Math.max(x, y) - 1;
            long[] lazyUpdate = new long[n];
            for (int i = 0; i < l; ++i) {
                int min = r + 1 - i - 1, max = n - 1 - i - 1;
                update(lazyUpdate, min, -2);
                update(lazyUpdate, max + 1, +2);
                update(lazyUpdate, min - (r - l - 1), 2);
                update(lazyUpdate, max - (r - l - 1) + 1, -2);
            }
            for (int i = l; i <= r; ++i) {
                if (2 * i > r + l + 1) {
                    int diff = 2 * i - l - r - 1;
                    int min = i - (l - 1) - 1, max = i - 1;
                    update(lazyUpdate, min, -2);
                    update(lazyUpdate, max + 1, +2);
                    update(lazyUpdate, min - diff, 2);
                    update(lazyUpdate, max - diff + 1, -2);
                }
                if (2 * i < l + r - 1) {
                    int diff = l + r - 1 - 2 * i;
                    int min = r + 1 - i - 1, max = n - 1 - i - 1;
                    update(lazyUpdate, min, -2);
                    update(lazyUpdate, max + 1, +2);
                    update(lazyUpdate, min - diff, 2);
                    update(lazyUpdate, max - diff + 1, -2);
                }
            }
            for (int i = r - l; i > 0; --i) {
                if (2 * i <= r - l + 1) {
                    break;
                }
                int count = r - l - i + 1;
                res[i - 1] -= 2L * count;
                res[r - l - i] += 2L * count;
            }
            long add = 0;
            for (int i = 0; i < lazyUpdate.length; ++i) {
                add += lazyUpdate[i];
                res[i] += add;
            }
        }
        return res;
    }

    private void update(long[] arr, int pos, int val) {
        if (pos >= 0 && pos < arr.length) {
            arr[pos] += val;
        }
    }
}

Leave a Reply

Your email address will not be published. Required fields are marked *