第十二周算法作业

Leetcode No. 692, 787, 934作业报告

No. 692

  • 思路
方法一:
直接使用sorted函数,重写cmp的排序算法,对整个序列进行排序,取前k个元素
注意的点:
1. python中的cmp方法需要返回值必须为 [1,-1,0]
2. 当不符合排序条件需要调整的时候返回1,符合的话返回-1,相等的话返回0,后两者不需要调整顺序

方法二:
定义一个Word类,重写def __lt__(self, other)方法
然后使用heapq.heappush(heap, Word(word, fre))和heapq.heappop(heap)方法对heap进行排序
采用与题目相反的排序,将前n-k个都pop掉,剩下的k个通过reverse获得最终答案
  • 代码
    方法一:
class Solution(object):
    def myCmp(self, a, b):
        # python中的cmp方法需要返回值必须为 [1,-1,0]
        # 当不符合排序条件需要调整的时候返回1,符合的话返回-1,相等的话返回0,后两者不需要调整顺序
        if a[0]==b[0]:
            #print(a[1], b[1], a[1]>b[1])
            if a[1]>b[1]:
                return 1
            return -1
        elif a[0]<b[0]:
            return 1
        return -1

    def topKFrequent(self, words, k):
        """
        :type words: List[str]
        :type k: int
        :rtype: List[str]
        """
        count = collections.Counter(words)
        items = [(val, key) for key, val in count.items()]
        itemsSorted = sorted(items, key = functools.cmp_to_key(self.myCmp))[:k]
        result = [(item[1]) for item in itemsSorted]
        return result

方法二:

class Word:
    def __init__(self, word, fre):
        self.word = word
        self.fre = fre
    def __lt__(self, other):
        if self.fre != other.fre:
            return self.fre < other.fre
        return self.word > other.word

class Solution:
    def topKFrequent(self, words: List[str], k: int) -> List[str]:

        cnt = collections.Counter(words)
        heap = []

        for word, fre in cnt.items():
            heapq.heappush(heap, Word(word, fre))
            if len(heap) > k:
                heapq.heappop(heap)

        heap.sort(reverse=True)
        return [x.word for x in heap]
  • 作业截图
    方法一:
    在这里插入图片描述
    方法二:
    在这里插入图片描述

No. 787

  • 思路
使用二维数组进行动态规划,定义dp[N][k]为在最多k个中转站的限制条件之下从src到达N的最短距离
动态规划,在k个中转限制下飞到目的地的最便宜价格等于
在k-1个中转限制下飞到目的地的最便宜价格或者利用额外一个中转地到目的地 的最低价格
因此状态转移方程为:dp[v][k] = min({dp[v][k - 1], dp[v][k], dp[u][k - 1] + w})
  • 代码
class Solution(object):
    def findCheapestPrice(self, N, flights, src, dst, K):
        dp = [[float('inf')] * (K + 1) for _ in range(0, N)]
        K = min(K, N - 2);
        # 最基本的直接飞到目的地
        dp[src][0] = 0
        # 对dp二维数组进行初始化
        for flight in flights:
           start = flight[0]
           end = flight[1]
           price = flight[2]
           if (start == src) :
                dp[end][0] = min(dp[end][0], price)

        for k in range(1, K + 1):
            for flight in flights:
                u = flight[0];
                v = flight[1];
                w = flight[2];
                # 动态规划,在k个中转限制下飞到目的地的最便宜价格等于
                # 在k-1个中转限制下飞到目的地的最便宜价格或者利用额外一个中转地到目的地 的最低价格
                dp[v][k] = min({dp[v][k - 1], dp[v][k], dp[u][k - 1] + w})

        return -1 if dp[dst][K] == float('inf') else dp[dst][K]
  • 作业截图
    在这里插入图片描述

No. 934

  • 思路
 采用dfs+bfs
 因为存在两个不相连的岛,所以需要先用dfs,将其中一个岛的所有1找到并标识为2(与0和另一个岛的1区分开来)
 将遍历过的2存入一个队列中
 然后以该队列中的所有点为起点进行bfs遍历,直到遇到1为止则中止bfs遍历
 需要注意的是,遍历的时候不要出界;遍历过的点需要表示为2(表示已经遍历过)
  • 代码
class Solution:
    def __init__(self):
        # 记录访问过的位置
        self.visited = []
    # 深度搜索,目的在与找到第一座岛并将其标记2这样可以不跟第二个冲突
    def dfs(self, A, i, j):
        # 记录岛的位置
        self.visited.append((i, j))
        A[i][j] = 2
        # 遍历四个方向
        for k, l in [(-1, 0), (0, 1), (1, 0), (0, -1)]:
            r = k + i
            c = l + j
            # 判断移动后的合理性
            if r < 0 or r >= len(A) or c < 0 or c >= len(A[0]):
                continue
            # 如果是0或者标记过的2则继续
            if A[r][c] == 0 or A[r][c] == 2:
                continue
            # 同一个岛的进行递归
            self.dfs(A, r, c)


    def shortestBridge(self, A):
        maxr, maxc = len(A), len(A[0])
        for i in range(maxr):
            for j in range(maxc):
                # 碰到第一个的时候开始深度搜索来找到第一个岛
                if A[i][j] == 1:
                    self.dfs(A, i, j)
                    # !!!注意这里只需要找到第一个岛,深度搜索后需要跳出两层循环,用for...else...结构
                    break
            else:
                continue
            break

        # step记录广度搜索的宽度
        step = 0
        # vist有的时候
        while self.visited:
            # 记录这次需要进行搜索的个数,这么做是因为后面搜索过程中会再添加
            vl = len(self.visited)
            # 将依次搜索本次step广度的各个节点
            for v in range(vl):
                i,j = self.visited.pop(0)
                for k,l in  [(-1, 0), (0, 1), (1, 0), (0, -1)]:
                    r = k + i
                    c = l + j
                    if r < 0 or r >= len(A) or c < 0 or c >= len(A[0]):
                        continue
                    if A[r][c] == 2:
                        continue
                    # step广度是由浅岛深,任何依次找到下一个岛即可返回step了
                    if A[r][c] == 1:
                        return step
                    # 否则经过0的话需要将位置标记为2,代表搜索过了,并且需要加入vist,
                    # 因为下一个广度也需要搜索其周围
                    A[r][c] = 2
                    self.visited.append((r, c))
            step += 1
        # 都没有则返回最大的广度
        return step
  • 作业截图
    在这里插入图片描述
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值