leetcode 算法题记

这篇博客记录了作者在LeetCode上遇到的算法题目,包括583. Delete Operation for Two Strings、72. Edit Distance等,通过解题过程反思自身成长,并分享解题思路和动态规划的应用。
摘要由CSDN通过智能技术生成

前言

会记录自己看过的一些leetcode小题记。希望自己能够慢慢成长起来。不再是一个小垃圾。

583. Delete Operation for Two Strings

Given two words word1 and word2, find the minimum number of steps required to make word1 and word2 the same, where in each step you can delete one character in either string.

Example 1:
Input: “sea”, “eat”
Output: 2
Explanation: You need one step to make “sea” to “ea” and another step to make “eat” to “ea”.

这道题是最近面试被问到的一个题,第一反应是编辑距离的变体,但是动态规划真的是让我头大。我一定好好加油啊!
哈哈哈
看着leetcode的解题思路整理一下。后边补上编辑距离的题。
Approch

  1. 遍历求得最长公共子序列,但是时间复杂度为 O ( 2 m a x ( m , n ) ) O(2^{max(m,n)}) O2max(m,n), 空复杂度 O ( m a x ( m , n ) ) O(max(m,n)) O(max(m,n))
#########################################################################
#  583. Delete Operation for Two Strings
#########################################################################
# solution 1: 递归求最长公共子序列


class Solution(object):
    def minDistance(self, word1, word2):
        """
        :type word1: str
        :type word2: str
        :rtype: int
        """
        len1 = len(word1)
        len2 = len(word2)
        return len1 + len2 - 2 * self.LongestCommonSubsequence(word1, word2, len1, len2)

    def LongestCommonSubsequence(self, word1, word2, len1, len2):
        if len1 == 0 or len2 == 0:
            return 0
        if word1[len1 - 1] == word2[len2 - 1]:
            return 1 + self.LongestCommonSubsequence(word1, word2, len1 - 1, len2 - 1)
        else:
            return max(self.LongestCommonSubsequence(word1, word2, len1 - 1, len2),
                       self.LongestCommonSubsequence(word1, word2, len1, len2 - 1))


# solution2:空间换时间 求得最长公共子序列. java代码可以 但是python不行

class Solution(object):
    def minDistance(self, word1, word2):
        """
        :type word1: str
        :type word2: str
        :rtype: int
        """
        len1 = len(word1)
        len2 = len(word2)
        memo = [[0] * (len1 + 1) for _ in range(len2 + 1)]
        return len1 + len2 - 2 * self.LongestCommonSubsequence(word1, word2, len1, len2, memo)

    def LongestCommonSubsequence(self, word1, word2, len1, len2, memo):
        if len1 == 0 or len2 == 0:
            return 0
        if memo[len1][len2] > 0:
            return memo[len1][len2]
        if word1[len1 - 1] == word2[len2 - 1]:
            memo[len1][len2] = 1 + self.LongestCommonSubsequence(word1, word2, len1 - 1, len2 - 1, memo)
        else:
            memo[len1][len2] = max(
                self.LongestCommonSubsequence(word1, word2, len1 - 1, len2, memo),
                self.LongestCommonSubsequence(word1, word2, len1, len2 - 1, memo))
        return memo[len1][len2]


# solution 3 : 动态规划求得最长公共子序列


class Solution(object):
    def minDistance(self, word1, word2):
        """
        :type word1: str
        :type word2: str
        :rtype: int
        """
        len1 = len(word1)
        len2 = len(word2)
        dp = [[0] * (len2 + 1) for _ in range(len1 + 1)]
        for i in range(1, len1 + 1):
            for j in range(1, len2 + 1):
                if word1[i - 1] == word2[j - 1]:
                    dp[i][j] = 1 + dp[i-1][j-1]
                else:
                    dp[i][j] = max(dp[i][j-1], dp[i-1][j])
        return len1 + len2 - 2 * dp[len1][len2]

# solution4: 动态规划,不求最长公共子序列

