双周赛106(模拟、双指针、脑经急转弯+贡献法)

文章目录

  • 双周赛106
    • [2729. 判断一个数是否迷人](https://leetcode.cn/problems/check-if-the-number-is-fascinating/)
      • 模拟
    • [2730. 找到最长的半重复子字符串](https://leetcode.cn/problems/find-the-longest-semi-repetitive-substring/)
      • 双指针
    • [2731. 移动机器人](https://leetcode.cn/problems/movement-of-robots/)
      • 脑筋急转弯

双周赛106

2729. 判断一个数是否迷人

难度简单0

给你一个三位数整数 n

如果经过以下修改得到的数字 恰好 包含数字 19 各一次且不包含任何 0 ,那么我们称数字 n迷人的

  • n 与数字 2 * n3 * n 连接

如果 n 是迷人的,返回 true,否则返回 false

连接 两个数字表示把它们首尾相接连在一起。比方说 121371 连接得到 121371

示例 1:

输入:n = 192
输出:true
解释:我们将数字 n = 192 ,2 * n = 384 和 3 * n = 576 连接,得到 192384576 。这个数字包含 1 到 9 恰好各一次。

示例 2:

输入:n = 100
输出:false
解释:我们将数字 n = 100 ,2 * n = 200 和 3 * n = 300 连接,得到 100200300 。这个数字不符合上述条件。

提示:

  • 100 <= n <= 999

模拟

不一定真的要拼接起来,只需要得到每位数字就行

class Solution {
    public boolean isFascinating(int n) {
        int a = 2 * n;
        int b = 3 * n;
        List<Integer> list = new ArrayList<>();
        while(n != 0){
            list.add(n % 10);
            n = n / 10;
        }
        while(a != 0){
            list.add(a % 10);
            a = a / 10;
        }
        while(b != 0){
            list.add(b % 10);
            b = b / 10;
        }
        Set<Integer> set = new HashSet<>();
        for(int num : list){
            if(set.contains(num) || num == 0)
                return false;
            set.add(num);
        }
        return set.size() == 9 ? true : false;
    }
}

2730. 找到最长的半重复子字符串

难度中等3

给你一个下标从 0 开始的字符串 s ,这个字符串只包含 09 的数字字符。

如果一个字符串 t 中至多有一对相邻字符是相等的,那么称这个字符串是 半重复的

请你返回 s 中最长 半重复 子字符串的长度。

一个 子字符串 是一个字符串中一段连续 非空 的字符。

示例 1:

输入:s = "52233"
输出:4
解释:最长半重复子字符串是 "5223" ,子字符串从 i = 0 开始,在 j = 3 处结束。

示例 2:

输入:s = "5494"
输出:4
解释:s 就是一个半重复字符串,所以答案为 4 。

示例 3:

输入:s = "1111111"
输出:2
解释:最长半重复子字符串是 "11" ,子字符串从 i = 0 开始,在 j = 1 处结束。

提示:

  • 1 <= s.length <= 50
  • '0' <= s[i] <= '9'

双指针

https://leetcode.cn/problems/find-the-longest-semi-repetitive-substring/solution/shuang-zhi-zhen-hua-chuang-pythonjavacgo-nurf/

移动右指针 right,并统计相邻相同的情况出现了多少次,记作 same如果 same >1,则不断移动左指针 left 直到 s[left] = s[left] - 1,此时将一对相同的字符移到窗口之外。然后将 same 置为 1。然后统计子串长度 right - left + 1 的最大值

class Solution {
    public int longestSemiRepetitiveSubstring(String S) {
        char[] s = S.toCharArray();
        int ans = 1, left = 0, same = 0, n = s.length;
        for(int right = 1; right < n; right++){
            if(s[right] == s[right-1]){
                same += 1;
                if(same > 1){
                    for(left += 1; s[left] != s[left-1]; left++);
                    same = 1;
                }
            }
            ans = Math.max(ans, right - left + 1);
        }
        return ans;
    }
}

2731. 移动机器人

难度中等8

有一些机器人分布在一条无限长的数轴上,他们初始坐标用一个下标从 0 开始的整数数组 nums 表示。当你给机器人下达命令时,它们以每秒钟一单位的速度开始移动。

给你一个字符串 s ,每个字符按顺序分别表示每个机器人移动的方向。'L' 表示机器人往左或者数轴的负方向移动,'R' 表示机器人往右或者数轴的正方向移动。

当两个机器人相撞时,它们开始沿着原本相反的方向移动。

请你返回指令重复执行 d 秒后,所有机器人之间两两距离之和。由于答案可能很大,请你将答案对 109 + 7 取余后返回。

注意:

  • 对于坐标在 ij 的两个机器人,(i,j)(j,i) 视为相同的坐标对。也就是说,机器人视为无差别的。
  • 当机器人相撞时,它们 立即改变 它们的前进时间,这个过程不消耗任何时间。
  • 当两个机器人在同一时刻占据相同的位置时,就会相撞。
    • 例如,如果一个机器人位于位置 0 并往右移动,另一个机器人位于位置 2 并往左移动,下一秒,它们都将占据位置 1,并改变方向。再下一秒钟后,第一个机器人位于位置 0 并往左移动,而另一个机器人位于位置 2 并往右移动。
    • 例如,如果一个机器人位于位置 0 并往右移动,另一个机器人位于位置 1 并往左移动,下一秒,第一个机器人位于位置 0 并往左行驶,而另一个机器人位于位置 1 并往右移动。

示例 1:

输入:nums = [-2,0,2], s = "RLL", d = 3
输出:8
解释:
1 秒后,机器人的位置为 [-1,-1,1] 。现在下标为 0 的机器人开始往左移动,下标为 1 的机器人开始往右移动。
2 秒后,机器人的位置为 [-2,0,0] 。现在下标为 1 的机器人开始往左移动,下标为 2 的机器人开始往右移动。
3 秒后,机器人的位置为 [-3,-1,1] 。
下标为 0 和 1 的机器人之间距离为 abs(-3 - (-1)) = 2 。
下标为 0 和 2 的机器人之间的距离为 abs(-3 - 1) = 4 。
下标为 1 和 2 的机器人之间的距离为 abs(-1 - 1) = 2 。
所有机器人对之间的总距离为 2 + 4 + 2 = 8 。

示例 2:

输入:nums = [1,0], s = "RL", d = 2
输出:5
解释:
1 秒后,机器人的位置为 [2,-1] 。
2 秒后,机器人的位置为 [3,-2] 。
两个机器人的距离为 abs(-2 - 3) = 5 。

提示:

  • 2 <= nums.length <= 105
  • -2 * 109 <= nums[i] <= 2 * 109
  • 0 <= d <= 109
  • nums.length == s.length
  • s 只包含 'L''R'
  • nums[i] 互不相同。

脑筋急转弯

https://leetcode.cn/problems/movement-of-robots/solution/nao-jin-ji-zhuan-wan-pai-xu-tong-ji-pyth-we55/

class Solution {
    /**
    题目最后要求机器人之间的距离,此时把任意两个机器人的位置交换,并不会对答案产生影响。
    既然如此,那么可以把机器人都看成是完全一样的,无法区分。

    相撞等价于机器人互相穿过对方,因为我们无法区分机器人。 所以可以无视相撞的规则,把每个机器人都看成是独立运动的。
    类似的思路在 1503. 所有蚂蚁掉下来前的最后一刻 中出现过。
     */
    public int sumDistance(int[] nums, String s, int d) {
        final long MOD = (long) 1e9 + 7;
        int n = nums.length;
        var a = new long[n];
        for (int i = 0; i < n; i++) // 注意 2e9+1e9 溢出了
            a[i] = (long) nums[i] + d * ((s.charAt(i) & 2) - 1); // L=-1, R=1
        long ans = 0, sum = 0;
        Arrays.sort(a);
        // 从小到大枚举a[i],此时左边有i个数都不超过a[i], a[i]与其左侧机器人的距离之和为
        // a[i]-a[0] + (a[i]-a[1]) + ... + (a[i]-a[i-1]) = i * a[i] - (a[0] + a[1] + ... + a[i-1])
        for (int i = 0; i < n; i++) {
            ans = (ans + i * a[i] - sum) % MOD;
            sum += a[i];
        }
        return (int) ans;
    }
}

你可能感兴趣的:(算法刷题记录,leetcode,算法,职场和发展)