【20230830】求线段最大重合数

题目:求线段最大重合数

给定很多线段,每个线段都有两个数[start,end],表示线段开始位置和结束位置,左右都是闭区间,所有的线段都记录在整数数组 lines ,其中lines[i] = [Xstart, Xend]。

规定:

  1. 线段开始和结束位置一定是整数
  2. 线段重合区域的长度必须 >= 1

返回线段最多重合区域中,包含了几条线段

示例1:

输入:lines=[ [3,6], [2,8],[4,7],[7,12] ]

输出:3

解题思路

方案一:暴力解法

思路:

有题目可知,线段的开始位置和结束位置都是整数,且线段长度大于等于1。因此,假设有个线段为[0,1],那么0.5肯定在该线段上。由此,可以通过暴力方式,求解数组中没一个x.5位置所在的线段个数,从而取最大值。

代码实现:
  1. 先求出数组的左右边界值,左边界为所有线段开始位置的最小值,右边界为所有线段结束位置的最大值。
  2. 循环计算每一个X.5位置线段重合个数。
	public static int maxCoverCount1( int[][] lines ){
		//1.计算左右边界
		int left = 0;
		int right = 0;

		for( int i = 0; i < lines.length; i++ ){
			left = Math.min( left, lines[ i ][ 0 ] );
			right = Math.max( right, lines[ i ][ 1 ] );
		}

		//2.暴力寻找包含X.5位置线段个数
		int max = 0;
		for( double p = left + 0.5; p < right; p += 1 ){
			int cur = 0;
			for( int i = 0; i < lines.length; i++ ){
				if( lines[ i ][ 0 ] < p && p < lines[ i ][ 1 ] ){
					cur++;
				}
			}
			max = Math.max( max, cur );
		}
		return max;
	}

方案二: 使用小根堆

思路:

给定的lines数组中的线段是无序的,计算线段重合个数时,由于线段无序,就需要同时考虑开始和结束两个位置的大小。

可以通过将数组按照开始位置排序,减少重合判断条件。此时,只需要比较某个线段的结束位置是否小于下一个线段的开始位置。

如过一个线段的结束位置小于另一个线段的开始位置,这两条线段肯定是不重合的。

已给定数组 lines = [ [3,6], [2,8],[4,7],[7,12] ] 为例。

排序后数组为:

lines = [ [2,8], [3,6],[4,7],[7,12] ]

  1. 小根堆 [ ] --> 执行 [2, 8] --> 小根堆 [8 ] ; count =1
  2. 执行 [3, 6]–>8大于3 --> 小根堆 [6,8 ] ; count =2
  3. 执行 [4,7] -->6,8都大于4 -->小根堆 [6,7,8 ] ; count =3
  4. 执行 [7,12]–> 6,7,8都小于12,小根堆弹出6,7,8 -->小根堆 [12 ]; count =1
代码实现

步骤:

  1. 将所有的线段按照开始位置进行排序,目的是为了保证任何一个线段尾部dou可以从右侧进来。
  2. 准备一个小根堆,用来存放线段的尾部。
  3. 对于每条线段,先将小跟堆中所有小于线段起点的数弹出。
  4. 将线段的尾部加入小根堆中,此时,小根堆中的数据个数就是重合的线段个数。
  5. 计算当前小跟堆大小,取最大值。
	public int maxCoverCount( int[][] lines ){

		if( lines.length == 0 ){
			return 0;
		}
		// 1.排序
		Arrays.sort( lines, ( x, y ) -> Integer.compare( x[ 0 ], y[ 0 ] ) );

		int max = 0;
		// 创建小根堆
		PriorityQueue<Integer> heap = new PriorityQueue<>();
		for( int i = 0; i < lines.length; i++ ){
			// 判断线段是否重合,并计算堆的长度
			while( !heap.isEmpty() && heap.peek() <= lines[ i ][ 0 ] ){
				heap.poll();
			}
			heap.add( lines[ i ][ 1 ] );
			max = Math.max( max, heap.size() );
		}
		return max;
	}

总结

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值