leetcode1488避免洪水泛滥

题目大意

你的国家有无数个湖泊,所有湖泊一开始都是空的。当第 n 个湖泊下雨的时候,如果第 n 个湖泊是空的,那么它就会装满水,否则这个湖泊会发生洪水。你的目标是避免任意一个湖泊发生洪水。

给你一个整数数组 rains ,其中:

  • rains[i] > 0 表示第 i 天时,第 rains[i] 个湖泊会下雨。
  • rains[i] == 0 表示第 i 天没有湖泊会下雨,你可以选择 一个 湖泊并 抽干 这个湖泊的水。

请返回一个数组 ans ,满足:

  • ans.length == rains.length
  • 如果 rains[i] > 0 ,那么ans[i] == -1 。
  • 如果 rains[i] == 0 ,ans[i] 是你第 i 天选择抽干的湖泊。

如果有多种可行解,请返回它们中的 任意一个 。如果没办法阻止洪水,请返回一个 空的数组 。

请注意,如果你选择抽干一个装满水的湖泊,它会变成一个空的湖泊。但如果你选择抽干一个空的湖泊,那么将无事发生(详情请看示例 4)。

示例 1:

输入:rains = [1,2,3,4]
输出:[-1,-1,-1,-1]
解释:第一天后,装满水的湖泊包括 [1]
第二天后,装满水的湖泊包括 [1,2]
第三天后,装满水的湖泊包括 [1,2,3]
第四天后,装满水的湖泊包括 [1,2,3,4]
没有哪一天你可以抽干任何湖泊的水,也没有湖泊会发生洪水。

解题思路

用一个map记录哪些湖下过雨(key),同时记录上一次下雨是哪一天(value)。记录一下哪几天是晴天(可用于抽湖水的天)。
另外,当前第k天第j个湖下雨了,且之前的第i天第j个湖也下雨了,则需要在第i~k天内找一个晴天,用来抽取第j个湖的湖水。
关键是用哪一个晴天抽水:首先第i天之前的晴天肯定无法用来抽水(因为还没下雨),另一方面,若rains=[1,0,2,0,1,2],若用第2个晴天来抽1号湖水,则2号湖水就无法被抽取。综上所述,策略是:找到第一个大于i的晴天,用来抽水
剩下的见代码注释:

	class Solution {
     
	public:
		vector<int> avoidFlood(vector<int>& rains) {
     
			int rains_size = rains.size();
			//因为最后如果有晴天但是不是必要的抽水天气时仍要给一个值
			vector<int> ans(rains_size, 1);
			//key是第几个湖,value是上一次下雨在rains中的索引i
			unordered_map<int, int> last_rain;
			//存晴天在rains中的索引
			set<int> sun;
			for (int i = 0; i < rains_size; ++i)
			{
     
				int ii = rains.at(i);  // 当天哪个湖下雨
				if (ii == 0)   //  没有下雨的湖
				{
     
					sun.insert(i);  // 第i天是晴天,可用来抽水,存入sun中
					continue;
				}
				// 第i天下雨了,且第ii个湖之前已经下过雨了
				if (last_rain.find(ii) != last_rain.end())
				{
     	// 第ii个湖上次下雨的天数是last_rain[ii],找到第一个大于该天的晴天
					auto p = sun.lower_bound(last_rain[ii]);
					// 如果last_rain[ii]天之后没有晴天了,则这个湖水无法抽取,返回{}
					if (p == sun.end())
						return {
     };
					ans.at(*p) = ii;  // 记录第p天抽取第ii个湖的湖水
					sun.erase(p);  // 该晴天已经被用来抽水了,排除掉
				}
				last_rain[ii] = i;
				ans.at(i) = -1;  // 只要第i天下雨了,就是-1
			}
			return ans;
		}
	};

你可能感兴趣的:(leetcode算法题解)