diff --git a/solution/1000-1099/1035.Uncrossed Lines/README.md b/solution/1000-1099/1035.Uncrossed Lines/README.md index 64fcc5e4d6581..a5b523e771cd3 100644 --- a/solution/1000-1099/1035.Uncrossed Lines/README.md +++ b/solution/1000-1099/1035.Uncrossed Lines/README.md @@ -39,7 +39,7 @@ tags:
 输入:nums1 = [1,4,2], nums2 = [1,2,4]
 输出:2
-解释:可以画出两条不交叉的线,如上图所示。 
+解释:可以画出两条不交叉的线,如上图所示。
 但无法画出第三条不相交的直线,因为从 nums1[1]=4 到 nums2[2]=4 的直线将与从 nums1[2]=2 到 nums2[1]=2 的直线相交。
 
@@ -79,19 +79,15 @@ tags: ### 方法一:动态规划 -最长公共子序列问题。 +我们定义 $f[i][j]$ 表示 $\textit{nums1}$ 前 $i$ 个数和 $\textit{nums2}$ 前 $j$ 个数的最大连线数。初始时 $f[i][j] = 0$,答案即为 $f[m][n]$。 -定义 $dp[i][j]$ 表示数组 `nums1` 的前 $i$ 个元素和数组 `nums2` 的前 $j$ 个元素的最长公共子序列的长度。则有: +当 $\textit{nums1}[i-1] = \textit{nums2}[j-1]$ 时,我们可以在 $\textit{nums1}$ 的前 $i-1$ 个数和 $\textit{nums2}$ 的前 $j-1$ 个数的基础上增加一条连线,此时 $f[i][j] = f[i-1][j-1] + 1$。 -$$ -dp[i][j]= -\begin{cases} -dp[i-1][j-1]+1, & nums1[i-1]=nums2[j-1] \\ -\max(dp[i-1][j], dp[i][j-1]), & nums1[i-1]\neq nums2[j-1] -\end{cases} -$$ +当 $\textit{nums1}[i-1] \neq \textit{nums2}[j-1]$ 时,我们要么在 $\textit{nums1}$ 的前 $i-1$ 个数和 $\textit{nums2}$ 的前 $j$ 个数的基础上求解,要么在 $\textit{nums1}$ 的前 $i$ 个数和 $\textit{nums2}$ 的前 $j-1$ 个数的基础上求解,取两者的最大值,即 $f[i][j] = \max(f[i-1][j], f[i][j-1])$。 -时间复杂度 $O(m\times n)$,空间复杂度 $O(m\times n)$。其中 $m$, $n$ 分别为数组 `nums1` 和 `nums2` 的长度。 +最后返回 $f[m][n]$ 即可。 + +时间复杂度 $O(m \times n)$,空间复杂度 $O(m \times n)$。其中 $m$ 和 $n$ 分别是 $\textit{nums1}$ 和 $\textit{nums2}$ 的长度。 @@ -101,14 +97,14 @@ $$ class Solution: def maxUncrossedLines(self, nums1: List[int], nums2: List[int]) -> int: m, n = len(nums1), len(nums2) - dp = [[0] * (n + 1) for i in range(m + 1)] - for i in range(1, m + 1): - for j in range(1, n + 1): - if nums1[i - 1] == nums2[j - 1]: - dp[i][j] = dp[i - 1][j - 1] + 1 + f = [[0] * (n + 1) for _ in range(m + 1)] + for i, x in enumerate(nums1, 1): + for j, y in enumerate(nums2, 1): + if x == y: + f[i][j] = f[i - 1][j - 1] + 1 else: - dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]) - return dp[m][n] + f[i][j] = max(f[i - 1][j], f[i][j - 1]) + return f[m][n] ``` #### Java @@ -116,19 +112,18 @@ class Solution: ```java class Solution { public int maxUncrossedLines(int[] nums1, int[] nums2) { - int m = nums1.length; - int n = nums2.length; - int[][] dp = new int[m + 1][n + 1]; - for (int i = 1; i <= m; i++) { - for (int j = 1; j <= n; j++) { + int m = nums1.length, n = nums2.length; + int[][] f = new int[m + 1][n + 1]; + for (int i = 1; i <= m; ++i) { + for (int j = 1; j <= n; ++j) { if (nums1[i - 1] == nums2[j - 1]) { - dp[i][j] = dp[i - 1][j - 1] + 1; + f[i][j] = f[i - 1][j - 1] + 1; } else { - dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]); + f[i][j] = Math.max(f[i - 1][j], f[i][j - 1]); } } } - return dp[m][n]; + return f[m][n]; } } ``` @@ -140,17 +135,18 @@ class Solution { public: int maxUncrossedLines(vector& nums1, vector& nums2) { int m = nums1.size(), n = nums2.size(); - vector> dp(m + 1, vector(n + 1)); + int f[m + 1][n + 1]; + memset(f, 0, sizeof(f)); for (int i = 1; i <= m; ++i) { for (int j = 1; j <= n; ++j) { if (nums1[i - 1] == nums2[j - 1]) { - dp[i][j] = dp[i - 1][j - 1] + 1; + f[i][j] = f[i - 1][j - 1] + 1; } else { - dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]); + f[i][j] = max(f[i - 1][j], f[i][j - 1]); } } } - return dp[m][n]; + return f[m][n]; } }; ``` @@ -160,20 +156,20 @@ public: ```go func maxUncrossedLines(nums1 []int, nums2 []int) int { m, n := len(nums1), len(nums2) - dp := make([][]int, m+1) - for i := range dp { - dp[i] = make([]int, n+1) + f := make([][]int, m+1) + for i := range f { + f[i] = make([]int, n+1) } for i := 1; i <= m; i++ { for j := 1; j <= n; j++ { if nums1[i-1] == nums2[j-1] { - dp[i][j] = dp[i-1][j-1] + 1 + f[i][j] = f[i-1][j-1] + 1 } else { - dp[i][j] = max(dp[i-1][j], dp[i][j-1]) + f[i][j] = max(f[i-1][j], f[i][j-1]) } } } - return dp[m][n] + return f[m][n] } ``` @@ -183,19 +179,45 @@ func maxUncrossedLines(nums1 []int, nums2 []int) int { function maxUncrossedLines(nums1: number[], nums2: number[]): number { const m = nums1.length; const n = nums2.length; - const dp = Array.from({ length: m + 1 }, () => new Array(n + 1).fill(0)); + const f: number[][] = Array.from({ length: m + 1 }, () => Array(n + 1).fill(0)); for (let i = 1; i <= m; ++i) { for (let j = 1; j <= n; ++j) { - dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]); - if (nums1[i - 1] == nums2[j - 1]) { - dp[i][j] = dp[i - 1][j - 1] + 1; + if (nums1[i - 1] === nums2[j - 1]) { + f[i][j] = f[i - 1][j - 1] + 1; + } else { + f[i][j] = Math.max(f[i - 1][j], f[i][j - 1]); } } } - return dp[m][n]; + return f[m][n]; } ``` +#### JavaScript + +```js +/** + * @param {number[]} nums1 + * @param {number[]} nums2 + * @return {number} + */ +var maxUncrossedLines = function (nums1, nums2) { + const m = nums1.length; + const n = nums2.length; + const f = Array.from({ length: m + 1 }, () => Array(n + 1).fill(0)); + for (let i = 1; i <= m; ++i) { + for (let j = 1; j <= n; ++j) { + if (nums1[i - 1] === nums2[j - 1]) { + f[i][j] = f[i - 1][j - 1] + 1; + } else { + f[i][j] = Math.max(f[i - 1][j], f[i][j - 1]); + } + } + } + return f[m][n]; +}; +``` + diff --git a/solution/1000-1099/1035.Uncrossed Lines/README_EN.md b/solution/1000-1099/1035.Uncrossed Lines/README_EN.md index 58d5c1873e5cf..e2b5065a2b399 100644 --- a/solution/1000-1099/1035.Uncrossed Lines/README_EN.md +++ b/solution/1000-1099/1035.Uncrossed Lines/README_EN.md @@ -70,7 +70,17 @@ We cannot draw 3 uncrossed lines, because the line from nums1[1] = 4 to nums2[2] -### Solution 1 +### Solution 1: Dynamic Programming + +We define $f[i][j]$ to represent the maximum number of connections between the first $i$ numbers of $\textit{nums1}$ and the first $j$ numbers of $\textit{nums2}$. Initially, $f[i][j] = 0$, and the answer is $f[m][n]$. + +When $\textit{nums1}[i-1] = \textit{nums2}[j-1]$, we can add a connection based on the first $i-1$ numbers of $\textit{nums1}$ and the first $j-1$ numbers of $\textit{nums2}$. In this case, $f[i][j] = f[i-1][j-1] + 1$. + +When $\textit{nums1}[i-1] \neq \textit{nums2}[j-1]$, we either solve based on the first $i-1$ numbers of $\textit{nums1}$ and the first $j$ numbers of $\textit{nums2}$, or solve based on the first $i$ numbers of $\textit{nums1}$ and the first $j-1$ numbers of $\textit{nums2}$, taking the maximum of the two. That is, $f[i][j] = \max(f[i-1][j], f[i][j-1])$. + +Finally, return $f[m][n]$. + +The time complexity is $O(m \times n)$, and the space complexity is $O(m \times n)$. Here, $m$ and $n$ are the lengths of $\textit{nums1}$ and $\textit{nums2}$, respectively. @@ -80,14 +90,14 @@ We cannot draw 3 uncrossed lines, because the line from nums1[1] = 4 to nums2[2] class Solution: def maxUncrossedLines(self, nums1: List[int], nums2: List[int]) -> int: m, n = len(nums1), len(nums2) - dp = [[0] * (n + 1) for i in range(m + 1)] - for i in range(1, m + 1): - for j in range(1, n + 1): - if nums1[i - 1] == nums2[j - 1]: - dp[i][j] = dp[i - 1][j - 1] + 1 + f = [[0] * (n + 1) for _ in range(m + 1)] + for i, x in enumerate(nums1, 1): + for j, y in enumerate(nums2, 1): + if x == y: + f[i][j] = f[i - 1][j - 1] + 1 else: - dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]) - return dp[m][n] + f[i][j] = max(f[i - 1][j], f[i][j - 1]) + return f[m][n] ``` #### Java @@ -95,19 +105,18 @@ class Solution: ```java class Solution { public int maxUncrossedLines(int[] nums1, int[] nums2) { - int m = nums1.length; - int n = nums2.length; - int[][] dp = new int[m + 1][n + 1]; - for (int i = 1; i <= m; i++) { - for (int j = 1; j <= n; j++) { + int m = nums1.length, n = nums2.length; + int[][] f = new int[m + 1][n + 1]; + for (int i = 1; i <= m; ++i) { + for (int j = 1; j <= n; ++j) { if (nums1[i - 1] == nums2[j - 1]) { - dp[i][j] = dp[i - 1][j - 1] + 1; + f[i][j] = f[i - 1][j - 1] + 1; } else { - dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]); + f[i][j] = Math.max(f[i - 1][j], f[i][j - 1]); } } } - return dp[m][n]; + return f[m][n]; } } ``` @@ -119,17 +128,18 @@ class Solution { public: int maxUncrossedLines(vector& nums1, vector& nums2) { int m = nums1.size(), n = nums2.size(); - vector> dp(m + 1, vector(n + 1)); + int f[m + 1][n + 1]; + memset(f, 0, sizeof(f)); for (int i = 1; i <= m; ++i) { for (int j = 1; j <= n; ++j) { if (nums1[i - 1] == nums2[j - 1]) { - dp[i][j] = dp[i - 1][j - 1] + 1; + f[i][j] = f[i - 1][j - 1] + 1; } else { - dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]); + f[i][j] = max(f[i - 1][j], f[i][j - 1]); } } } - return dp[m][n]; + return f[m][n]; } }; ``` @@ -139,20 +149,20 @@ public: ```go func maxUncrossedLines(nums1 []int, nums2 []int) int { m, n := len(nums1), len(nums2) - dp := make([][]int, m+1) - for i := range dp { - dp[i] = make([]int, n+1) + f := make([][]int, m+1) + for i := range f { + f[i] = make([]int, n+1) } for i := 1; i <= m; i++ { for j := 1; j <= n; j++ { if nums1[i-1] == nums2[j-1] { - dp[i][j] = dp[i-1][j-1] + 1 + f[i][j] = f[i-1][j-1] + 1 } else { - dp[i][j] = max(dp[i-1][j], dp[i][j-1]) + f[i][j] = max(f[i-1][j], f[i][j-1]) } } } - return dp[m][n] + return f[m][n] } ``` @@ -162,19 +172,45 @@ func maxUncrossedLines(nums1 []int, nums2 []int) int { function maxUncrossedLines(nums1: number[], nums2: number[]): number { const m = nums1.length; const n = nums2.length; - const dp = Array.from({ length: m + 1 }, () => new Array(n + 1).fill(0)); + const f: number[][] = Array.from({ length: m + 1 }, () => Array(n + 1).fill(0)); for (let i = 1; i <= m; ++i) { for (let j = 1; j <= n; ++j) { - dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]); - if (nums1[i - 1] == nums2[j - 1]) { - dp[i][j] = dp[i - 1][j - 1] + 1; + if (nums1[i - 1] === nums2[j - 1]) { + f[i][j] = f[i - 1][j - 1] + 1; + } else { + f[i][j] = Math.max(f[i - 1][j], f[i][j - 1]); } } } - return dp[m][n]; + return f[m][n]; } ``` +#### JavaScript + +```js +/** + * @param {number[]} nums1 + * @param {number[]} nums2 + * @return {number} + */ +var maxUncrossedLines = function (nums1, nums2) { + const m = nums1.length; + const n = nums2.length; + const f = Array.from({ length: m + 1 }, () => Array(n + 1).fill(0)); + for (let i = 1; i <= m; ++i) { + for (let j = 1; j <= n; ++j) { + if (nums1[i - 1] === nums2[j - 1]) { + f[i][j] = f[i - 1][j - 1] + 1; + } else { + f[i][j] = Math.max(f[i - 1][j], f[i][j - 1]); + } + } + } + return f[m][n]; +}; +``` + diff --git a/solution/1000-1099/1035.Uncrossed Lines/Solution.cpp b/solution/1000-1099/1035.Uncrossed Lines/Solution.cpp index 9d5e571698609..78f903049ccab 100644 --- a/solution/1000-1099/1035.Uncrossed Lines/Solution.cpp +++ b/solution/1000-1099/1035.Uncrossed Lines/Solution.cpp @@ -2,16 +2,17 @@ class Solution { public: int maxUncrossedLines(vector& nums1, vector& nums2) { int m = nums1.size(), n = nums2.size(); - vector> dp(m + 1, vector(n + 1)); + int f[m + 1][n + 1]; + memset(f, 0, sizeof(f)); for (int i = 1; i <= m; ++i) { for (int j = 1; j <= n; ++j) { if (nums1[i - 1] == nums2[j - 1]) { - dp[i][j] = dp[i - 1][j - 1] + 1; + f[i][j] = f[i - 1][j - 1] + 1; } else { - dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]); + f[i][j] = max(f[i - 1][j], f[i][j - 1]); } } } - return dp[m][n]; + return f[m][n]; } -}; \ No newline at end of file +}; diff --git a/solution/1000-1099/1035.Uncrossed Lines/Solution.go b/solution/1000-1099/1035.Uncrossed Lines/Solution.go index c176c14388dcf..3a25cfee7b9aa 100644 --- a/solution/1000-1099/1035.Uncrossed Lines/Solution.go +++ b/solution/1000-1099/1035.Uncrossed Lines/Solution.go @@ -1,17 +1,17 @@ func maxUncrossedLines(nums1 []int, nums2 []int) int { m, n := len(nums1), len(nums2) - dp := make([][]int, m+1) - for i := range dp { - dp[i] = make([]int, n+1) + f := make([][]int, m+1) + for i := range f { + f[i] = make([]int, n+1) } for i := 1; i <= m; i++ { for j := 1; j <= n; j++ { if nums1[i-1] == nums2[j-1] { - dp[i][j] = dp[i-1][j-1] + 1 + f[i][j] = f[i-1][j-1] + 1 } else { - dp[i][j] = max(dp[i-1][j], dp[i][j-1]) + f[i][j] = max(f[i-1][j], f[i][j-1]) } } } - return dp[m][n] -} \ No newline at end of file + return f[m][n] +} diff --git a/solution/1000-1099/1035.Uncrossed Lines/Solution.java b/solution/1000-1099/1035.Uncrossed Lines/Solution.java index 292f14a655f96..00bb0ed57dfc8 100644 --- a/solution/1000-1099/1035.Uncrossed Lines/Solution.java +++ b/solution/1000-1099/1035.Uncrossed Lines/Solution.java @@ -1,17 +1,16 @@ class Solution { public int maxUncrossedLines(int[] nums1, int[] nums2) { - int m = nums1.length; - int n = nums2.length; - int[][] dp = new int[m + 1][n + 1]; - for (int i = 1; i <= m; i++) { - for (int j = 1; j <= n; j++) { + int m = nums1.length, n = nums2.length; + int[][] f = new int[m + 1][n + 1]; + for (int i = 1; i <= m; ++i) { + for (int j = 1; j <= n; ++j) { if (nums1[i - 1] == nums2[j - 1]) { - dp[i][j] = dp[i - 1][j - 1] + 1; + f[i][j] = f[i - 1][j - 1] + 1; } else { - dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]); + f[i][j] = Math.max(f[i - 1][j], f[i][j - 1]); } } } - return dp[m][n]; + return f[m][n]; } -} \ No newline at end of file +} diff --git a/solution/1000-1099/1035.Uncrossed Lines/Solution.js b/solution/1000-1099/1035.Uncrossed Lines/Solution.js new file mode 100644 index 0000000000000..13abac72f5ba8 --- /dev/null +++ b/solution/1000-1099/1035.Uncrossed Lines/Solution.js @@ -0,0 +1,20 @@ +/** + * @param {number[]} nums1 + * @param {number[]} nums2 + * @return {number} + */ +var maxUncrossedLines = function (nums1, nums2) { + const m = nums1.length; + const n = nums2.length; + const f = Array.from({ length: m + 1 }, () => Array(n + 1).fill(0)); + for (let i = 1; i <= m; ++i) { + for (let j = 1; j <= n; ++j) { + if (nums1[i - 1] === nums2[j - 1]) { + f[i][j] = f[i - 1][j - 1] + 1; + } else { + f[i][j] = Math.max(f[i - 1][j], f[i][j - 1]); + } + } + } + return f[m][n]; +}; diff --git a/solution/1000-1099/1035.Uncrossed Lines/Solution.py b/solution/1000-1099/1035.Uncrossed Lines/Solution.py index 524bbe665f054..3f8d2f713c5d6 100644 --- a/solution/1000-1099/1035.Uncrossed Lines/Solution.py +++ b/solution/1000-1099/1035.Uncrossed Lines/Solution.py @@ -1,11 +1,11 @@ class Solution: def maxUncrossedLines(self, nums1: List[int], nums2: List[int]) -> int: m, n = len(nums1), len(nums2) - dp = [[0] * (n + 1) for i in range(m + 1)] - for i in range(1, m + 1): - for j in range(1, n + 1): - if nums1[i - 1] == nums2[j - 1]: - dp[i][j] = dp[i - 1][j - 1] + 1 + f = [[0] * (n + 1) for _ in range(m + 1)] + for i, x in enumerate(nums1, 1): + for j, y in enumerate(nums2, 1): + if x == y: + f[i][j] = f[i - 1][j - 1] + 1 else: - dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]) - return dp[m][n] + f[i][j] = max(f[i - 1][j], f[i][j - 1]) + return f[m][n] diff --git a/solution/1000-1099/1035.Uncrossed Lines/Solution.ts b/solution/1000-1099/1035.Uncrossed Lines/Solution.ts index aa7ec45c257a4..5f0bee4e7f5a2 100644 --- a/solution/1000-1099/1035.Uncrossed Lines/Solution.ts +++ b/solution/1000-1099/1035.Uncrossed Lines/Solution.ts @@ -1,14 +1,15 @@ function maxUncrossedLines(nums1: number[], nums2: number[]): number { const m = nums1.length; const n = nums2.length; - const dp = Array.from({ length: m + 1 }, () => new Array(n + 1).fill(0)); + const f: number[][] = Array.from({ length: m + 1 }, () => Array(n + 1).fill(0)); for (let i = 1; i <= m; ++i) { for (let j = 1; j <= n; ++j) { - dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]); - if (nums1[i - 1] == nums2[j - 1]) { - dp[i][j] = dp[i - 1][j - 1] + 1; + if (nums1[i - 1] === nums2[j - 1]) { + f[i][j] = f[i - 1][j - 1] + 1; + } else { + f[i][j] = Math.max(f[i - 1][j], f[i][j - 1]); } } } - return dp[m][n]; + return f[m][n]; }