【问题标题】:Maximum value stocks, implementation details最大价值股票,实施细节
【发布时间】:2018-07-17 09:26:27
【问题描述】:

我在面试时被问到这样一个问题:

给定股票的价格:

MS  | 500   
Apl | 1000  
Nefx| 500   
MS  | 500   

每次有新库存出现时,我们都必须添加到现有库存中,或者如果它是新库存,则只会让其感到不适。所以这个结果应该是MS - 1000, Apl - 1000, Nefs - 500.

我们应该有两个功能:

void add(string, int); // adds new stock  
void display(unsigned n); // displays top n stocks

所以我是这样实现的:

unordered_map<string, int> UM;
void add(string s, int n)
{
    auto iter = M.find(s);
    if(s==M.end())
    { 
        M[str] = n;
    }
    else
    {
        M[str] += n; 
    }
}

void display(unsigned n)
{
    std::map<int,string> M;
    for(auto iter = UM.begin(); iter!=UM.end(); ++iter)
    {
        M.insert(make_pair(iter->second, iter->first));
    }
    for(auto iter = M.rbegin(); iter!=M.rend(); ++iter)
    {
        if(n==0){break;}
        cout<<iter->second<<" "<<iter->first<<endl;
        n--;
    }
}

虽然add函数非常有效,如果散列完美的话O(1),但是dislpay太慢了,O(NlogN) + n。无论我们必须显示多少项目,我们都会操作所有项目。有没有更有效的方法来解决这个问题,即使它需要改变 add 函数??

【问题讨论】:

  • @Someprogrammerdude 为什么哈希完美时找不到 O(1)?
  • 使用最大堆怎么样?
  • 我需要前N个价值股@Someprogrammerdude,如何在UM中找到未排序的?
  • 您不需要在add 函数中调用find。并且请清楚需求,不清楚的需求是程序员和开发者痛苦的一大原因。
  • 这可以通过一个结构 using PriceAndTickers = std::set&lt;std::pair&lt;int, std::string&gt;&gt;; 和另一个查找结构 std::unordered_map&lt;std::string, PriceAndTickers::iterator&gt; 来完成。使用此解决方案,添加为 O(log N),显示为 O(n)。

标签: c++ algorithm hash stl


【解决方案1】:

add 函数应该是单行的UM[s] += n;。没有其他必要了。

显示速度太慢,O(NlogN) + n

您可以将指向UM 元素的指针复制到一个向量中,并对n 顶部元素执行std::partial_sort,复杂性O(size*log(n))

void display(unsigned n) {
    n = std::min<unsigned>(n, UM.size());
    std::vector<std::reference_wrapper<decltype(UM)::value_type>> v(UM.begin(), UM.end());
    std::partial_sort(v.begin(), v.begin() + n, v.end(), [](auto a, auto b) { return a.get().second > b.get().second; });
    for(auto p = v.begin(); n--; ++p)
        std::cout << p->get().second << " " << p->get().first << '\n';
}

使用O(n) 额外存储(而不是上面的O(N)):

template<class T, class Less>
void insert_sorted_ref(std::vector<T const*>& v, T const& element, Less&& less) {
    auto i = std::lower_bound(v.begin(), v.end(), &element, less);
    if(i == v.end()) {
        if(v.size() < v.capacity())
            v.insert(i, &element);
    }
    else if(less(&element, *i)) {
        if(v.size() == v.capacity())
            v.pop_back();
        v.insert(i, &element);
    }
}

void display(unsigned n) {
    std::vector<decltype(UM)::value_type const*> v;
    v.reserve(std::min<unsigned>(n, UM.size()));
    auto greater = [](auto* a, auto* b) { return a->second > b->second; };
    for(auto const& sn : UM)
        insert_sorted_ref(v, sn, greater);
    for(auto const& p : v)
        std::cout << p->second << " " << p->first << '\n';
}

【讨论】:

  • 这需要 O(N) 内存,可以在 O(n) 内完成(N 是元素的总数,n 是您要显示的数量)。
  • @DavidRodríguez-dribeas 添加了O(n) 存储版本。
【解决方案2】:

类似这样的:

struct PriceAndTicker {
    PriceAndTicker(int price, const std::string& ticker)
        : price(price), ticker(ticker) {}

    int price;
    std::string ticker;
};

bool operator<(const PriceAndTicker& lhs, const PriceAndTicker& rhs) {
    return lhs.price > rhs.price
        || (lhs.price == rhs.price && lhs.ticker < rhs.ticker);
}

std::set<PriceAndTicker> priceAndTickers;
std::unordered_map<std::string, std::set<PriceAndTicker>::iterator> tickerLookup;

void add(const std::string& s, int priceChange) {
    int newPrice;
    auto it = tickerLookup.find(s);
    if (it == tickerLookup.end()) {
        newPrice = priceChange;
    } else {
        newPrice = it->second->price + priceChange;
        priceAndTickers.erase(it->second);
    }
    tickerLookup.emplace(
        s, priceAndTickers.emplace(newPrice, s).first);
}

void display(size_t n) {
    size_t counter = 0;
    for (auto it = priceAndTickers.begin(); it != priceAndTickers.end(); ++it) {
        if (counter++ == n) {
            break;
        }
        std::cout << it->ticker << " " << it->price << "\n";
    }
}

add 的时间复杂度为 O(log N),display 的时间复杂度为 O(n)。

【讨论】:

    猜你喜欢
    • 2016-08-29
    • 1970-01-01
    • 1970-01-01
    • 2011-03-15
    • 2017-12-14
    • 2012-03-19
    • 1970-01-01
    • 2020-04-21
    • 2010-12-12
    相关资源
    最近更新 更多