标签:pos 网络 .com 数据 skyline while 代码 style ted
【23】 Merge k Sorted Lists
【215】 Kth Largest Element in an Array (无序数组中最小/大的K个数)(2018年11月30日第一次复习)
给了一个无序数组,可能有重复数字,找到第 k 个最大的元素并且返回这个元素值。
题解:直接用直接用个堆保存数组中最大的 K 个数。时间复杂度是 O(NlogK)。
1 //时间复杂度是 O(NlogK), 用堆辅助。
2 class Solution {
3 public:
4 int findKthLargest(vector<int>& nums, int k) {
5 const int n = nums.size();
6 priority_queue<int, vector<int>, greater<int>> pq;
7 for (int i = 0; i < n; ++i) {
8 if (pq.size() < k) {
9 pq.push(nums[i]);
10 } else {
11 if (pq.top() < nums[i]) {
12 pq.pop();
13 pq.push(nums[i]);
14 }
15 }
16 }
17 return pq.top();
18 }
19 };
本题可以有 O(N) 的解法,详见《剑指offer》或者《程序员代码面试指南》P336
【218】 The Skyline Problem(2019年2月5日,算法群打卡复习)
给了一个tuple list, 每个三元组 [a, b, h] 代表一个楼的x轴坐标是在[a, b],楼的高度是 h,返回所有楼轮廓的左上角坐标。
题解:用了一个 multiset 来存这个楼是进来还是出去,如果是进来,就存[a, h], 如果是出去,就存[b, -h]。 然后遍历这个 multiset,如果这个楼是进来的话,就看当前高度它是不是最高的,如果是,那么这个点在答案中,如果这个楼是出去的话,先把这个高度删除,然后看当前这个高度是不是比剩下所有楼都高,如果是,就把当前坐标和剩下的最高的楼组成的坐标加入答案中。
1 class Solution { 2 public: 3 vector<pair<int, int>> getSkyline(vector<vector<int>>& buildings) { 4 for (auto& b : buildings) { 5 record.insert(make_pair(b[0], b[2])); 6 record.insert(make_pair(b[1], -b[2])); 7 } 8 vector<pair<int, int>> ret; 9 for (auto& r : record) { 10 bool entry = r.second > 0 ? true : false; 11 int idx = r.first, h = abs(r.second); 12 // printf("idx = %d, h = %d, entry = %d\n", idx, h, entry); 13 if (entry) { 14 if (h > getMaxHeight()) { 15 ret.push_back(make_pair(idx, h)); 16 } 17 height.insert(h); 18 } else { 19 auto iter = height.find(h); 20 height.erase(iter); 21 if (h > getMaxHeight()) { 22 ret.push_back(make_pair(idx, getMaxHeight())); 23 } 24 } 25 } 26 return ret; 27 } 28 struct kcmp { 29 bool operator() (const pair<int, int>& p1, const pair<int, int>& p2) const { 30 if (p1.first == p2.first) { 31 return p1.second > p2.second; 32 } 33 return p1.first < p2.first; 34 } 35 }; 36 multiset<pair<int, int>, kcmp> record; 37 multiset<int> height; 38 int getMaxHeight() { 39 if (height.empty()) {return 0;} 40 return *height.rbegin(); 41 } 42 };
【239】 Sliding Window Maximum
【253】 Meeting Rooms II
题意是252的升级版,给了一个数组,数组里面的每个元素代表一个会议的开始时间和结束时间,问想安排下所有的会议,至少需要多少个会议室。
题解:这个题目在 sort 的分类里面说过,链接:https://www.cnblogs.com/zhangwanying/p/9914941.html
【264】 Ugly Number II
【295】 Find Median from Data Stream (2018年11月30日,堆的题目)
给了一个数据流,设计api接口,addNum() 用于接收一个数,findMedian() 用于返回数据流的中位数。返回数据流的中位数。
Example: addNum(1) addNum(2) findMedian() -> 1.5 addNum(3) findMedian() -> 2
题解:这题是今天看算法课看到的一个题,我们用一个大根堆存储数据流比较小的一半数字,用一个小根堆存数据流的比较大的一半数字。(这两个堆的元素个数要么相等,要么存小数的那个堆比存大数的那个堆多存一个数。)中位数如果两个堆元素个数相差 1 ,那么就返回大根堆的堆顶。不然返回两个堆顶的平均数。
1 class MedianFinder { 2 public: 3 /** initialize your data structure here. */ 4 MedianFinder() { 5 6 } 7 void addNum(int num) { 8 lowhalf.push(num); 9 int k = lowhalf.top(); lowhalf.pop(); 10 highhalf.push(k); 11 if (lowhalf.size() < highhalf.size()) { 12 k = highhalf.top(); highhalf.pop(); 13 lowhalf.push(k); 14 } 15 return; 16 } 17 double findMedian() { 18 if (lowhalf.size() == highhalf.size()) { 19 return (double)(lowhalf.top() + highhalf.top()) / 2; 20 } 21 return (double)lowhalf.top(); 22 } 23 priority_queue<int, vector<int>, greater<int>> lowhalf; //小根堆存大的那边 24 priority_queue<int> highhalf; //大根堆存小的那边 25 }; 26 27 /** 28 * Your MedianFinder object will be instantiated and called as such: 29 * MedianFinder obj = new MedianFinder(); 30 * obj.addNum(num); 31 * double param_2 = obj.findMedian(); 32 */
【313】 Super Ugly Number
【347】 Top K Frequent Elements
【355】 Design Twitter (2018年12月3日,heap专题)
实现四个 api。
Example: Twitter twitter = new Twitter(); // User 1 posts a new tweet (id = 5). twitter.postTweet(1, 5); // User 1‘s news feed should return a list with 1 tweet id -> [5]. twitter.getNewsFeed(1); // User 1 follows user 2. twitter.follow(1, 2); // User 2 posts a new tweet (id = 6). twitter.postTweet(2, 6); // User 1‘s news feed should return a list with 2 tweet ids -> [6, 5]. // Tweet id 6 should precede tweet id 5 because it is posted after tweet id 5. twitter.getNewsFeed(1); // User 1 unfollows user 2. twitter.unfollow(1, 2); // User 1‘s news feed should return a list with 1 tweet id -> [5], // since user 1 is no longer following user 2. twitter.getNewsFeed(1);
题解:用个 unordered_map 标记用户关系,然后一个 vector 存储 twitter post
1 class Twitter { 2 public: 3 /** Initialize your data structure here. */ 4 Twitter() { 5 6 } 7 8 /** Compose a new tweet. */ 9 void postTweet(int userId, int tweetId) { 10 twit.push_back(make_pair(userId, tweetId)); 11 } 12 13 /** Retrieve the 10 most recent tweet ids in the user‘s news feed. Each item in the news feed must be posted by users who the user followed or by the user herself. Tweets must be ordered from most recent to least recent. */ 14 vector<int> getNewsFeed(int userId) { 15 set<int> people = followRelation[userId]; 16 people.insert(userId); 17 vector<int> ret; 18 int idx = twit.size() - 1, cnt = 0;; 19 while (cnt < 10 && idx >= 0) { 20 auto p = twit[idx--]; 21 int uid = p.first, tid = p.second; 22 if (people.find(uid) != people.end()) { 23 ret.push_back(tid); 24 cnt++; 25 } 26 } 27 return ret; 28 } 29 30 /** Follower follows a followee. If the operation is invalid, it should be a no-op. */ 31 void follow(int followerId, int followeeId) { 32 followRelation[followerId].insert(followeeId); 33 } 34 35 /** Follower unfollows a followee. If the operation is invalid, it should be a no-op. */ 36 void unfollow(int followerId, int followeeId) { 37 if (followRelation.find(followerId) == followRelation.end()) { return; } 38 if (followRelation[followerId].find(followeeId) == followRelation[followerId].end()) {return;} 39 followRelation[followerId].erase(followeeId); 40 } 41 42 unordered_map<int, set<int>> followRelation; 43 vector<pair<int, int>> twit; // (user, id) 44 }; 45 46 /** 47 * Your Twitter object will be instantiated and called as such: 48 * Twitter obj = new Twitter(); 49 * obj.postTweet(userId,tweetId); 50 * vector<int> param_2 = obj.getNewsFeed(userId); 51 * obj.follow(followerId,followeeId); 52 * obj.unfollow(followerId,followeeId); 53 */
【358】 Rearrange String k Distance Apart
【373】 Find K Pairs with Smallest Sums (2018年12月1日)
给了两个整数数组 nums1 和 nums2, 和一个整数 k,求 nums1 和 nums2 的笛卡尔积中(就是 nums1 中选择一个数字 n1,nums2 中选择一个数字 n2 组成pair),sum 最小的 k 个pair。
题解:本题就是自定义排序的大根堆,pair排序的规则是 sum 大的在堆顶。
1 class Solution { 2 public: 3 vector<pair<int, int>> kSmallestPairs(vector<int>& nums1, vector<int>& nums2, int k) { 4 if (nums1.empty() || nums2.empty()) {return vector<pair<int, int>>();} 5 priority_queue<pair<int, int>, vector<pair<int, int>>, cmp> pq; 6 for (auto n1 : nums1) { 7 for (auto n2 : nums2) { 8 pq.push(make_pair(n1, n2)); 9 if (pq.size() > k) { pq.pop(); } 10 } 11 } 12 vector<pair<int, int>> ret; //可能nums1和nums2的组合的pair不够 k 个,所以不能一开始初始化为 k 个结果。 13 while (!pq.empty()) { 14 ret.push_back(pq.top()); 15 pq.pop(); 16 } 17 return ret; 18 } 19 struct cmp{ 20 bool operator()(const pair<int, int>& p1, const pair<int, int>& p2) { 21 return p1.first + p1.second < p2.first + p2.second; 22 } 23 }; 24 };
【378】 Kth Smallest Element in a Sorted Matrix
【407】 Trapping Rain Water II
【451】 Sort Characters By Frequency
【502】 IPO
【659】 Split Array into Consecutive Subsequences
【692】 Top K Frequent Words (2018年11月30日)
给了一个string类型的数组 words,在给定整数k,请严格按照出现频率顺序打印出现次数前 k 名的字符串。(出现频率相同的按照字典顺序打印)
题解:用个 unordered_map 存储每个单词出现的次数,然后建立一个小根堆,里面存 k 个pair,(小根堆自定义排序class),然后遍历一遍map,把最后剩下在堆里的 k 个pair的字符串提取出来。
1 class Solution { 2 public: 3 vector<string> topKFrequent(vector<string>& words, int k) { 4 const int n = words.size(); 5 unordered_map<string, int> mp; 6 for (auto w : words) { mp[w]++; } 7 8 priority_queue<pair<string, int>, vector<pair<string, int>>, cmp> pq; 9 for (auto ele : mp) { 10 pq.push(ele); 11 if (pq.size() > k) { pq.pop(); } 12 } 13 vector<string> ret(k, ""); 14 int idx = k-1; 15 while (!pq.empty()) { 16 auto p = pq.top(); 17 pq.pop(); 18 ret[idx--] = p.first; 19 } 20 return ret; 21 } 22 //自定义比较函数,为啥我想小的排前面要写大于。。 23 struct cmp { 24 bool operator()(const pair<string, int> a, const pair<string, int>& b) { 25 if (a.second == b.second) { 26 return a.first < b.first; 27 } 28 return a.second > b.second; 29 } 30 }; 31 };
//自定义比较函数,为啥我想小的排前面要写大于。。(优先队列的自定义比较函数要搞明白,还是不懂啊)
【703】 Kth Largest Element in a Stream
给个数字流,总是返回最大的第K个元素
解法就是用一个只有K个元素的堆,维护这这些数字里面从最大的第K个到最大的元素。
[最小元素...第K大的元素..最大元素], 这个堆总维护后半段的K个
【719】 Find K-th Smallest Pair Distance
【743】 Network Delay Time (2018年12月4日)
一个社交网络里面有 N 个结点,标号为 1 ~ N,给了一个 times 数组,里面的元素 t(u, v, w) 代表从 u结点 到 v结点需要 w 的时间,给了一个源点 K, 问从 K 开始传播一条信息,到每个结点需要至少多少时间,如果从 K 到一个结点不可达,就返回 -1。
题解:floyed求最短路。
1 class Solution { 2 public: 3 int networkDelayTime(vector<vector<int>>& times, int N, int K) { 4 vector<vector<int>> g(N+1, vector<int>(N+1, INT_MAX)); 5 for (auto t : times) { 6 int u = t[0], v = t[1], cost = t[2]; 7 g[u][v] = cost; 8 } 9 //floyed 10 for (int f = 1; f <= N; ++f) { 11 for (int i = 1; i <= N; ++i) { 12 g[i][i] = 0; 13 for (int j = 1; j <= N; ++j) { 14 if (g[i][f] != INT_MAX && g[f][j] != INT_MAX) { 15 g[i][j] = min(g[i][f] + g[f][j], g[i][j]); 16 } 17 } 18 } 19 } 20 int ret = INT_MIN; 21 for (int i = 1; i <= N; ++i) { 22 if (i == K) {continue;} 23 if (g[K][i] == INT_MAX) { 24 ret = -1; 25 break; 26 } 27 ret = max(ret, g[K][i]); 28 } 29 return ret; 30 } 31 };
此外,我没看出来跟 heap 有啥关系。
【759】 Employee Free Time
【767】 Reorganize String
【778】 Swim in Rising Water
【786】 K-th Smallest Prime Fraction
【787】 Cheapest Flights Within K Stops
【818】 Race Car
【857】 Minimum Cost to Hire K Workers
【864】 Shortest Path to Get All Keys
【871】 Minimum Number of Refueling Stops
【882】 Reachable Nodes In Subdivided Graph
标签:pos 网络 .com 数据 skyline while 代码 style ted
原文地址:https://www.cnblogs.com/zhangwanying/p/9357141.html