【leetcode系列】【算法】第187 场周赛

题目一:

题目链接: https://leetcode-cn.com/problems/destination-city/

 

解题思路:

把所有起终点信息,放入到hash表中,key = 起点,val = 终点

然后遍历hash表,如果某个终点在hash表中没有对应的key,说明是最终终点

 

代码实现:

class Solution:
    def destCity(self, paths: List[List[str]]) -> str:
        rec = {a : b for a, b in paths}
        for key in rec:
            dst = rec[key]
            if dst not in rec:
                return dst

        return ''

 

题目二:

题目链接: https://leetcode-cn.com/problems/check-if-all-1s-are-at-least-length-k-places-away/

 

解题思路:

双指针,遍历数组的同时,使用一个指针指向上一个1的位置

遍历中间遇到1时,计算与上一个1的距离,并更新上一个1的位置到当前位置

 

代码实现:

class Solution:
    def kLengthApart(self, nums: List[int], k: int) -> bool:
        last_pos = -1
        for idx, a in enumerate(nums):
            print(last_pos, idx)
            if a != 1:
                continue
            elif last_pos == -1:
                last_pos = idx
                continue
            elif idx - last_pos - 1 < k:
                return False

            last_pos = idx

        return True

 

题目三:

题目链接: https://leetcode-cn.com/problems/longest-continuous-subarray-with-absolute-diff-less-than-or-equal-to-limit/

 

解题思路:

遍历数组的同时,记录当前遍历子串中的最大值、最大值位置、最小值、最小值位置

如果发现最大值 - 最小值 > limit,则使用min(最大值位置, 最小值位置)的下一位重新开始遍历

 

代码实现:

class Solution:
    def longestSubarray(self, nums: List[int], limit: int) -> int:
        # 记录的最小值信息
        min_info = [nums[0], 0]
        # 记录的最大值信息
        max_info = [nums[0], 0]
        # idx : 遍历指针,从1开始
        # longest : 最长子串
        # curr_len : 当前子串长度
        # 因为是从第二位开始遍历,所以两个长度初始化为1
        idx = longest = curr_len = 1
        while idx < len(nums):
            curr_num = nums[idx]
            # 判断当前值与最大、最小值的绝对差,取最大的一个
            curr_diff = max(abs(curr_num - min_info[0]), abs(curr_num - max_info[0]))
            # 如果最大的绝对差比limit小, 更新信息, 继续遍历
            if curr_diff <= limit:
                # 更新当前长度+1
                curr_len += 1
                # 更新最大子串长度
                longest = max(longest, curr_len)
                # 更新最大、最小值信息
                if curr_num <= min_info[0]:
                    min_info = [curr_num, idx]

                if curr_num >= max_info[0]:
                    max_info = [curr_num, idx]

                # 向后移动指针
                idx += 1
                continue

            # 如果当前值不符合要求
            # 从最大值、最小值下标中更小一个的下一位重新开始遍历
            idx = min(min_info[1], max_info[1]) + 1
            # 保护性判断
            if idx >= len(nums):
                break

            # 更新当前长度为1
            curr_len = 1
            # 更新最大、最小值信息为最大值、最小值下标更小一个的下一位信息
            min_info = [nums[idx], idx]
            max_info = [nums[idx], idx]
            # 向后移动指针
            idx += 1

        return longest

 

题目四:

题目链接: https://leetcode-cn.com/problems/find-the-kth-smallest-sum-of-a-matrix-with-sorted-rows/

 

解题思路:

专门截图了提示,是因为有k <= 200的限制,所以直接暴力,最终是没有超时的

暴力的方法就不解释了,这里只写二分查找

具体逻辑写在代码注释中

 

代码实现:

class Solution:

    def kthSmallest(self, mat: List[List[int]], k: int) -> int:
        def dfs(mat, k, max_sum, idx, curr_sum, cnt):
            # 计算所有小于max_sum的个数
            # 递归退出条件
            # 额外注意的是cnt[0] > k这个条件,只要当前小于max_sum的个数已经大于k了,就不需要继续遍历了
            # 因为已经知道如何继续下一次遍历查找了
            if idx == len(mat) or curr_sum > max_sum or cnt[0] > k:
                return

            # 因为curr_sum的初始值为原始的left值,所以先递归到最后一层开始,从最后一层的第二个数还是加
            dfs(mat, k, max_sum, idx + 1, curr_sum, cnt)

            # 遍历当前层数组从第二个数字开始的和,是否小于max_sum
            for i in range(1, len(mat[idx])):
                # 因为每层数组只能取一个元素,所以更新当前和时,需要减去第一个元素的值
                tmp_sum = curr_sum + mat[idx][i] - mat[idx][0]
                # 剪枝条件,如果当前和已经大于max_sum,则后续的所有值也大于
                # 因为只计算小于的个数, 所以此时退出
                if tmp_sum > max_sum:
                    break

                # 更新结果数目
                cnt[0] += 1
                # 以当前和为基准,继续遍历之后的每一层
                dfs(mat, k, max_sum, idx + 1, tmp_sum, cnt)

            return

        left = right = 0
        for idx in range(len(mat)):
            # 每一层最小数字相加
            left += mat[idx][0]
            # 每一层最大数字相加
            right += mat[idx][-1]

        # 因为遍历过程中,需要更新left的值
        # 但是每次dfs遍历时,需要使用最小值进行当前值的计算
        # 所以此处记录最小值(详细见dfs中for循环内第一个注释内容)
        base = left
        while left < right:
            mid = (left + right) // 2
            cnt = [1]
            dfs(mat, k, mid, 0, base, cnt)
            if cnt[0] < k:
                left = mid + 1
            else:
                right = mid

        return right

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值