leetcode 632.最小区间

题目

你有 k 个升序排列的整数数组。找到一个最小区间,使得 k 个列表中的每个列表至少有一个数包含在其中。
我们定义如果 b-a < d-c 或者在 b-a == d-c 时 a < c,则区间 [a,b] 比 [c,d] 小。

题解

大纲思路如下:

1、定义一个当前最优解的数组 R,格式为 [x, y]
2、定义一个迭代数列 D,长度为k,格式为 [ x1, x2, x3, …, xk ]
3、首先,取出每一个数组中最小的数放入迭代数列 D 中,计算当前最优解的值 R
4、之后,选择迭代数组中最小的那个,将其替换为其对应数组中的下一个数,再对迭代数列 D 进行最优解计算,将计算结果与 R 进行比较,若优于 R 则替换 R ,否则跳过,继续进行该步骤,直至每一个数列都取到了最后一个数为之。

具体函数设计:
1、数据基础设定

数据名称数据类型数据用途
Rint[]最优解数组
Dint[]迭代数组
indexint[]当前迭代位置下表数组
numsList<List<Intager>>k个升序排列的有序数组

2、辅助函数设计
ArrayFull()

输入:nums、index
输出:boolean
功能:判断当前循环是否到达数组最后一位,仅全部的 index[i] = nums[i].size() 时返回 false ,否则返回 true

ArrayBest()

输入:D
输出:R#
功能:计算当前迭代数组的最优解,并返回当前数组最优解

ArraySmallest()

输入:D
输出:s
功能:找出最小的数的下标的下一位

RightIndex()

输入:D、index、nums
输出:k
功能:修正ArraySmallest()函数寻找的下标,保证其下标不是该数组的最后一位

CompareR()

输入:R、Ri
输出:R
功能:比较R与Ri谁更小

3、主函数设计

初始化数据
当ArrayFull()函数为true时,执行以下循环:
寻找最小数下标
更新index,指定下标的index+1
更新迭代数组D
更新最终结果R

程序

待修改的代码:

public class SmallestRange {
	
	public int[] smallestRange(List<List<Integer>> nums) {
		int[] R = new int[2];  //当前最优解
		List<Integer> D = new ArrayList<Integer>(nums.size());  //迭代数组
		List<Integer> index = new ArrayList<Integer>(nums.size());  //迭代指针
		int smallest_index;
		
		for(int i = 0; i < nums.size(); i++) {  //初始化迭代数组
			D.add(nums.get(i).get(0));
		}
		R = this.ArrayBest(D);  //初始化最优解数组
		for(int i = 0; i < nums.size(); i++) {  //初始化迭代下标
			index.add(0);
		}
		
		while( this.ArrayFull(nums, index) ) {
			/*  
			 *  寻找最小数下标
			 *  更新index,指定下标的index+1
			 *  更新迭代数组D
			 */
			smallest_index = this.RightIndex(D, index, nums);
			index.set(smallest_index, index.get(smallest_index)+1);
			D.set(smallest_index, nums.get(smallest_index).get(index.get(smallest_index))); 
			R = this.ArrayBest(D);
		}
		return R;
    }
	
	public boolean ArrayFull(List<List<Integer>> nums, List<Integer> index) {
		// 判断index是否均为最后一位
		for(int i = 0; i < index.size(); i++) {
			if(index.get(i) == nums.get(i).size() - 1) {
				continue;
			}else {
				return true;
			}
		}
		return false;
	}
	
	public int[] ArrayBest(List<Integer> D) {
		//  计算当前迭代数组的最优解,并返回当前数组最优解
		int[] Ri = new int[2];
		
		if(D.get(0) < D.get(1)) {
			Ri[0] = D.get(0);
			Ri[1] = D.get(1);
		}else {
			Ri[0] = D.get(1);
			Ri[1] = D.get(0);
		}
		
		for(int i = 2; i < D.size(); i++) {
			if(D.get(i) > Ri[1]) {
				Ri[1] = D.get(i);
			}else if(D.get(i) < Ri[0]) {
				Ri[0] = D.get(i);
			}
		}
		return Ri;
	}
	
	public int ArraySmallest(List<Integer> D) {
		//  寻找数组D中最小的数的下标
		int z = D.get(0);
		int k = 0;
		for(int i = 1; i < D.size(); i++) {
			if(D.get(i) < z) {
				z = D.get(i);
				k = i;
			}
		}
		return k;
	}
	
	public int RightIndex(List<Integer> D, List<Integer> index, List<List<Integer>> nums) {
		//  修正下标,确保下表不是最后一位
		int k = this.ArraySmallest(D);
		List<Integer> D_cut = new ArrayList<Integer>();
		for(int i = 0; i < D.size(); i++) {
			D_cut.add(index.get(i));
		}
		
		while( index.get(k) == nums.get(k).size()-1 ) {
			
			D_cut.remove(k);
			k = this.ArraySmallest(D_cut);
			
		}
		return k;
	}
	
	public int[] CompareR(int[] R, int[] Ri) {
		
		if(R[1] - R[0] > Ri[1] - Ri[0]) {
			return Ri;
		}else if(R[1] - R[0] < Ri[1] - Ri[0]){
			return R;
		}else if(R[1] - R[0] == Ri[1] - Ri[0]){
			if(R[0] > Ri[0]) {
				return Ri;
			}else {
				return R;
			}
		}
		
		return R;
	}
	
	
	//测试主函数
	public static void main(String[] args) {
		SmallestRange s = new SmallestRange();
		List<List<Integer>> L = new ArrayList<List<Integer>>();
		Integer[][] k = {{4,10,15,24,26}, {0,9,12,20}, {5,18,22,30}};
		for(int i = 0; i < k.length; i++ ) {
			L.add((List<Integer>)Arrays.asList(k[i]));
		}
		
		//int[] R = s.smallestRange(L);
		//System.out.println(R);
		
		int[] R = {20, 24};
		int[] Ri = {20, 26};
		System.out.println(s.CompareR(R, Ri)[0] + s.CompareR(R, Ri)[1]);
		
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值