力扣第 187 场周赛小结(有collections、bisect的用法)滑动窗口法解题

这是第三次参赛,只完成做出了第二题,第三题做一半。其他参考各位大神做法。

一、旅行终点站

1、题目描述:
https://leetcode-cn.com/problems/destination-city/

在这里插入图片描述
在这里插入图片描述
2、题解:
创建一个集合res,创建一个Counter,先遍历paths一次,将路径中的第一个值的次数+1,并且把路径的两个值添加到res中。再次在res中遍历,查看出现的次数,如果次数为0那么就是终点。

class Solution:
    def destCity(self, paths: List[List[str]]) -> str:
        res = set()
        c = collections.Counter()#创建一个Counter
        for path in paths:#让paths中的每一个元素都添加到res中,并将每个path的第一个值出现的次数+1
            c[path[0]] += 1
            res.add(path[0])
            res.add(path[1])
        for x in res:#遍历,查看出现次数为0的就是终点
            if c[x] == 0:
                return x

创建一个集合res,放入所有路径的第二个值,遍历paths一次,如果路径的第一个值在res中,那么删除,最终剩下的就是终点。

class Solution:
    def destCity(self, paths: List[List[str]]) -> str:
        res = set(path[1] for path in paths)
        for path in paths:
            if path[0] in res:
                res.remove(path[0])
        return list(res)[0]

集合去重法,两个集合分别存开头和结尾,差集运算后,剩下的元素就是终点。

class Solution:
    def destCity(self, paths: List[List[str]]) -> str:
        n = len(paths)
        begin = set()  # 存储所有起点
        end = set()  # 存储所有终点
        for i in range(n):
            begin.add(paths[i][0])
            end.add(paths[i][1])
        print(begin, end)
        where = list(end - begin)  # 集合的差集运算
        print(where)
        return where[0]

3、注意:
collections模块的defaultdict和Counter用法:

defaultdict: dict在使用时,当key值不存在时,直接添加value时会出现错误,使用defaultdict可以很好的规避该错误。defaultdict是对字典类型的补充,它可以给字典的值设置一个类型,当key不存在时可以自动生成相应类型的value。
Counter: 字典子类,为可以哈希的对象计数。追踪元素出现的次数并按照从高到低的顺序排列成字典,对象为key,出现的次数为value。

b = set()
c = collections.Counter()
for p in paths:
    c[p[0]] += 1
    b.add(p[0])
    b.add(p[1])
    print(c)
print(c['djz'])

打印出:

Counter({'London': 1})
Counter({'London': 1, 'New York': 1})
Counter({'London': 1, 'New York': 1, 'Lima': 1})
0

二、是否所有 1 都至少相隔 k 个元素

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

在这里插入图片描述
在这里插入图片描述
2、题解:
自己的解法:
滑动窗口法,维护一个首尾是1的窗口,不断往后走,遇到间隔小于k的直接返回False,否则,走到最后都没遇到,则返回T#

class Solution:
    def kLengthApart(self, nums, k) :
        #滑动窗口法
        if nums == []:
            return False
        left,right = 0,0
        while left <len(nums)-1 and right < len(nums)  :
            if nums[left] != 1:#先找窗口的左侧为1的下标
                left += 1
            elif nums[left] == 1:#若窗口的左侧为1,再找窗口的右侧为1的下标
                right = left+1 #赋初值
                while right <len(nums)-1 and nums[right] != 1:#找窗口右侧为1的下标
                    right += 1
                if nums[right] == 1:#找到窗口的左右,则计算间隔,并与k进行比较
                    temp = right - left -1
                    if temp < k:
                        return False
                    left =right #移动,新窗口的左侧为原窗口的右侧。继续进行下个循环
                elif right == len(nums) -1 :#考虑[1,0,0,0,0]这种情况
                    break
        return True

设置哨兵,并更新哨兵,只要有一个间隔小于k的情况,就返回False。

class Solution:
    def kLengthApart(self, nums: List[int], k: int) -> bool:
        pre = -k -1 #哨兵,上一个1所在位置下标
        for i in range(len(nums)):
            if nums[i] == 1:
                if i - pre - 1 < k :#间隔有小于k的情况,直接返回False
                    return False
                pre  = i
        return True

三、绝对差不超过限制的最长连续子数组

1、题目描述:
https://leetcode-cn.com/problems/longest-continuous-subarray-with-absolute-diff-less-than-or-equal-to-limit/

在这里插入图片描述
在这里插入图片描述
2、题解:
滑动窗口法:引入bisect,题后有具体讲解。res是一个有序的数组,很容易得出最大、最小值。维护一个窗口,使窗口里的最大值与最小值之差不大于limit,如果有大于limit的,循环取出最左边的元素,并移动窗口的左侧;否则移动窗口的右侧。

class Solution:
    def longestSubarray(self, nums: List[int], limit: int) -> int:
        l, r, res, ans = 0, 0, [], 0
        while r < len(nums):
            bisect.insort(res, nums[r])
            while res[-1] - res[0] > limit:
                res.remove(nums[l])
                l += 1
            r += 1
            ans = max(ans, len(res))
        return ans

3、注意:
1、bisect模块的bisect和insort的用法:
bisect.bisect(a,b): a为列表,b为一个元素:bisect 返回b在列表a中的下标(此时a未改变)。假定列表是有序的。若列表无序,那么会返回插入到列表最后一个合适的位置。
bisect.insort (a,c) : a为列表,b为一个元素:会在列表a中插入元素c到正确位置,假定列表有序(无返回值)。如果列表无序,那么会返回空。默认插入到右边。

a = [1,2]
b = bisect.bisect(a,3)
print(a,b)

c = bisect.insort(a,3)
print(a,c)

结果:

[1, 2] 2
[1, 2, 3] None

2、remove(obj): 移除列表中某个值的第一个匹配(无返回值)。obj为列表中的值
列表的list.pop([index=-1]) 移除列表中的一个元素(默认最后一个元素),并且返回该元素的值。index为下标
字典的set.pop(key[,default]) 删除字典给定键 key 所对应的值,返回值为被删除的值。key值必须给出。 否则,返回default值。

a = [1,2,3,4]
a.remove(3)
print(a)

b = a.pop()
print(a,b)
e = a.pop(0)
print(a,e)

c = {'djz':1,'lsd':2,'dd':3}
d = c.pop('djz')
print(c,d)

结果:

[1, 2, 4]
[1, 2] 4
[2] 1
{'lsd': 2, 'dd': 3} 1

四、有序矩阵中的第 k 个最小数组和

1、题目描述:
https://leetcode-cn.com/problems/find-the-kth-smallest-sum-of-a-matrix-with-sorted-rows/

在这里插入图片描述
在这里插入图片描述
2、题解:
不断更新res值

class Solution:
    def kthSmallest(self, mat: List[List[int]], k: int) -> int:
        #不断更新
        #m ,n = len(mat),len(mat[0])
        res = mat[0]
        for row in mat[1:]:
            t = []
            for x in row:
                for y in res:
                    t.append(x+y)
            res = sorted(t)[:k]            
        return res[-1] 

bisect方法:

class Solution:
    def kthSmallest(self, mat: List[List[int]], k: int) -> int:
        import bisect
        res = []
        for row in mat:
            if not res:
                res = mat[0]
            else:
                temp = []
                for x in row:
                    for y in res:
                        bisect.insort(temp, x + y)
                res = temp
            if len(res) > k:
                res = res[:k]
        return res[-1]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值