第 235 场周赛

495 阅读2分钟

1816. 截断句子

题目

句子 是一个单词列表,列表中的单词之间用单个空格隔开,且不存在前导或尾随空格。每个单词仅由大小写英文字母组成(不含标点符号)。

  • 例如,"Hello World""HELLO""hello world hello world" 都是句子。

给你一个句子 s 和一个整数 k ,请你将 s 截断 ,使截断后的句子仅含 k 个单词。返回 截断 s** 后得到的句子*。*

示例 1:

输入:s = "Hello how are you Contestant", k = 4
输出:"Hello how are you"
解释:
s 中的单词为 ["Hello", "how" "are", "you", "Contestant"]
前 4 个单词为 ["Hello", "how", "are", "you"]
因此,应当返回 "Hello how are you"

示例 2:

输入:s = "What is the solution to this problem", k = 4
输出:"What is the solution"
解释:
s 中的单词为 ["What", "is" "the", "solution", "to", "this", "problem"]
前 4 个单词为 ["What", "is", "the", "solution"]
因此,应当返回 "What is the solution"

示例 3:

输入:s = "chopper is not a tanuki", k = 5
输出:"chopper is not a tanuki"

提示:

  • 1 <= s.length <= 500
  • k 的取值范围是 [1, s 中单词的数目]
  • s 仅由大小写英文字母和空格组成
  • s 中的单词之间由单个空格隔开
  • 不存在前导或尾随空格

代码

class Solution {
public:
    string truncateSentence(string s, int k) {
        int cnt = 0;
        int i = 0;
        for (; i < s.length() && cnt != k; i++) {
            if (s[i] == ' ') cnt++;
        }
        return cnt == k ? s.substr(0, i - 1) : s;
    }
};

1817. 查找用户活跃分钟数

题目

给你用户在 LeetCode 的操作日志,和一个整数 k 。日志用一个二维整数数组 logs 表示,其中每个 logs[i] = [IDi, timei] 表示 ID 为 IDi 的用户在 timei 分钟时执行了某个操作。

多个用户 可以同时执行操作,单个用户可以在同一分钟内执行 多个操作

指定用户的 用户活跃分钟数(user active minutes,UAM) 定义为用户对 LeetCode 执行操作的 唯一分钟数 。 即使一分钟内执行多个操作,也只能按一分钟计数。

请你统计用户活跃分钟数的分布情况,统计结果是一个长度为 k下标从 1 开始计数 的数组 answer ,对于每个 j1 <= j <= k),answer[j] 表示 用户活跃分钟数 等于 j 的用户数。

返回上面描述的答案数组 answer

示例 1:

输入:logs = [[0,5],[1,2],[0,2],[0,5],[1,3]], k = 5
输出:[0,2,0,0,0]
解释:
ID=0 的用户执行操作的分钟分别是:525 。因此,该用户的用户活跃分钟数为 2(分钟 5 只计数一次)
ID=1 的用户执行操作的分钟分别是:23 。因此,该用户的用户活跃分钟数为 2
2 个用户的用户活跃分钟数都是 2 ,answer[2] 为 2 ,其余 answer[j] 的值都是 0

示例 2:

输入:logs = [[1,1],[2,2],[2,3]], k = 4
输出:[1,1,0,0]
解释:
ID=1 的用户仅在分钟 1 执行单个操作。因此,该用户的用户活跃分钟数为 1
ID=2 的用户执行操作的分钟分别是:23 。因此,该用户的用户活跃分钟数为 2
1 个用户的用户活跃分钟数是 1 ,1 个用户的用户活跃分钟数是 2 
因此,answer[1] = 1 ,answer[2] = 1 ,其余的值都是 0

提示:

  • 1 <= logs.length <= 104
  • 0 <= IDi <= 109
  • 1 <= timei <= 105
  • k 的取值范围是 [用户的最大用户活跃分钟数, 105]

代码

class Solution {
public:
    vector<int> findingUsersActiveMinutes(vector<vector<int>>& logs, int k) {
        unordered_map<int, unordered_set<int>> Map;
        for (auto& log : logs) {
            Map[log[0]].insert(log[1]);
        }
        vector<int> res(k, 0);
        for (auto& m : Map) {
            res[m.second.size() - 1]++;
        }
        return res;
    }
};

1818. 绝对差值和

题目

给你两个正整数数组 nums1nums2 ,数组的长度都是 n

数组 nums1nums2绝对差值和 定义为所有 |nums1[i] - nums2[i]|0 <= i < n)的 总和下标从 0 开始)。

