Leetcode 第 381 场周赛题解
- Leetcode 第 381 场周赛题解
- 题目1:3014. 输入单词需要的最少按键次数 I
- 思路
- 代码
- 复杂度分析
- 题目2:3015. 按距离统计房屋对数目 I
- 思路
- 代码
- 复杂度分析
- 题目3:3016. 输入单词需要的最少按键次数 II
- 思路
- 代码
- 复杂度分析
- 题目4:3017. 按距离统计房屋对数目 II
- 思路
- 代码
- 复杂度分析
Leetcode 第 381 场周赛题解
题目1:3014. 输入单词需要的最少按键次数 I
思路
题目里说了字符串 s 中只要小写字母,所以不用统计 1、#、*、0 这 4 个特殊字符的出现次数。
代码
// 数学class Solution
{
public:int minimumPushes(string word){// 特判if (word.empty())return 0;int n = word.length();int k = n / 8;return (k * 4 + n % 8) * (k + 1);}
};
复杂度分析
时间复杂度:O(1)。
空间复杂度:O(1)。
题目2:3015. 按距离统计房屋对数目 I
思路
暴力枚举每一个房屋对 (i, j) 的 3 种路径:
- i->j:长度为 len1 = j-i;
- i->x->y->j:长度为 len2 = abs(i - x) + 1 + abs(j - y);
- i->y->x->j:长度为 len3 = abs(i - y) + 1 + abs(j - x)。
取这 3 种路径的最小值作为房屋对 (i, j) 的路径,路径长度 len = min({len1, len2, len3}),因为路径是双向的,在答案数组 ans 中 ans[len - 1] += 2。
最后返回 ans 数组。
代码
/** @lc app=leetcode.cn id=3015 lang=cpp** [3015] 按距离统计房屋对数目 I*/// @lc code=start
class Solution
{
public:vector<int> countOfPairs(int n, int x, int y){vector<int> ans(n, 0);for (int i = 1; i < n; i++)for (int j = i + 1; j <= n; j++){int len1 = j - i; // i->jint len2 = abs(i - x) + 1 + abs(j - y); // i->x->y->jint len3 = abs(i - y) + 1 + abs(j - x); // i->y->x->j// 取最短距离作为路径int len = min({len1, len2, len3});ans[len - 1] += 2; // 路径是双向的}return ans;}
};
// @lc code=end
复杂度分析
时间复杂度:O(n2),其中 n 是房屋数量。
空间复杂度:O(n),其中 n 是房屋数量。
题目3:3016. 输入单词需要的最少按键次数 II
思路
本题与 3014. 输入单词需要的最少按键次数 I 唯一不同的点在于:
3014. 输入单词需要的最少按键次数 I 中字符串 word 所有字母互不相同,而 3016. 输入单词需要的最少按键次数 II
中字符串 word 的字符可以重复。
因为我们希望出现次数多的字符的点击次数尽可能少。
我们用一个哈希表 alpha 统计字符串 word 中各个字符 c 出现的次数,按降序排序。
遍历哈希表 alpha,当前下标为 i,当前字符次数为 alpha[i],它的单次点击所需次数为 i/8+1 次,因为我们只有 8 个按钮可以按。把 alpha[i] * (i / 8 + 1) 累加起来,这样得到的总按键次数最小。
代码
/** @lc app=leetcode.cn id=3016 lang=cpp** [3016] 输入单词需要的最少按键次数 II*/// @lc code=start
class Solution
{
public:int minimumPushes(string word){// 特判if (word.empty())return 0;int n = word.size();vector<int> alpha(26, 0);for (char &c : word)alpha[c - 'a']++;sort(alpha.begin(), alpha.end(), greater<int>());int ans = 0;for (int i = 0; i < 26; i++)ans += alpha[i] * (i / 8 + 1);return ans;}
};
// @lc code=end
复杂度分析
时间复杂度:O(n),其中 n 是字符串 word 的长度。
空间复杂度:O(n),其中 n 是字符串 word 的长度。
题目4:3017. 按距离统计房屋对数目 II
思路
题解:两种分类讨论思路(Python/Java/C++/Go)
代码
/** @lc app=leetcode.cn id=3017 lang=cpp** [3017] 按距离统计房屋对数目 II*/// @lc code=start
class Solution
{
public:vector<long long> countOfPairs(int n, int x, int y){if (x > y){swap(x, y);}vector<int> diff(n + 1);auto add = [&](int l, int r, int v){if (l > r)return;diff[l] += v;diff[r + 1] -= v;};auto update = [&](int i, int x, int y){add(y - i, n - i, -1); // 撤销 [y,n]int dec = y - x - 1; // 缩短的距离add(y - i - dec, n - i - dec, 1);int j = (x + y + 1) / 2 + 1;add(j - i, y - 1 - i, -1); // 撤销 [j, y-1]add(x - i + 2, x - i + y - j + 1, 1);};auto update2 = [&](int i, int x, int y){add(y - i, n - i, -1); // 撤销 [y,n]int dec = (y - i) - (i - x + 1); // 缩短的距离add(y - i - dec, n - i - dec, 1);int j = i + (y - x + 1) / 2 + 1;add(j - i, y - 1 - i, -1); // 撤销 [j, y-1]add(i - x + 2, i - x + y - j + 1, 1);};for (int i = 1; i <= n; i++){add(1, i - 1, 1);add(1, n - i, 1);if (x + 1 >= y){continue;}if (i <= x){update(i, x, y);}else if (i >= y){update(n + 1 - i, n + 1 - y, n + 1 - x);}else if (i < (x + y) / 2){update2(i, x, y);}else if (i > (x + y + 1) / 2){update2(n + 1 - i, n + 1 - y, n + 1 - x);}}vector<long long> ans(n);long long sum_d = 0;for (int i = 0; i < n; i++){sum_d += diff[i + 1];ans[i] = sum_d;}return ans;}
};
// @lc code=end
复杂度分析
时间复杂度:O(n),其中 n 是房屋数量。
空间复杂度:O(n),其中 n 是房屋数量。