当前位置:实例文章 » 其他实例» [文章]day53 | 1143.最长公共子序列、1035.不相交的线、53. 最大子序和

day53 | 1143.最长公共子序列、1035.不相交的线、53. 最大子序和

发布人:shili8 发布时间:2024-12-28 02:05 阅读次数:0

**Day53**

### **1143. 最长公共子序列**

#### **问题描述**

给定两个字符串 `s1` 和 `s2`,找到它们的最长公共子序列(LCS)。如果有多个长度相同的 LCS,则返回其中一个。

#### **示例**

* 输入:`s1 = "AGGTAB"、` `s2 = "GXTXAYB"`
输出: `"GTAB"`

#### **解决方案**

我们可以使用动态规划来解决这个问题。首先,我们需要定义一个2D 数组 `dp`,其中 `dp[i][j]` 表示 `s1[0..i-1]` 和 `s2[0..j-1]` 的 LCS 的长度。

def longestCommonSubsequence(s1, s2):
 m, n = len(s1), len(s2)
 # Initialize dp array with zeros dp = [[0] * (n +1) for _ in range(m +1)]
 # Fill up the first row and column of dp array for i in range(1, m +1):
 dp[i][0] =0 for j in range(1, n +1):
 dp[0][j] =0 # Fill up the rest of the dp array for i in range(1, m +1):
 for j in range(1, n +1):
 if s1[i -1] == s2[j -1]:
 dp[i][j] = dp[i -1][j -1] +1 else:
 dp[i][j] = max(dp[i -1][j], dp[i][j -1])
 # Reconstruct the LCS from the dp array lcs = []
 i, j = m, n while i >0 and j >0:
 if s1[i -1] == s2[j -1]:
 lcs.append(s1[i -1])
 i -=1 j -=1 elif dp[i -1][j] > dp[i][j -1]:
 i -=1 else:
 j -=1 return "".join(reversed(lcs))


#### **注释**

* 我们首先初始化一个 `dp` 数组,大小为 `(m +1) x (n +1)`,其中 `m` 和 `n` 是 `s1` 和 `s2` 的长度。
* 然后,我们填充了 `dp` 数组的第一行和第一列。这些值都是零,因为当一个字符串为空时,它与另一个字符串的 LCS 长度也是零。
* 接下来,我们填充了 `dp` 数组的剩余部分。对于每个位置 `(i, j)`,我们检查 `s1[i -1]` 和 `s2[j -1]` 是否相等。如果它们相等,则 `dp[i][j]` 的值是 `dp[i -1][j -1]` 的值加一。否则,我们取 `dp[i -1][j]` 和 `dp[i][j -1]` 中较大的值。
* 最后,我们从 `dp` 数组中重构了 LCS。我们从 `(m, n)` 开始,检查当前位置的值。如果它等于前一个位置的值加一,则将该值添加到 LCS 中,并移动到上一个位置。否则,我们移动到下一个位置。

### **1035. 不相交的线**

#### **问题描述**

给定 `n` 个不相交的线段,每个线段由两个坐标 `(x1, y1)` 和 `(x2, y2)` 定义。请找出这些线段中最多有多少条可以同时画在同一张纸上。

#### **示例**

* 输入:`n =4`
输出: `4`

#### **解决方案**

我们可以使用贪婪算法来解决这个问题。首先,我们需要定义一个函数 `getMaxVal`,该函数返回给定线段的最大值和最小值。

def getMaxVal(x1, y1, x2, y2):
 return max(x1, x2), min(y1, y2)


然后,我们可以使用贪婪算法来找到不相交的线段的数量。我们首先将所有线段的最大值和最小值存储在一个列表中。

def getLines(n):
 lines = []
 for i in range(1, n +1):
 x1, y1 =2 * i -3,0 x2, y2 =2 * i -1,4 maxVal, minVal = getMaxVal(x1, y1, x2, y2)
 lines.append((maxVal, minVal))
 return lines


接下来,我们可以使用贪婺算法来找到不相交的线段的数量。我们首先将所有线段的最大值和最小值存储在一个列表中。

def getNonIntersectingLines(lines):
 nonIntersectingLines = []
 for i in range(len(lines)):
 count =1 for j in range(i +1, len(lines)):
 if lines[i][0] > lines[j][1]:
 count +=1 nonIntersectingLines.append(count)
 return max(nonIntersectingLines)


最后,我们可以使用上述函数来找到不相交的线段的数量。

def findNonIntersectingLines(n):
 lines = getLines(n)
 return getNonIntersectingLines(lines)


#### **注释**

* 我们首先定义了一个函数 `getMaxVal`,该函数返回给定线段的最大值和最小值。
* 然后,我们使用贪婺算法来找到不相交的线段的数量。我们首先将所有线段的最大值和最小值存储在一个列表中。
* 接下来,我们使用贪婺算法来找到不相交的线段的数量。我们首先将所有线段的最大值和最小值存储在一个列表中。
* 最后,我们使用上述函数来找到不相交的线段的数量。

### **53. 最大子序和**

#### **问题描述**

给定一个整数数组 `nums`,请找出该数组中最大子序列和。

#### **示例**

* 输入:`[-2,1,-3,4,-1,2,1,-5,4]`
输出: `6`

#### **解决方案**

我们可以使用动态规划来解决这个问题。首先,我们需要定义一个数组 `dp`,其中 `dp[i]` 表示 `nums[0..i-1]` 的最大子序列和。

def maxSubarraySum(nums):
 dp = [0] * len(nums)
 dp[0] = nums[0]
 for i in range(1, len(nums)):
 if nums[i] >0:
 dp[i] = max(dp[i -1], nums[i])
 else:
 dp[i] = dp[i -1]
 return max(dp)


#### **注释**

* 我们首先定义了一个数组 `dp`,其中 `dp[i]` 表示 `nums[0..i-1]` 的最大子序列和。
* 然后,我们将 `dp[0]` 初始化为 `nums[0]`。
* 接下来,我们遍历 `nums`,对于每个位置 `i`,我们检查 `nums[i]` 是否大于零。如果它是,则 `dp[i]` 的值是 `max(dp[i -1], nums[i])`。否则,`dp[i]` 的值保持不变。
* 最后,我们返回 `dp` 中的最大值。

#### **时间复杂度**

* 时间复杂度为 O(n),其中 n 是数组长度。

#### **空间复杂度**

* 空间复杂度为 O(n),其中 n 是数组长度。

相关标签:
其他信息

其他资源

Top