LeetCode-算法:71-80(Python)


71. 简化路径

在这里插入图片描述
思路

  1. 以"/"分隔输入路径path保存在catelog中
  2. 不为空或不为当前目录".“或上一级目录”…“时,将目录名插入ans列表,遇到”.“时不作操作,遇到”…"时ans.pop()掉最后一个目录,即返回上一级目录
  3. 连接ans中的目录
class Solution(object):
    def simplifyPath(self, path):
        """
        :type path: str
        :rtype: str
        """
        catelog = path.split('/')
        ans = list()
        for item in catelog:
            if item and item not in [".", ".."]:
                ans.append(item)
            elif item == ".":
                pass
            elif item == "..":
                if not ans:
                    pass
                else:
                    ans.pop()
        return "/"+"/".join(ans)



72. 编辑距离

在这里插入图片描述
思路
word1插入 等价 word2删除
word1删除 等价 word2插入
word1替换 等价 word2替换

动态规划

  1. m为word1的长度,n为word2的长度。当word1或word2其一为空或都为空时,需要n+m次操作
  2. 创建dp数组,初始化dp[i]0,同理初始化dp[0][j]
  3. 计算dp数组中的值dp[i][j]
    • dp[i-1][j]为word1的前i-1个字符和word2的前j个字符的操作距离。在word1后操作1个字符得到dp[i][j],即dp[i-1][j]+1
    • dp[i][j-1]为word1的前i个字符和word2的前j-1个字符的操作距离。在word2后操作1个字符得到dp[i][j],即dp[i][j-1]+1
    • dp[i-1][j-1]为word1的前i-1个字符和word2的前j-1个字符的操作距离。word1的第i个字符不等于word2的第j个字符时,dp[i-1][j-1]操作1个字符得到dp[i][j],即dp[i][j-1]+1;word1的第i个字符等于word2的第j个字符时,dp[i-1][j-1]无需操作得到dp[i][j],即dp[i][j-1]
  4. 得到状态转移方程
    • word[i]!=word[j]时,dp[i][j]=min(dp[i-1][j]+1, dp[i][j-1]+1, dp[i][j-1]+1)==1+min(dp[i-1][j], dp[i][j-1], dp[i][j-1])
    • word[i]==word[j]时,dp[i][j]=min(dp[i-1][j]+1, dp[i][j-1]+1, dp[i][j-1])==1+min(dp[i-1][j], dp[i][j-1], dp[i][j-1]-1)

栗子:

e5443
s4332
r3222
o2212
h1123
#0123
-#ros
class Solution(object):
    def minDistance(self, word1, word2):
        """
        :type word1: str
        :type word2: str
        :rtype: int
        """
        m, n = len(word1), len(word2)
        if n*m == 0:
            return n+m
        dp = [[0]*(n+1) for _ in range(m+1)]
        for i in range(m+1):
            dp[i][0] = i
        for j in range(n+1)    :
            dp[0][j] = j
        for i in range(1, m+1):
            for j in range(1, n+1):
                dp[i][j] = 1 + min(dp[i-1][j], dp[i][j-1], dp[i-1][j-1]) if word1[i-1] != word2[j-1] else 1 + min(dp[i-1][j], dp[i][j-1], dp[i-1][j-1]-1)
        return dp[-1][-1]



73. 矩阵置零

在这里插入图片描述
思路

  1. 创建row, col保存matrix中值为0的行和列
  2. 将row中的行元素置0,将col中的列元素置0
class Solution(object):
    def setZeroes(self, matrix):
        """
        :type matrix: List[List[int]]
        :rtype: None Do not return anything, modify matrix in-place instead.
        """
        if not matrix:
            return matrix
        n, m = len(matrix), len(matrix[0])
        row, col = set(), set()
        for i in range(n):
            for j in range(m):
                if matrix[i][j]==0:
                    row.add(i)
                    col.add(j)

        for r in row:
            matrix[r]=[0 for _ in range(m)]
        for c in col:
            for i in range(n):
                matrix[i][c]=0
        return matrix



74. 搜索二维矩阵

在这里插入图片描述
思路
遍历matrix元素,查找是否存在target,是返回True,否返回False

class Solution(object):
    def searchMatrix(self, matrix, target):
        """
        :type matrix: List[List[int]]
        :type target: int
        :rtype: bool
        """
        if not matrix:
            return False
        n = len(matrix)
        for i in range(n):
            if target in matrix[i]:
                return True
        return False

思路
matrix全部元素看作有序数组,然后使用二分查找target