class Solution(object):
    def minDistance(self, word1, word2):
        """
        :type word1: str
        :type word2: str
        :rtype: int
        """
        len1 = len(word1)
        len2 = len(word2)
        dp = [[0] * (len2 + 1) for _ in range(len1 + 1)]
        for i in range(len1 + 1):
            for j in range(len2 + 1):
                if i == 0 or j == 0:
                    dp[i][j] = i+j
                elif word1[i - 1] == word2[j - 1]:
                    dp[i][j] = dp[i-1][j-1]
                else:
                    dp[i][j] = 1 + min(dp[i][j-1], dp[i-1][j])
        return dp[len1][len2]

72. Edit Distance


#########################################################################
#  72. Edit Distance
#########################################################################
# 动态规划求得编辑距离
#  if word1[i - 1] == word2[j - 1],
# then no more operation is needed and dp[i][j] = dp[i - 1][j - 1].

# If word1[i - 1] != word2[j - 1], we need to consider three cases.
# Replace word1[i - 1] by word2[j - 1] (dp[i][j] = dp[i - 1][j - 1] + 1);
# If word1[0..i - 1) =  word2[0..j) then delete word1[i - 1] (dp[i][j] = dp[i - 1][j] + 1);
# If word1[0..i) + word2[j - 1] = word2[0..j) then insert word2[j - 1] to word1[0..i) (dp[i][j] = dp[i][j - 1] + 1).

class Solution(object):
    def minDistance(self, word1, word2):
        """
        :type word1: str
        :type word2: str
        :rtype: int
        """
        len1 = len(word1)
        len2 = len(word2)
        if len1 == 0 or len2 == 0:
            return len1 + len2
        # 定义len2 * len1 的二维数组
        dp = [[0] * (len1 + 1) for _ in range(len2 + 1)]
        # 遍历每一行
        for i in range(len2 + 1):
            # 遍历每一列
            for j in range(len1 + 1):
                if i == 0 or j == 0:
                    dp[i][j] = i + j
                elif word1[i - 1] == word2[j - 1]:
                    dp[i][j] = dp[i - 1][j - 1]
                else:
                    # 用w2的当前元素替换w1的当前元素
                    replace = dp[i - 1][j - 1] + 1
                    #
                    delete = dp[i - 1][j] + 1
                    insert = dp[i][j - 1] + 1
                    dp[i][j] = min(replace, insert, delete)
        return dp[len2][len1]

10. Regular Expression Matching

class Solution:
    # s, pattern都是字符串
    def isMatch(self, s, pattern):
        # write code here
        if len(s) == 0 and len(pattern) == 0:
            return True
        if len(s) != 0 and len(pattern) == 0:
            return False

        # 第二个字符是*
        if len(pattern) > 1 and pattern[1] == '*':

            # 首字母相同或者pattern第一个为.
            if len(s) > 0 and (s[0] == pattern[0] or pattern[0] == '.'):
                return self.isMatch(s, pattern[2:]) or \
                       self.isMatch(s[1:], pattern[2:]) or \
                       self.isMatch(s[1:], pattern)
            else:
                return self.isMatch(s, pattern[2:])
        # 第二个不是*,首字母相同或者pattern[0]为 .
        if len(s) > 0 and (s[0] == pattern[0] or pattern[0] == '.'):
            return self.isMatch(s[1:], pattern[1:])
        return False


# solution2: 动态规划
# 动态匹配s[i] p[j]
class Solution:
    # s, pattern都是字符串
    def isMatch(self, s, p):
        memo = {}

        def dp(i, j):
            if (i, j) not in memo:
                if len(p) == j:
                    res = i == len(s)
                else:
                    fistmatch = len(s) > i and p[j] in {s[i], '.'}
                    if len(p) > j + 1 and p[j + 1] == '*':
                        res = dp(i, j + 2) or fistmatch and dp(i + 1, j)
                    else:
                        res = dp(i + 1, j + 1) and fistmatch
                memo[i, j] = res
            return memo[i, j]
        return dp(0, 0)

62. Unique Paths

 #########################################################################
# 62. Unique Paths
#########################################################################
# 因为机器人只能向下或者向右走,所以每一个格子dp[i][j] = dp[i-1][j] + dp[i][j-1]
class Solution(object):
    def uniquePaths(self, m, n):
        """
        :type m: int
        :type n: int
        :rtype: int
        """
        dp = [[1 for _ in range(m)] for _ in range(n)]
        for i in range(1, n):
            for j in range(1, m):
                dp[i][j] = dp[i-1][j] + dp[i][j-1]
        return dp[n-1][m-1]

