美文网首页
2020-3-1 刷题记录

2020-3-1 刷题记录

作者: madao756 | 来源:发表于2020-03-01 23:44 被阅读0次

    前言:每天写这个的目的就是能够每天回忆一遍今天做过的题,如果哪里需要总结的单独拿出来

    0X00 leetcode 做了 5 道

    0X01 每道题的小小总结

    动态规划是道难啃的题目,我感觉每天都要做一做

    323. Number of Connected Components in an Undirected Graph

    并查集模板题目

    class UnionFind:
        def __init__(self, n):
            self.father = [i for i in range(n)]
            self.count = n
    
        def find(self, x):
            if self.father[x] != x:
                self.father[x] = self.find(self.father[x])
            return self.father[x]
        
        def union(self, x, y):
            fx, fy = self.find(x), self.find(y)
            if fx != fy:
                self.count -= 1
                self.father[fy] = fx
    
    class Solution:
        def countComponents(self, n: int, edges: List[List[int]]) -> int:
            uf = UnionFind(n)
    
            for x, y in edges:
                uf.union(x, y)
            
            return uf.count
    

    261. Graph Valid Tree

    也是动态规划的模板题,

    坑的地方在: 不能有离散的点

    class UnionFind:
        def __init__(self, n):
            self.fathers = [i for i in range(n)]
            self.count = n
        
        def find(self, x):
            if self.fathers[x] != x:
                self.fathers[x] = self.find(self.fathers[x])
            return self.fathers[x]
        
        def union(self, x, y):
            fx, fy = self.find(x), self.find(y)
            if fx == fy:
                return False
            self.fathers[fy] = fx
            self.count -= 1
            return True
    
    class Solution:
        def validTree(self, n: int, edges: List[List[int]]) -> bool:
            uf = UnionFind(n)
    
            for x, y in edges:
                if not uf.union(x, y):
                    return False
            
            return uf.count == 1
    

    305. Number of Islands II

    关键在于「集合合并」, 所以是并查集的题目,

    不过是一个二维并查集

    class UnionFind:
        def __init__(self, m, n):
            l = m * n
            self.m = m
            self.n = n
            self.fathers = [i for i in range(l)]
        
        def pos2idx(self, p):
            x, y = p
            return x * self.n + y
        
        def find(self, idx):
            if self.fathers[idx] != idx:
                self.fathers[idx] = self.find(self.fathers[idx])
            return self.fathers[idx]
        
        def union(self, p1, p2):
            idx1, idx2 = self.pos2idx(p1), self.pos2idx(p2)
            f1, f2 = self.find(idx1), self.find(idx2)
            if f1 == f2:
                return False
            self.fathers[f1] = self.fathers[f2]
            return True  
        
    class Solution:
        def numIslands2(self, m: int, n: int, positions: List[List[int]]) -> List[int]:
            if len(positions) == 0: return [0]
            
            lands = set()
            res = []
            uf = UnionFind(m, n)
            count = 0
    
            dirs = [(1, 0), (-1, 0), (0, 1), (0, -1)]
            for p in positions:
                count += 1
                idx = uf.pos2idx(p)
                if idx in lands: 
                    count -= 1
                    res.append(count)
                    continue
                lands.add(idx)
                x, y = p
                for dx, dy in dirs:
                    x1, y1 = x + dx, y + dy
                    if x1 < 0 or y1 < 0 or x1 >= m or y1 >= n: continue
                    if uf.pos2idx((x1, y1)) not in lands: continue
                    # print("x1, y1 ", x1, y1)
                    if uf.union(p, (x1, y1)): count -= 1
                # print("---------------")
                
                res.append(count)
    
            return res
    

    关于并查集的一些小总结我都写到这里:

    2020-3-1 并查集小总结

    200. Number of Islands

    标准网格型 dfs 题目,知道那个模板直接秒

    class Solution:
        def numIslands(self, grid: List[List[str]]) -> int:
    
            if len(grid) == 0: return 0
    
            m, n = len(grid), len(grid[0])
            visited = [[False] * n for _ in range(m)]
            count = 0
    
            def dfs(x, y):
                if x < 0 or x >= m or y < 0 or y >= n: return
                if grid[x][y] == "0" or visited[x][y]: return
                visited[x][y] = True
                dirs = [(-1, 0), (0, 1), (1, 0), (0, -1)]
                for dx, dy in dirs:
                    dfs(x + dx, y + dy)
    
            for x in range(m):
                for y in range(n):
                    if grid[x][y] == "1" and not visited[x][y]:
                        dfs(x, y)
                        count += 1
    
            return c
    

    300. Longest Increasing Subsequence

    动态规划...每天来一道...

    首先一个 O(n^2) 的做法

    class Solution:
        def lengthOfLIS(self, nums: List[int]) -> int:
            # 一维坐标型动态规划
            # dp[x] 代表 包含 x 的最长子序列
            # dp[x] = 从 0 ~ x -1 寻找一个比 nums[x] 小的,而且 dp 最大的 
            # 答案取最大值
            if len(nums) == 0: return 0
            m = len(nums)
            dp = [1] * m
            ans = 1
            for i in range(1, m):
                for j in range(i-1, -1, -1):
                    if nums[i] > nums[j]:
                        dp[i] = max(dp[i], dp[j] + 1) 
                
                ans = max(ans, dp[i])
            
            return ans
    

    第二种解法,直接从这个序列里面找到最长上升子序列

    class Solution:
        def lengthOfLIS(self, nums: List[int]) -> int:
            if len(nums) == 0: return 0
            # 维护一个最长子序列
            m = len(nums)
            record = [0] * m
            # init 
            record[0] = nums[0]
            ans = 1
    
            for i in range(1, m):
                left, right = 0, ans - 1
                while left <= right:
                    mid = left + (right - left) // 2
                    if record[mid] == nums[i]: 
                        left = mid
                        break
                    if record[mid] < nums[i]:
                        left = mid + 1
                    else:
                        right = mid - 1
                
                record[left] = nums[i]
                if left == ans:
                    ans += 1
            
            return ans
    

    record[i] 记录了 i+1 长度 的最小的那个值, 时间复杂度 O(nlogn)

    这里还用到了二分查找的模板,我在这里复习一下

    left, right = 0, len(nums) - 1
    while left <= right:
        mid = left + (right - left)
        if nums[mid] == target:
            left = mid
            break
        elif nums[mid] < target:
            left = mid + 1
        else:
            right = mid - 1
            
    # 最后 left 是插入的位置
    

    相关文章

      网友评论

          本文标题:2020-3-1 刷题记录

          本文链接:https://www.haomeiwen.com/subject/jcpdkhtx.html