class Solution(object):
    def searchMatrix(self, matrix, target):
        """
        :type matrix: List[List[int]]
        :type target: int
        :rtype: bool
        """
        if not matrix:
            return False
        m , n = len(matrix), len(matrix[0])
        left, right =0, m*n-1
        while left <= right:
            mid = (left+right)//2 
            r, c = mid//n, mid%n
            if matrix[r][c] == target:
                return True
            elif matrix[r][c] > target:
                right = mid - 1
            else:
                left = mid + 1
        return False



75. 颜色分类

在这里插入图片描述
思路
一个直观的解决方案是使用计数排序的两趟扫描算法。
首先,迭代计算出0、1 和 2 元素的个数,然后按照0、1、2的排序,重写当前数组。

class Solution(object):
    def sortColors(self, nums):
        """
        :type nums: List[int]
        :rtype: None Do not return anything, modify nums in-place instead.
        """
        n = len(nums)
        n0, n1, n2 = 0, 0, 0
        for num in nums:
            if num == 0:
                n0 += 1
            elif num == 1:
                n1 += 1
            else:
                n2 += 1

        nums[:n0] = [0 for _ in range(n0)]
        nums[n0:n0+n1] = [1 for _ in range(n1)]
        nums[n0+n1:n0+n1+n2] = [2 for _ in range(n2)]
        return nums

思路
快速排序

class Solution(object):
    def sortColors(self, nums):
        """
        :type nums: List[int]
        :rtype: None Do not return anything, modify nums in-place instead.
        """
        left, right = 0, len(nums)-1
        def QuickSort(nums, left, right):
            if left < right:
                i = left
                j = right
                key = nums[i]
                while i < j:
                    while i < j and nums[j] >= key:
                        j -= 1
                    nums[i] = nums[j]
                    while i < j and nums[i] < key:
                        i += 1
                    nums[j] = nums[i]
                nums[i] = key
                QuickSort(nums, left, i-1)
                QuickSort(nums, i+1, right)
            return nums

        QuickSort(nums, left, right)
        return nums

思路

  1. left记录0的边界,right记录2的边界
  2. cur遇到0时,和left交换值,更新left+=1,cur+1;cur遇到2时,和right交换值,更新right-=1,cur不变;当cur遇到1时,cur+1

栗子:
在这里插入图片描述

class Solution(object):
    def sortColors(self, nums):
        """
        :type nums: List[int]
        :rtype: None Do not return anything, modify nums in-place instead.
        """
        left, right, cur = 0, len(nums)-1, 0
        while cur <= right:
            if nums[cur] == 0:
                nums[cur], nums[left] = nums[left], nums[cur]
                left += 1
                cur += 1
            elif nums[cur] == 2:
                nums[cur], nums[right] = nums[right], nums[cur]
                right -= 1
            else:
                cur += 1
        return nums



76. 最小覆盖子串

在这里插入图片描述
思路

  1. l, r双指针,r往右走(r = r+1);字符串t的字母和对应的个数记录为dict_t(键为字母,值为字母个数),字符串s的字母和对应的个数记录为dict_s;required记录dict_t的长度,即字母数,当dict_s和dict_t相同字母的个数相同时,ack加1;ans记录s中包含t所有字母的最小子串的长度,初始化为无穷大;left, right记录ans的左边和右边
  2. 当required与ack相等时,即dist_s(s的子串s[l, r])中包含了dist_t(字符串t),如果r-l+1小于原ans,则更新ans=r-1+1, left=l, right=r。
  3. l往右走时(l = l+1),丢弃字母s[l],如果s[l]存在字符串t中,则ack减1,及dist_s中不再包含所有的dist_t。如果s[l]不存在字符串t中,大胆往右走,啥也不影响。
class Solution(object):
    def minWindow(self, s, t):
        """
        :type s: str
        :type t: str
        :rtype: str
        """
        from collections import Counter
        if not s or not t or len(t) > len(s):
            return ""
        if t == s:
            return t
        n = len(s)
        dict_t, dict_s = dict(Counter(t)), dict()
        required, ack = len(dict_t), 0
        l, r, left, right, ans = 0, 0, 0, 0, float("inf")
        while r < n:
            char = s[r]
            # Python 字典(Dictionary) get() 函数返回指定键的值,如果值不在字典中返回默认值
            dict_s[char] = dict_s.get(char, 0) + 1 
            if char in dict_t and dict_s[char] == dict_t[char]:
                ack += 1
            while l <= r and required == ack:
                if r-l+1<ans:
                    left, right = l, r
                    ans = r-l+1
                char = s[l]
                dict_s[char] -= 1
                if char in dict_t and dict_s[char] < dict_t[char]:
                    ack -= 1    
                l += 1
            r += 1
        
        return "" if ans == float("inf") else s[left:right+1]



