632. Smallest Range

description:

632
Smallest Range   
42.2% Hard

You have k lists of sorted integers in ascending order. Find the smallest range that includes at least one number from each of the k lists.

We define the range [a,b] is smaller than range [c,d] if b-a < d-c or a < c if b-a == d-c.

Example 1:

Input:[[4,10,15,24,26], [0,9,12,20], [5,18,22,30]]
Output: [20,24]
Explanation: 
List 1: [4, 10, 15, 24,26], 24 is in range [20,24].
List 2: [0, 9, 12, 20], 20 is in range [20,24].
List 3: [5, 18, 22, 30], 22 is in range [20,24].

Note:

  1. The given list may contain duplicates, so ascending order means >= here.
  2. 1 <= k <= 3500
  3. -105 <= value of elements <= 105.
  4. For Java users, please note that the input type has been changed to List>. And after you reset the code template, you'll see this point.

my solution:
事实上这道题我没想出来要怎么解决……一开始我的思路是暴力求解,找出所有ans可能的排列组合然后再一一比较,但是这样所消耗的时间空间资源太大,所以并不适合这个题目。阅读了别人的解决方案。

better ways:
by Aeonaxx
#pragma once
#include
#include
#include
#include
#include
using namespace std;

class Solution {
public:
	vector smallestRange(vector>& nums) {
		//构建迭代器
		typedef vector::iterator vi;

		//构建comp用于比较,用于priority_queue,小根堆,升序
		struct comp {
			bool operator()(pair p1, pair p2) {
				return *p1.first > *p2.first;
			}
		};

		int lo = INT_MAX, hi = INT_MIN;
		//创建queue
		priority_queue, vector>, comp> pq;
		//初始化lo和hi,lo是每个队列的最小值,hi是每个队列开头的最大值
		//把nums中每一个队列的开头和结束迭代器放入priority_queue中
		for (auto &row : nums) {
			lo = min(lo, row[0]);
			hi = max(hi, row[0]);
			pq.push({ row.begin(), row.end() });
		}

		vector ans = { lo, hi };
		while (true) {
			auto p = pq.top();//取出堆顶队列
			pq.pop();
			++p.first;//原堆顶队列的下一个元素
			if (p.first == p.second)
				break;//如果队列已经全部遍历则终止
			pq.push(p);//放回该队列

			//如果区间缩小,则重新赋值
			lo = *pq.top().first;//新堆顶元素
			hi = max(hi, *p.first);//原堆顶元素
			if (hi - lo < ans[1] - ans[0])
				ans = { lo, hi };
		}
		return ans;
	}
};

thought:

这个人的解法十分和谐方便,巧妙利用了stl,值得学习。

你可能感兴趣的:(算法,Algorithms,priority_queue)