63. Unique Paths II

class Solution(object):
    def uniquePathsWithObstacles(self, obstacleGrid):
        """
        :type obstacleGrid: List[List[int]]
        :rtype: int
        """
        row = len(obstacleGrid)
        col = len(obstacleGrid[0])

        if obstacleGrid[0][0] == 1:
            return 0
        obstacleGrid[0][0] = 1
        for i in range(1, row):
            obstacleGrid[i][0] = int(obstacleGrid[i][0] == 0 and obstacleGrid[i-1][0] == 1)
        for j in range(1, col):
            obstacleGrid[0][j] = int(obstacleGrid[0][j] == 0 and obstacleGrid[0][j-1] == 1)

        for i in range(1, row):
            for j in range(1, col):
                if obstacleGrid[i][j] == 0:
                    obstacleGrid[i][j] = obstacleGrid[i-1][j] + obstacleGrid[i][j-1]
                else:
                    obstacleGrid[i][j] = 0
        return obstacleGrid[row-1][col-1]

64. Minimum Path Sum

#########################################################################
# 64. Minimum Path Sum
#########################################################################
# 初始化第一行和第一列为逐元素的加和,之后的每一个格子的值为上边和左边的元素的min加上当前元素的值。
class Solution(object):
    def minPathSum(self, grid):
        """
        :type grid: List[List[int]]
        :rtype: int
        """
        row = len(grid)
        col = len(grid[0])

        for i in range(1, col):
            grid[0][i] += grid[0][i-1]
        for j in range(1, row):
            grid[j][0] += grid[j-1][0]
        for i in range(1, row):
            for j in range(1, col):
                grid[i][j] += min(grid[i-1][j], grid[i][j-1])
        return grid[row-1][col-1]

85. Maximal Rectangle

#########################################################################
# 85. Maximal Rectangle
#########################################################################
# 用三个变量分别记录长方形的长宽高。
# height[j]记录第j列 1 的个数。
# left[j]记录左边的边界。
# right[i]记录右边的边界。

class Solution(object):
    def maximalRectangle(self, matrix):
        """
        :type matrix: List[List[str]]
        :rtype: int
        """
        if matrix == []:
            return 0
        row = len(matrix)
        col = len(matrix[0])

        height = [0] * col
        left = [0] * col
        right = [col - 1] * col
        maxA = 0
        for i in range(row):
            cur_left = 0
            cur_right = row - 1

            # 更新height
            for j in range(col):
                if matrix[i][j] == '1':
                    height[j] += 1
                else:
                    height[j] = 0

            # 更新left
            for j in range(col):
                if matrix[i][j] == '1':
                    left[j] = max(left[j], cur_left)
                else:
                    left[j] = 0
                    cur_left = j + 1

            for j in range(col-1, -1, -1):
                if matrix[i][j] == '1':
                    right[j] = min(right[j], cur_right)
                else:
                    right[j] = col - 1
                    cur_right = j - 1

            for j in range(col):
                maxA = max(maxA, (right[j] - left[j] + 1) * height[j])

        return maxA

87. Scramble String

#########################################################################
# 87. Scramble String
#########################################################################
# 跟二叉树的镜像有点相似。这道题主要是将两个字符串分为两部分,然后分为两种情况进行比较,
# 情况1:s1的右边跟s2的右边符合isScramble 且同时 s1的左边跟s2的左边符合isScramble
# 情况2:s1的右边i个字符跟s2的左边i个符合isScramble 且同时 s1的左边跟s2的右边符合isScramble
class Solution(object):
    def isScramble(self, s1, s2):
        """
        :type s1: str
        :type s2: str
        :rtype: bool
        """
        len1 = len(s1)
        len2 = len(s2)
        if (len1 != len2 ) or (sorted(s1) != sorted(s2)):
            return False
        if s1 == s2 or len1 < 3:
            return True

        for i in range(1, len1):
            if self.isScramble(s1[0:i], s2[0:i]) and self.isScramble(s1[i:], s2[i:]) \
                    or self.isScramble(s1[0:i], s2[len2-i:]) and self.isScramble(s1[i:], s2[:len2-i]):
                return True
        return False

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值