对于力扣2025,10,7的每日的一点反思(非递归并查集写法)
这次我写的二分的cpp,写的比较繁琐,而且WA了很多发
代码如下:
class Solution {
public:vector<int> avoidFlood(vector<int>& rains) {int n = rains.size();vector<int> ans(n,-1);vector<int> cnt0 ;int length_cnt = 0 ;unordered_map<int,int> has;for (int i = 0 ;i<n ; i ++){// printf("%d",length_cnt);if (rains[i] > 0){if (has.find(rains[i]) == has.end()){// cout<<"True"<<endl;has[rains[i]] = i;}else{auto it = upper_bound(cnt0.begin(), cnt0.end(), has[rains[i]]);if( it != cnt0.end()){// for(auto&i :cnt0){// cout <<i<<" "<<endl;// }// while (length_cnt >0 and cnt0.front() <= has[rains[i]]){// cnt0.pop_front();// length_cnt --;// }// cout <<"True"<<endl;// if (length_cnt>0){ans[*it] = rains[i];length_cnt--;// cout<<"True"<<endl;cnt0.erase(it);has[rains[i]] = i;// }else{// vector<int> tmp;// return tmp;// }}else{// cout<<i<<endl;vector<int> tmp;return tmp;}}ans[i] = -1;}else{cnt0.push_back(i);length_cnt ++;}}for (int i = 0 ;i < n; i ++){if (rains[i] == 0 && ans[i] ==-1)ans[i] = 1;}return ans;}
};
这个代码放这这里仅仅作为纪念,毕竟我熟悉了一些cpp的语法,比如lower_bound,vector的push_back,以及unordered_map的erase。
这道题最让我感到惊艳的是灵神的并查集算法。
并查集算法又称为认祖归宗算法,其基本思想是通过数组的祖先关系对元素实现聚类,从而能更快得搜索到元素的聚类团。
而并查集算法在本题的应用是,把删除的抽水天进行从小到大的认祖归宗,然后能比二分更快找到需要安排的位置。
然后灵神写了一个非递归的并查集 ,用Python写的, 我觉得很有意思,所以放在这里学习一下。
class Solution:def avoidFlood(self, rains: List[int]) -> List[int]:n = len(rains)# 非递归并查集fa = list(range(n + 1))def find(x: int) -> int:rt = xwhile fa[rt] != rt:rt = fa[rt]while fa[x] != rt:fa[x], x = rt, fa[x]return rtans = [-1] * nfull_day = {} # lake -> 装满日for i, lake in enumerate(rains):if lake == 0:ans[i] = 1 # 先随便选一个湖抽干continueif lake in full_day:j = full_day[lake]# 必须在 j 之后,i 之前把 lake 抽干# 选一个最早的未被使用的抽水日,如果选晚的,可能会导致其他湖没有可用的抽水日dry_day = find(j + 1)if dry_day >= i:return [] # 无法阻止洪水ans[dry_day] = lakefa[dry_day] = find(dry_day + 1) # 删除 dry_dayfa[i] = i + 1 # 删除 ifull_day[lake] = i # 插入或更新装满日return ans作者:灵茶山艾府
链接:https://leetcode.cn/problems/avoid-flood-in-the-city/solutions/3796865/tan-xin-you-xu-ji-he-bing-cha-ji-pythonj-djlm/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
其中并查集的find函数 ,先用while函数找到祖先,再把这一路上的元素都认了这个祖先。大概这个思路。
我总结板子如下:
class bingchaji:def __init__(self,n):self.fa = [i for i in range(n)] def find(self, cur):now = cur while now != self.fa[now]:now = self.fa[now]while cur != now:self.fa[cur], cur = now ,self.fa[cur]return now
今日算法学习结束,诸位晚安,我慢慢进步。
供交流使用,欢迎批评和指正。