646. 最长数对链——【Leetcode每日刷题】

646. 最长数对链

给你一个由 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] 后面。我们用这种形式来构造 数对链

找出并返回能够形成的 最长数对链的长度

你不需要用到所有的数对,你可以以任何顺序选择其中的一些数对来构造。

示例 1:

输入:pairs = [[1,2], [2,3], [3,4]]
输出:2
解释:最长的数对链是 [1,2] -> [3,4] 。

示例 2:

输入:pairs = [[1,2],[7,8],[4,5]]
输出:3
解释:最长的数对链是 [1,2] -> [4,5] -> [7,8] 。

提示:
  • n = = p a i r s . l e n g t h n == pairs.length n==pairs.length
  • 1 < = n < = 1000 1 <= n <= 1000 1<=n<=1000
  • − 1000 < = l e f t i < r i g h t i < = 1000 -1000 <= left_i < right_i <= 1000 1000<=lefti<righti<=1000

思路:

首先对二维数组进行排序:

  • 使用Arrays.sort(arr,Comparator<>)
    对数组中相邻的两个数进行比较, 一轮完了接着二轮 是一个冒泡排序,时间复杂度为: O ( n 2 ) O(n^2) O(n2)

(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]))
以行为整体 按指定列比较

  • 使用快排,时间复杂度为:O(nlogn)

法一:动态规划

  1. 排序(按上述两种方法)
  2. 定义 dp[i] 为以 pairs[i] 为结尾的最长数对链的长度。
  3. 计算 dp[i] 时,可以先找出所有的满足 pairs[i][0] > pairs[j][1] 的 j,并求出最大的
    dp[j],dp[i]的值即可赋为这个最大值再加一。

法二:贪心

使用贪心思想扩展数对链,在所有可作为下一个数对的集合中选择第二个数最小的数对添加到数对链。

要挑选最长数对链的第一个数对时,最优的选择是挑选第二个数字最小的,这样能给挑选后续的数对留下更多的空间。挑完第一个数对后,要挑第二个数对时,也是按照相同的思路,是在剩下的数对中,第一个数字满足题意的条件下,挑选第二个数字最小的。按照这样的思路,可以先将输入按照第二个数字排序,然后不停地判断第一个数字是否能满足大于前一个数对的第二个数字即可。

  1. 排序(按上述两种方法)
  2. 由于所有的数对都已按照第一个升序排序,所以在构造数对链过程中,只需挑选数对第二数尽量小的数。使用temp0,temp1 记录数对链的最后一组数据。
  3. 对任意pairs[i - 1][0] <= pairs[i][0],所以 temp0 <= pairs[i][0]
    • 如果 pairs[i][0] > temp1 ,添加到数对链中,长度加1
    • 如果 pairs[i][1] < temp1 , 可以使数对链最后一个数对的第二个数更小,则替换最后一个数对
    • 其他的都跳过.

代码:(Java)

快排函数:

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(nlog⁡n),两层 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(nlog⁡n)。

  • 空间复杂度:O(1)。

注:仅供学习参考!

题目来源:力扣。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

酷酷的懒虫

你的鼓励将是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值