|
| 1 | +# 1035. Uncrossed Lines |
| 2 | +LeetCode problem: [1035. Uncrossed Lines](https://leetcode.com/problems/uncrossed-lines/) |
| 3 | + |
| 4 | +## LeetCode problem description |
| 5 | +You are given two integer arrays `nums1` and `nums2`. We write the integers of `nums1` and `nums2` (in the order they are given) on two separate horizontal lines. |
| 6 | + |
| 7 | +We may draw connecting lines: a straight line connecting two numbers `nums1[i]` and `nums2[j]` such that: |
| 8 | + |
| 9 | +* `nums1[i]` == `nums2[j]`, and |
| 10 | +* the line we draw does not intersect any other connecting (non-horizontal) line. |
| 11 | + |
| 12 | +Note that a connecting line cannot intersect even at the endpoints (i.e., each number can only belong to one connecting line). |
| 13 | + |
| 14 | +Return the maximum number of connecting lines we can draw in this way. |
| 15 | + |
| 16 | +``` |
| 17 | +------------------------------------------------------------------------------------------------------------------------------------------- |
| 18 | +[Example 1] |
| 19 | +
|
| 20 | +Input: nums1 = [1,4,2], nums2 = [1,2,4] |
| 21 | +Output: 2 |
| 22 | +Explanation: We can draw 2 uncrossed lines as in the diagram. |
| 23 | +We cannot draw 3 uncrossed lines, because the line from nums1[1] = 4 to nums2[2] = 4 will intersect the line from nums1[2]=2 to nums2[1]=2. |
| 24 | +------------------------------------------------------------------------------------------------------------------------------------------- |
| 25 | +[Example 2] |
| 26 | +
|
| 27 | +Input: nums1 = [2,5,1,2,5], nums2 = [10,5,2,1,5,2] |
| 28 | +Output: 3 |
| 29 | +------------------------------------------------------------------------------------------------------------------------------------------- |
| 30 | +[Example 3] |
| 31 | +
|
| 32 | +Input: nums1 = [1,3,7,1,7,5], nums2 = [1,9,2,5,1] |
| 33 | +Output: 2 |
| 34 | +------------------------------------------------------------------------------------------------------------------------------------------- |
| 35 | +[Constraints] |
| 36 | +
|
| 37 | +1 <= nums1.length, nums2.length <= 500 |
| 38 | +1 <= nums1[i], nums2[j] <= 2000 |
| 39 | +------------------------------------------------------------------------------------------------------------------------------------------- |
| 40 | +``` |
| 41 | + |
| 42 | +## Thoughts |
| 43 | +This problem can be solved using **Dynamic programming**. |
| 44 | + |
| 45 | +Detailed solutions will be given later, and now only the best practices in 7 languages are given. |
| 46 | + |
| 47 | +### Complexity |
| 48 | +* Time: `O(n * m)`. |
| 49 | +* Space: `O(n * m)`. |
| 50 | + |
| 51 | +## Python |
| 52 | +```python |
| 53 | +# Example of a 2D 'dp' array: |
| 54 | +# nums1 = [ 2, 5, 1, 2, 5] |
| 55 | +# nums2 = [10, 5, 2, 1, 5, 2] |
| 56 | +# 10 5 2 1 5 2 |
| 57 | +# 0 0 0 0 0 0 0 |
| 58 | +# 2 0 0 0 1 1 1 1 |
| 59 | +# 5 0 0 1 1 1 2 2 |
| 60 | +# 1 0 ... |
| 61 | +# 2 0 ... |
| 62 | +# 5 0 ... |
| 63 | +class Solution: |
| 64 | + def maxUncrossedLines(self, nums1: List[int], nums2: List[int]) -> int: |
| 65 | + dp = [[0] * (len(nums2) + 1) for _ in range(len(nums1) + 1)] |
| 66 | + |
| 67 | + for i in range(1, len(dp)): |
| 68 | + for j in range(1, len(dp[0])): |
| 69 | + if nums1[i - 1] == nums2[j - 1]: |
| 70 | + dp[i][j] = dp[i - 1][j - 1] + 1 |
| 71 | + else: |
| 72 | + dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]) |
| 73 | + |
| 74 | + return dp[-1][-1] |
| 75 | +``` |
| 76 | + |
| 77 | +## Java |
| 78 | +```java |
| 79 | +class Solution { |
| 80 | + public int maxUncrossedLines(int[] nums1, int[] nums2) { |
| 81 | + var dp = new int[nums1.length + 1][nums2.length + 1]; |
| 82 | + |
| 83 | + for (var i = 1; i < dp.length; i++) { |
| 84 | + for (var j = 1; j < dp[0].length; j++) { |
| 85 | + if (nums1[i - 1] == nums2[j - 1]) { |
| 86 | + dp[i][j] = dp[i - 1][j - 1] + 1; |
| 87 | + } else { |
| 88 | + dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]); |
| 89 | + } |
| 90 | + } |
| 91 | + } |
| 92 | + |
| 93 | + return dp[dp.length - 1][dp[0].length - 1]; |
| 94 | + } |
| 95 | +} |
| 96 | +``` |
| 97 | + |
| 98 | +## C# |
| 99 | +```c# |
| 100 | +public class Solution { |
| 101 | + public int MaxUncrossedLines(int[] nums1, int[] nums2) { |
| 102 | + var dp = new int[nums1.Length + 1, nums2.Length + 1]; |
| 103 | + |
| 104 | + for (var i = 1; i < dp.GetLength(0); i++) { |
| 105 | + for (var j = 1; j < dp.GetLength(1); j++) { |
| 106 | + if (nums1[i - 1] == nums2[j - 1]) { |
| 107 | + dp[i, j] = dp[i - 1, j - 1] + 1; |
| 108 | + } else { |
| 109 | + dp[i, j] = Math.Max(dp[i - 1, j], dp[i, j - 1]); |
| 110 | + } |
| 111 | + } |
| 112 | + } |
| 113 | + |
| 114 | + return dp[dp.GetUpperBound(0), dp.GetUpperBound(1)]; |
| 115 | + } |
| 116 | +} |
| 117 | +``` |
| 118 | + |
| 119 | +## C++ |
| 120 | +```cpp |
| 121 | +class Solution { |
| 122 | +public: |
| 123 | + int maxUncrossedLines(vector<int>& nums1, vector<int>& nums2) { |
| 124 | + vector<vector<int>> dp(nums1.size() + 1, vector<int>(nums2.size() + 1)); |
| 125 | + |
| 126 | + for (auto i = 1; i < dp.size(); i++) { |
| 127 | + for (auto j = 1; j < dp[0].size(); j++) { |
| 128 | + if (nums1[i - 1] == nums2[j - 1]) { |
| 129 | + dp[i][j] = dp[i - 1][j - 1] + 1; |
| 130 | + } else { |
| 131 | + dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]); |
| 132 | + } |
| 133 | + } |
| 134 | + } |
| 135 | + |
| 136 | + return dp[dp.size() - 1][dp[0].size() - 1]; |
| 137 | + } |
| 138 | +}; |
| 139 | +``` |
| 140 | + |
| 141 | +## JavaScript |
| 142 | +```javascript |
| 143 | +var maxUncrossedLines = function(nums1, nums2) { |
| 144 | + const dp = Array(nums1.length + 1).fill().map( |
| 145 | + () => Array(nums2.length + 1).fill(0) |
| 146 | + ) |
| 147 | + |
| 148 | + for (let i = 1; i < dp.length; i++) { |
| 149 | + for (let j = 1; j < dp[0].length; j++) { |
| 150 | + if (nums1[i - 1] === nums2[j - 1]) { |
| 151 | + dp[i][j] = dp[i - 1][j - 1] + 1 |
| 152 | + } else { |
| 153 | + dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]) |
| 154 | + } |
| 155 | + } |
| 156 | + } |
| 157 | + |
| 158 | + return dp.at(-1).at(-1) |
| 159 | +}; |
| 160 | +``` |
| 161 | + |
| 162 | +## Go |
| 163 | +```go |
| 164 | +func maxUncrossedLines(nums1 []int, nums2 []int) int { |
| 165 | + dp := make([][]int, len(nums1) + 1) |
| 166 | + for i := range dp { |
| 167 | + dp[i] = make([]int, len(nums2) + 1) |
| 168 | + } |
| 169 | + |
| 170 | + for i := 1; i < len(dp); i++ { |
| 171 | + for j := 1; j < len(dp[0]); j++ { |
| 172 | + if nums1[i - 1] == nums2[j - 1] { |
| 173 | + dp[i][j] = dp[i - 1][j - 1] + 1 |
| 174 | + } else { |
| 175 | + dp[i][j] = max(dp[i][j - 1], dp[i - 1][j]) |
| 176 | + } |
| 177 | + } |
| 178 | + } |
| 179 | + |
| 180 | + return dp[len(dp) - 1][len(dp[0]) - 1] |
| 181 | +} |
| 182 | +``` |
| 183 | + |
| 184 | +## Ruby |
| 185 | +```ruby |
| 186 | +def max_uncrossed_lines(nums1, nums2) |
| 187 | + dp = Array.new(nums1.size + 1) do |
| 188 | + Array.new(nums2.size + 1, 0) |
| 189 | + end |
| 190 | + |
| 191 | + (1...dp.size).each do |i| |
| 192 | + (1...dp[0].size).each do |j| |
| 193 | + dp[i][j] = |
| 194 | + if nums1[i - 1] == nums2[j - 1] |
| 195 | + dp[i - 1][j - 1] + 1 |
| 196 | + else |
| 197 | + [ dp[i][j - 1], dp[i - 1][j] ].max |
| 198 | + end |
| 199 | + end |
| 200 | + end |
| 201 | + |
| 202 | + dp[-1][-1] |
| 203 | +end |
| 204 | +``` |
| 205 | + |
| 206 | +## Rust |
| 207 | +```rust |
| 208 | +// Welcome to create a PR to complete the code of this language, thanks! |
| 209 | +``` |
| 210 | + |
| 211 | +## Other languages |
| 212 | +``` |
| 213 | +// Welcome to create a PR to complete the code of this language, thanks! |
| 214 | +``` |
0 commit comments