77. 组合

在这里插入图片描述
思路
回溯

class Solution(object):
    def combine(self, n, k):
        """
        :type n: int
        :type k: int
        :rtype: List[List[int]]
        """
        def backtrack(first=1, ele=list()):
            if len(ele[:]) == k:
                ans.append(ele[:])
            for i in range(first, n+1):
                ele.append(i)
                backtrack(i+1, ele)
                ele.pop()

        ans = list()
        backtrack()
        return ans



78. 子集

在这里插入图片描述
思路
栗子:
nums = [1, 2, 3]
初始化ans=[[]]
遍历nums的元素num:

  • num = 1:

    • pre=[], ans+=[pre + [num] for pre in ans] = [[]] + [[]+[1]] = [[], [1]]
  • num = 2:

    • pre=[], ans+=[pre + [num] for pre in ans] = [[], [1]] + [[]+[2]] = [[], [1], [2]]
    • pre=[1], ans+=[pre + [num] for pre in ans] = [[], [1], [2]] + [[1]+[2]] = [[], [1], [2], [1, 2]]
  • num = 3:

    • pre = [], ans+=[pre + [num] for pre in ans] = ans + [[]+[3]] = [[], [1], [2], [1, 2], [3]]
    • pre = [1], ans+=[pre + [num] for pre in ans] = ans + [[1]+[3]] = [[], [1], [2], [1, 2], [3], [1, 3]]
    • pre = [2], ans+=…= ans + [[2]+[3]] = [[], [1], [2], [1, 2], [3], [1, 3], [2, 3]]
    • pre = [1, 2], ans+=…= ans + [[1, 2]+[3]] = [[], [1], [2], [1, 2], [3], [1, 3], [2, 3], [1, 2, 3]]
class Solution(object):
    def subsets(self, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """
        ans = [[]]
        for num in nums:
            ans += [pre + [num] for pre in ans]
        return ans



79. 单词搜索

在这里插入图片描述
思路

  1. searchStart寻找board中与word第一位字符相等的位置记录在start列表中
  2. searchPath寻找word是否存在board中,从start的位置开始从direction中上下左右的4个方向找出改单词是否在board中
class Solution(object):
    def exist(self, board, word):
        """
        :type board: List[List[str]]
        :type word: str
        :rtype: bool
        """
        len_word = len(word)
        len_m = len(board)
        len_n = len(board[0])
        direction = [[-1, 0], [1, 0], [0, -1], [0, 1]]     # 方向:上下左右
        if len_word > len_m * len_n:
            return False

        def searchStart(first):
            for i in range(len_m):
                for j in range(len_n):
                    if board[i][j] == first:
                        start.append([i, j])

        start = list()
        searchStart(word[0][0])
        if not start:
            return False

        def searchPath(start_x, start_y, index_w):
            if index_w == len(word) - 1:
                return board[start_x][start_y] == word[index_w]
            if board[start_x][start_y] == word[index_w]:
                visited[start_x][start_y] = True
                for d in direction:
                    new_x = start_x+d[0]
                    new_y = start_y+d[1]
                    if new_x >= 0 and new_x < len_m and new_y >= 0 and new_y < len_n\
                    and not visited[new_x][new_y] and searchPath(new_x, new_y, index_w+1):
                        return True
                visited[start_x][start_y] = False
                    
        for i in range(len(start)):
            visited = [[False]*len_n for _ in range(len_m)]
            if searchPath(start[i][0], start[i][1], 0):
                return True
        return False



80. 删除排序数组中的重复项 II

在这里插入图片描述
思路
是26. 删除排序数组中的重复项的进阶,双指针

  1. 当nums长度n小于等于2时,直接返回n
  2. 因为nums是一个排序数组,无需排序。初始化索引i为0,count默认为已出现1次,索引j从1开始。当nums[i]等于nums[j]时,如果nums[j]出现的次数少于2次,i往右移动一步,并令nums[i] = nums[j];如果count大于2,则索引i不往右移动,count加1,索引j继续往右移动。当nums[i]不等于nums[j]时,i往右移动一步,并令nums[i] = nums[j],count设为1
class Solution(object):
    def removeDuplicates(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        n = len(nums)
        if n <= 2:
            return n
        i, count = 0, 1
        for j in range(1, n):
            if nums[i] == nums[j]:
                if count < 2:
                    i += 1
                    nums[i] = nums[j]
                count += 1
            else:
                i += 1
                count = 1
                nums[i] = nums[j]   
        return i+1

丢一只我家谢谢
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值