leetcode题解日练--2016.8.9

不给自己任何借口

今日题目:

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值