给你一个由 n 个数对组成的数对数组 pairs ,其中 p a i r s [ i ] = [ l e f t i , r i g h t i ] pairs[i] = [left_i, right_i] pairs[i]=[lefti,righti] 且 l e f t i < r i g h t i left_i < right_i lefti<righti。
现在,我们定义一种 跟随 关系,当且仅当 b < c 时,数对 p2 = [c, d] 才可以跟在 p1 = [a, b] 后面。我们用这种形式来构造 数对链 。
找出并返回能够形成的 最长数对链的长度 。
你不需要用到所有的数对,你可以以任何顺序选择其中的一些数对来构造。
输入:pairs = [[1,2], [2,3], [3,4]]
输出:2
解释:最长的数对链是 [1,2] -> [3,4] 。
输入:pairs = [[1,2],[7,8],[4,5]]
输出:3
解释:最长的数对链是 [1,2] -> [4,5] -> [7,8] 。
首先对二维数组进行排序:
(a, b) -> a - b 相当于
function(a,b){
return a-b;
}
Arrays.sort(arr, (a, b) -> a - b) 是对数组进行冒泡排序
如果 a - b>0 则b 在前 a 在后、直到有序
二维数组
Arrays.sort(arr, (a, b) ->(a[clomun]- b[clomun]))
以行为整体 按指定列比较
法一:动态规划
法二:贪心
使用贪心思想扩展数对链,在所有可作为下一个数对的集合中选择第二个数最小的数对添加到数对链。
要挑选最长数对链的第一个数对时,最优的选择是挑选第二个数字最小的,这样能给挑选后续的数对留下更多的空间。挑完第一个数对后,要挑第二个数对时,也是按照相同的思路,是在剩下的数对中,第一个数字满足题意的条件下,挑选第二个数字最小的。按照这样的思路,可以先将输入按照第二个数字排序,然后不停地判断第一个数字是否能满足大于前一个数对的第二个数字即可。
快排函数:
private static void quicksort(int[][] pairs, int left, int right) {//快排
// TODO Auto-generated method stub
int i = left, j = right;
if(i >= j)
return;
int temp1 = pairs[i][0], temp2 = pairs[i][1];
int a, b;
while(i != j) {
while(pairs[j][0] >= temp1 && i < j) {
j--;
}
while(pairs[i][0] <= temp1 && i < j) {
i++;
}
if(i < j) {
a = pairs[i][0];
b = pairs[i][1];
pairs[i][0] = pairs[j][0];
pairs[i][1] = pairs[j][1];
pairs[j][0] = a;
pairs[j][1] = b;
}
}
pairs[left][0] = pairs[i][0];
pairs[left][1] = pairs[i][1];
pairs[i][0] = temp1;
pairs[i][1] = temp2;
quicksort(pairs, left, i-1);
quicksort(pairs, i+1, right);
return;
}
}
法一:动态规划
import java.util.Arrays;
public class FindLongestChain {
public static void main(String[] args) {
// TODO Auto-generated method stub
int[][] pairs = {{1,2}, {7,8}, {4,5}};
System.out.println(findLongestChain(pairs));
}
public static int findLongestChain(int[][] pairs) {
int n = pairs.length;
//Arrays.sort(pairs, (a,b)->(a[0] - b[0]));//冒泡排序
quicksort(pairs, 0, n-1);
int[] dp = new int[n];
Arrays.fill(dp, 1);
for(int i = 0; i < n; i++) {
for(int j = 0; j < i; j++) {
if(pairs[i][0] > pairs[j][1]) {
dp[i] = Math.max(dp[i], dp[j] + 1);
}
}
}
return dp[n - 1];
}
法二:贪心
import java.util.Arrays;
public class FindLongestChain {
public static void main(String[] args) {
// TODO Auto-generated method stub
int[][] pairs = {{1,2}, {7,8}, {4,5}};
System.out.println(findLongestChain(pairs));
}
public static int findLongestChain(int[][] pairs) {
int n = pairs.length;
//Arrays.sort(pairs, (a,b)->(a[0] - b[0]));//冒泡排序
quicksort(pairs, 0, n-1);
int len = 1;
int temp0 = pairs[0][0], temp1 = pairs[0][1];
for(int i = 1; i < n; i++) {
if(pairs[i][0] > temp1) {
len ++;
temp0 = pairs[i][0];
temp1 = pairs[i][1];
}else if(pairs[i][1] < temp1 ) {
temp0 = pairs[i][0];
temp1 = pairs[i][1];
}else {
continue;
}
}
return len;
}
法一:动态规划
时间复杂度: O ( n 2 ) O(n^2) O(n2),其中 n 为 pairs 的长度。排序的时间复杂度为 O(nlogn),两层 for 循环的时间复杂度为 O ( n 2 ) O(n^2) O(n2)。
空间复杂度:O(n),数组 dp的空间复杂度为 O(n)。
法二:贪心
时间复杂度: O ( n l o g n ) O(nlogn) O(nlogn),其中 n 为 pairs 的长度。排序的时间复杂度为 O(nlogn)。
空间复杂度:O(1)。
题目来源:力扣。