【LeetCode周赛】第195场周赛

一、1496. 判断路径是否相交

给你一个字符串 path,其中 path[i] 的值可以是 'N'、'S'、'E' 或者 'W',分别表示向北、向南、向东、向西移动一个单位。

机器人从二维平面上的原点 (0, 0) 处开始出发,按 path 所指示的路径行走

如果路径在任何位置上出现相交的情况,也就是走到之前已经走过的位置,请返回 True ;否则,返回 False

示例:

img 输入:path = "NESWW" 输出:true 解释:该路径经过原点两次。

分析:

​ 一开始看错题目,如果只需要判断是否能回到原点,可以利用类似栈的思想。如果需要判断所有走过的位置,也只需要使用字典或者数组记录就可以解决。

代码(Python):

class Solution:
    def isPathCrossing(self, path: str) -> bool:
        if not path:
            return False
        n = len(path)
        pos = defaultdict(bool)
        pos[(0, 0)] = True
        vert = 0
        hor = 0
        for val in path:
            if val == "N":
                vert += 1
            elif val == "E":
                hor += 1
            elif val == "S":
                vert -= 1
            elif val == "W":
                hor -= 1
            if pos[(hor, vert)]:
                return True
            else:
                pos[(hor, vert)] = True
        return False

二、1497. 检查数组对是否可以被 k 整除

给你一个整数数组 arr 和一个整数 k ,其中数组长度是偶数,值为 n

现在需要把数组恰好分成 n / 2 对,以使每对数字的和都能够被 k 整除。

如果存在这样的分法,请返回 True ;否则,返回 False

示例:

输入:arr = [1,2,3,4,5,10,6,7,8,9], k = 5
输出:true
解释:划分后的数字对为 (1,9),(2,8),(3,7),(4,6) 以及 (5,10) 。

输入:arr = [1,2,3,4,5,6], k = 7
输出:true
解释:划分后的数字对为 (1,6),(2,5) 以及 (3,4) 。

分析:

​ 如果我们暴力枚举每一对组合,并且判断是否被k整除,时间复杂度会相当高。原因之一:例如我们选择1,我们无法非常明显的找到我们所需要的配对元素。二:对于多个配对的元素,如何进行选择?

解决:

​ 1可以与4, 9相加后被5整除。但是并不直观,如果我们对数组中每个元素 先对k取余

(1 o 1, 4 o 4, 9 o 4)

这样就可以通过两个余数相加,是否为k或0来判断,更加直观。

​ 如上例,1可以与两个数配对。而可能只有一个数才可以使所有数满足要求。如何进行选择?

将余数作为键,存储所有值的个数,进行匹配即可。

代码(Python):

class Solution:
    def canArrange(self, arr: List[int], k: int) -> bool:
        mod = collections.Counter(num % k for num in arr)
        for t, occ in mod.items():
            if t > 0 and (k - t not in mod or mod[k - t] != occ):
                return False
        return mod[0] % 2 == 0

三、1498. 满足条件的子序列数目

给你一个整数数组 nums 和一个整数 target 。

请你统计并返回 nums 中能满足其最小元素与最大元素的 和 小于或等于 target 的 非空 子序列的数目。

由于答案可能很大,请将结果对 10^9 + 7 取余后返回。

示例:

输入:nums = [3,5,6,7], target = 9
输出:4
解释:有 4 个子序列满足该条件。
[3] -> 最小元素 + 最大元素 <= target (3 + 3 <= 9)
[3,5] -> (3 + 5 <= 9)
[3,5,6] -> (3 + 6 <= 9)
[3,6] -> (3 + 6 <= 9)

输入:nums = [3,3,6,8], target = 10
输出:6
解释:有 6 个子序列满足该条件。(nums 中可以有重复数字)
[3] , [3] , [3,3], [3,6] , [3,6] , [3,3,6]

分析:

​ 看到数组,最大值、最小值、和这些关键字,就可以想到利用滑动窗口解决问题了。

​ 首先进行排序,确保数组元素升序。接着从right指针开始寻找符合要求的第一个位置,接着往右移动,不断累加计算。

代码(Python):

class Solution:
    def numSubseq(self, nums: List[int], target: int) -> int:
        nums.sort()
        if nums[0] * 2 > target:
            return 0
        n = len(nums)
        ans = 0
        left, right = 0, n - 1
        while right >= left:
            if nums[left] + nums[right] <= target:
                ans += 2 ** (right - left)
                left += 1
            else:
                right -= 1
        return ans % (10 ** 9 + 7)

原文地址:https://www.cnblogs.com/enmac/p/13246016.html