你可以选用 nums1 中的 任意一个 元素来替换 nums1 中的 至多 一个元素,以 最小化 绝对差值和。

在替换数组 nums1 中最多一个元素 之后 ,返回最小绝对差值和。因为答案可能很大,所以需要对 109 + 7 取余 后返回。

|x| 定义为:

  • 如果 x >= 0 ,值为 x ,或者

  • 如果 x <= 0 ,值为 -x

示例 1:

输入:nums1 = [1,7,5], nums2 = [2,3,5]
输出:3
解释:有两种可能的最优方案:
- 将第二个元素替换为第一个元素:[1,7,5] => [1,1,5] ,或者
- 将第二个元素替换为第三个元素:[1,7,5] => [1,5,5]
两种方案的绝对差值和都是 |1-2| + (|1-3| 或者 |5-3|) + |5-5| = 3

示例 2:

输入:nums1 = [2,4,6,8,10], nums2 = [2,4,6,8,10]
输出:0
解释:nums1 和 nums2 相等,所以不用替换元素。绝对差值和为 0

示例 3**:**

输入:nums1 = [1,10,4,4,2,7], nums2 = [9,3,5,1,7,4]
输出:20
解释:将第一个元素替换为第二个元素:[1,10,4,4,2,7] => [10,10,4,4,2,7]
绝对差值和为 |10-9| + |10-3| + |4-5| + |4-1| + |2-7| + |7-4| = 20

提示:

  • n == nums1.length
  • n == nums2.length
  • 1 <= n <= 105
  • 1 <= nums1[i], nums2[i] <= 105

代码

// 因为可以用nums1中的任意数字替换nums1中的一个数字使得绝对差值和最小
// 我们可以枚举每一个nums2中的元素, 最小化其与nums1对应元素的绝对差值
// 也就是可以将nums1当前位置的数字nums1[i]替换成nums1中第一个大于或者等于nums2[i]的数字, 或者最后一个小于nums2[i]的数字
// 取最小差值即可
typedef long long ll;
int mod = 1e9 + 7;
class Solution {
public:
    int minAbsoluteSumDiff(vector<int>& nums1, vector<int>& nums2) {
        int n = nums1.size();
        set<int> st; // sort
        ll tot = 0;
        for (int i = 0; i < n; i++) {
            tot += abs(nums1[i] - nums2[i]);
            st.insert(nums1[i]);
        }
        ll ans = tot;
        for (int i = 0; i < n; i++) {
            auto it = st.lower_bound(nums2[i]);
            if (it != st.end()) {
                ll now = tot - abs(nums1[i] - nums2[i]) + abs(*it - nums2[i]);
                ans = min(ans, now);
            } 
            if (it != st.begin()) {
                --it;
                ll pre = tot - abs(nums1[i] - nums2[i]) + abs(*it - nums2[i]);
                ans = min(ans, pre);
            }
        }
        return ans % mod;
    }
};

1819. 序列中不同最大公约数的数目

题目

给你一个由正整数组成的数组 nums

数字序列的 最大公约数 定义为序列中所有整数的共有约数中的最大整数。

  • 例如,序列 [4,6,16] 的最大公约数是 2

数组的一个 子序列 本质是一个序列,可以通过删除数组中的某些元素(或者不删除)得到。

  • 例如,[2,5,10][1,2,1,**2**,4,1,**5**,**10**] 的一个子序列。

计算并返回 nums 的所有 非空 子序列中 不同 最大公约数的 数目

示例 1:

img

输入:nums = [6,10,3]
输出:5
解释:上图显示了所有的非空子序列与各自的最大公约数。
不同的最大公约数为 6 、10 、3 、2 和 1 。

示例 2:

输入:nums = [5,15,40,5,6]
输出:7

提示:

  • 1 <= nums.length <= 105
  • 1 <= nums[i] <= 2 * 105

代码

class Solution {
public:
    int m = 0;
    bool f[200010];
    int gcd(int a,int b){return a%b==0?b:gcd(b,a%b);}
    bool check(int x){
        int t = 0;
        for(int i = x; i <= m; i += x) 
            if(f[i]){
                if(t==0)t = i/x;
                else t=gcd(t,i/x);
            }
        return t == 1;
    }
    int countDifferentSubsequenceGCDs(vector<int>& nums) {
        int n = nums.size();
        int ans = 0;
        for(int i = 0; i < n; ++i){
            m = max(m,nums[i]);
            f[nums[i]] = 1;
        }
        for(int i = 1;i <= m; ++i)
            if(check(i))
                ++ans;
        return ans;
    }
};