不给自己任何借口
今日题目:
1、插入删除获得随机O(1)复杂度的数据结构–允许重复 ; tag:数组|哈希表|设计
❤2、课程表 tag:DFS|BFS|图|拓扑排序
今日摘录:
成功不必在我,而功力必不唐捐。
——胡适
381. Insert Delete GetRandom O(1) - Duplicates allowed | Difficulty: Medium
Design a data structure that supports all following operations in average O(1) time.
Note: Duplicate elements are allowed.
insert(val): Inserts an item val to the collection.
remove(val): Removes an item val from the collection if present.
getRandom: Returns a random element from current collection of elements. The probability of each element being returned is linearly related to the number of same value the collection contains.
Example:
// Init an empty collection.
RandomizedCollection collection = new RandomizedCollection();
// Inserts 1 to the collection. Returns true as the collection did not contain 1.
collection.insert(1);
// Inserts another 1 to the collection. Returns false as the collection contained 1. Collection now contains [1,1].
collection.insert(1);
// Inserts 2 to the collection, returns true. Collection now contains [1,1,2].
collection.insert(2);
// getRandom should return 1 with the probability 2/3, and returns 2 with the probability 1/3.
collection.getRandom();
// Removes 1 from the collection, returns true. Collection now contains [1,2].
collection.remove(1);
// getRandom should return 1 and 2 both equally likely.
collection.getRandom();
相关题目:Insert Delete GetRandom O(1)
tag:数组|哈希表|设计
题意:设计一个类,使得插入删除获得随机元素复杂度都是O(1),但是允许保留相同元素
思路:
1、用multimap来代替之前的map
class RandomizedCollection {
public:
/** Initialize your data structure here. */
RandomizedCollection() {
}
/** Inserts a value to the collection. Returns true if the collection did not already contain the specified element. */
bool insert(int val) {
int count = map.count(val);
map.insert(make_pair(val,nums.size()));
nums.push_back(val);
return !count;
}
/** Removes a value from the collection. Returns true if the collection contained the specified element. */
bool remove(int val) {
if(map.find(val)!=map.end())
{
int pos = map.find(val)->second;
map.erase(map.find(val),++map.find(val));
int last = nums.back();
nums.pop_back();
nums[pos] = last;
for(auto i=map.begin();i!=map.end();i++)
{
if(i->second==nums.size())
{
i->second=pos;
}
}
return true;
}
else return false;
}
/** Get a random element from the collection. */
int getRandom() {
return nums[rand() % nums.size()];
}
private:
unordered_multimap<int,int>map;
vector<int> nums;
};
/**
* Your RandomizedCollection object will be instantiated and called as such:
* RandomizedCollection obj = new RandomizedCollection();
* bool param_1 = obj.insert(val);
* bool param_2 = obj.remove(val);
* int param_3 = obj.getRandom();
*/
结果:792ms
207. Course Schedule |Difficulty: Medium
There are a total of n courses you have to take, labeled from 0 to n - 1.
Some courses may have prerequisites, for example to take course 0 you have to first take course 1, which is expressed as a pair: [0,1]
Given the total number of courses and a list of prerequisite pairs, is it possible for you to finish all courses?
For example:
2, [[1,0]]
There are a total of 2 courses to take. To take course 1 you should have finished course 0. So it is possible.
2, [[1,0],[0,1]]
There are a total of 2 courses to take. To take course 1 you should have finished course 0, and to take course 0 you should also have finished course 1. So it is impossible.
Note:
The input prerequisites is a graph represented by a list of edges, not adjacency matrices. Read more about how a graph is represented.
tag:BFS|DFS|图|拓扑排序
题意:给定课程总数(编号为0-n-1),和课程之间的相互依赖,求能否修完所有课程。
思路:
1、根据题目给出的提示,这个问题其实是在一个有向图中去寻找是否存在环,如果存在则不能满足,如果不存在则说明能够满足条件。由于之前并未接触过什么图算法,所以这里直接看了下discuss,参考了jianchao.li.fighter的solutions,采用DFS和BFS两种方法来解答。
首先看看BFS的方法:
首先建立一个图,用向量来实现,每个元素一个集合,代表依赖于当前节点的那些节点。建好图之后需要针对每个节点去计算入度,如果找不到任何一个入度为0的节点,说明一定存在环路。如果找到入度为0的点,说明这个点没有依赖项,可以想办法将这个点从图中删除,只需要将当前点和所有与当前点有连接的点的入度全部减1,然后继续下一轮的判断,如果知道最后都没找到形成环路的条件,则返回true。
class Solution {
public:
bool canFinish(int numCourses, vector<pair<int, int>>& prerequisites) {
vector<unordered_set<int>>graph= make_graph(numCourses,prerequisites);
vector<int> degrees = count_indegrees(graph);
for(int i=0;i<numCourses;i++)
{
int j=0;
for(;j<numCourses;j++)
{
if(!degrees[j]) break;
}
if(j==numCourses) return false;
degrees[j]--;
for(auto k:graph[j])
degrees[k]--;
}
return true;
}
private:
vector<unordered_set<int>>make_graph(int numCourses,vector<pair<int,int>>&prerequisites)
{
vector<unordered_set<int>> graph(numCourses);
for(auto request:prerequisites)
{
graph[request.first].insert(request.second);
}
return graph;
}
vector<int> count_indegrees(vector<unordered_set<int>>&graph)
{
vector<int>degrees(graph.size(),0);
for(auto nodes:graph)
{
for(auto node:nodes)
degrees[node]++;
}
return degrees;
}
};
结果:52ms
2、DFS:
首先从一个节点开始,已知递归去访问当前节点的邻居,并记录下当前的路径,如果在访问过程中遇到当前路径上的点,说明有环路。
class Solution {
public:
bool canFinish(int numCourses, vector<pair<int, int>>& prerequisites) {
vector<unordered_set<int>>graph= make_graph(numCourses,prerequisites);
vector<bool>visited(numCourses,false);
vector<bool>cur(numCourses,false);
for(int i=0;i<numCourses;i++)
{
if(!visited[i]&&has_circle(graph,i,visited,cur))
return false;
}
return true;
}
private:
vector<unordered_set<int>>make_graph(int numCourses,vector<pair<int,int>>&prerequisites)
{
vector<unordered_set<int>> graph(numCourses);
for(auto request:prerequisites)
{
graph[request.first].insert(request.second);
}
return graph;
}
bool has_circle(vector<unordered_set<int>>&graph,int node,vector<bool>&visited,vector<bool>&cur)
{
if(cur[node]) return true;
visited[node] = cur[node] = true;
for(auto neighbor : graph[node])
{
if(cur[neighbor] || has_circle(graph,neighbor,visited,cur))
return true;
}
cur[node] = false;
return false;
}
};
结果:50ms