优先级队列作为最大优先级队列不按预期工作。

huangapple go评论77阅读模式
英文:

priority queue as max priority queue not working as expected

问题

我正在处理一个leetcode问题,我们需要设计基本的推特功能,例如关注和取消关注、发推文以及新闻源,该新闻源会为用户提供最近的10条推文。

postTweet(userId, tweetId): 发布一条新推文。
getNewsFeed(userId): 获取用户新闻源中最近的10条推文ID。新闻源中的每个项目必须由用户关注的用户或用户本人发布。推文必须按照从最近到最旧的顺序排序。
follow(followerId, followeeId): 关注者关注一个被关注者。
unfollow(followerId, followeeId): 关注者取消关注一个被关注者。

import java.time.Instant;
import java.util.*;

class Twitter {

    Map<Integer, List<Integer>> followMap = new HashMap<Integer, List<Integer>>();
    Queue<Tweet> pQueue = new PriorityQueue<Tweet>((a, b) -> (int)(b.createdOn - a.createdOn));

    public Twitter() {

    }

    public void postTweet(int userId, int tweetId) {
        Tweet tweet = new Tweet(userId, tweetId, System.nanoTime());
        pQueue.add(tweet);
    }

    public List<Integer> getNewsFeed(int userId) {
        List<Integer> newsFeed = new ArrayList<Integer>();
        List<Integer> followedList = followMap.get(userId);
        List<Tweet> tempList = new ArrayList<Tweet>();

        while (pQueue.peek() != null) {
            Tweet element = pQueue.poll();
            if (newsFeed.size() == 10) {
                pQueue.addAll(tempList);
                return newsFeed;
            }
            if (element.userId == userId || (followedList != null && followedList.contains(element.userId))) {
                newsFeed.add(element.tweetId);
            }
            tempList.add(element);
        }

        pQueue.addAll(tempList);
        return newsFeed;
    }

    public void follow(int followerId, int followeeId) {
        if (followMap.get(followerId) == null) {
            List<Integer> list = new ArrayList<Integer>();
            list.add(followeeId);
            followMap.put(followerId, list);
        } else {
            followMap.get(followerId).add(followeeId);
        }
    }

    public void unfollow(int followerId, int followeeId) {
        if (followMap.get(followerId) != null) {
            followMap.get(followerId).removeIf(id -> id == followeeId);
        }
    }
}

class Tweet {
    int tweetId;
    int userId;
    long createdOn;

    Tweet(int userId, int tweetId, long createdOn) {
        this.tweetId = tweetId;
        this.userId = userId;
        this.createdOn = createdOn;
    }
}

代码在大多数测试用例中都能正常工作,除了一个测试用例。预期输出结果中最后一个新闻源存在错误,对我来说,推文ID 205没有被包括在内,但是按设计我期望它在结果中,不确定为什么会出现这种情况。

英文:

I was working on a leetcode question where we need to design the basic twitter functionality ,
such as follow and unfollow , post a tweet and newsfeed which will give the most recent 10 tweets for a user

postTweet(userId, tweetId): Compose a new tweet.
getNewsFeed(userId): 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.
follow(followerId, followeeId): Follower follows a followee.
unfollow(followerId, followeeId): Follower unfollows a followee.

import java.time.Instant;
import java.util.*;
class Twitter {
Map&lt;Integer, List&lt;Integer&gt;&gt; followMap = new HashMap&lt;Integer,List&lt;Integer&gt;&gt;();
Queue&lt;Tweet&gt; pQueue = new PriorityQueue&lt;Tweet&gt;((a, b)-&gt; (int)(b.createdOn-a.createdOn));
/** Initialize your data structure here. */
public Twitter() {
}
/** Compose a new tweet. */
public void postTweet(int userId, int tweetId) {
Tweet tweet = new Tweet(userId,tweetId, System.nanoTime());
pQueue.add(tweet);
}
/** Retrieve the 10 most recent tweet ids in the user&#39;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. */
public List&lt;Integer&gt; getNewsFeed(int userId) {
List&lt;Integer&gt; newsFeed = new ArrayList&lt;Integer&gt;();
List&lt;Integer&gt; follwedList = followMap.get(userId);
List&lt;Tweet&gt; la = new ArrayList&lt;Tweet&gt;();
while(pQueue.peek()!=null){
Tweet element = pQueue.poll();
if(newsFeed.size()==10){
pQueue.addAll(la);
return newsFeed;
}
if(element.userId == userId || (follwedList!=null &amp;&amp; follwedList.contains(element.userId))){
newsFeed.add(element.tweetId);
}
la.add(element);
}
pQueue.addAll(la);
return newsFeed;
}
/** Follower follows a followee. If the operation is invalid, it should be a no-op. */
public void follow(int followerId, int followeeId) {
if(followMap.get(followerId)==null){
List&lt;Integer&gt; a = new ArrayList&lt;Integer&gt;();
a.add(followeeId);
followMap.put(followerId,a);
}else{
followMap.get(followerId).add(followeeId);
}
}
/** Follower unfollows a followee. If the operation is invalid, it should be a no-op. */
public void unfollow(int followerId, int followeeId) {
if(followMap.get(followerId)!=null){
for(int i=0;i&lt;followMap.get(followerId).size();i++){
if(followMap.get(followerId).get(i)==followeeId){
followMap.get(followerId).remove(i);
break;
}
}
}
}
}
class Tweet {
int tweetId;
int userId;
long createdOn;
Tweet(int userId, int tweetId, long createdOn){
this.tweetId = tweetId;
this.userId = userId;
this.createdOn = createdOn;
}
}

the code work as expected for most of the test cases except one

["Twitter","postTweet","postTweet","postTweet","postTweet","postTweet","postTweet","postTweet","postTweet","postTweet","postTweet","postTweet","postTweet","postTweet","postTweet","postTweet","postTweet","postTweet","postTweet","postTweet","postTweet","postTweet","postTweet","getNewsFeed","follow","getNewsFeed","unfollow","getNewsFeed"]
[[],[1,5],[2,3],[1,101],[2,13],[2,10],[1,2],[1,94],[2,505],[1,333],[2,22],[1,11],[1,205],[2,203],[1,201],[2,213],[1,200],[2,202],[1,204],[2,208],[2,233],[1,222],[2,211],1,[1,2],1,[1,2],1]

My answer

[null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,[222,204,200,201,205,11,333,94,2,101],null,[211,222,233,208,204,202,200,213,201,203],null,[222,204,200,201,11,333,94,2,101,5]]

Expected answer

[null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,[222,204,200,201,205,11,333,94,2,101],null,[211,222,233,208,204,202,200,213,201,203],null,[222,204,200,201,205,11,333,94,2,101]]

in the last news feed there is an error , for me 205 in not coming , but by design I expect it to be in the result , not sure why it is happening

答案1

得分: 0

如果我正确理解你的策略:

            Tweet element = pQueue.poll();
            if(newsFeed.size()==10){
                pQueue.addAll(la);
                return newsFeed;
            }
            if(element.userId == userId || (follwedList!=null && follwedList.contains(element.userId))){
                newsFeed.add(element.tweetId);
            }
            la.add(element);

你将所有推文放在 pQueue 中,你的 la 列表跟踪你(暂时)移除的推文,一旦循环完成,你会将所有这些推文重新添加到 pQueue 中。

如果是这样的话,在你达到 newsFeed.size()==10 的情况下,la 并不包含所有已移除的推文,因为你提前进行了 return

要修复这个问题,你应该将 la.add(element) 放在 .poll() 之后。

英文:

If I understand your strategy correctly:

            Tweet element = pQueue.poll();
            if(newsFeed.size()==10){
                pQueue.addAll(la);
                return newsFeed;
            }
            if(element.userId == userId || (follwedList!=null &amp;&amp; follwedList.contains(element.userId))){
                newsFeed.add(element.tweetId);
            }
            la.add(element);

you have all tweets in pQueue and your la list keeps track of tweets that you have (temporarily) removed, and once your loop is complete, you add all those tweets in la back to the pQueue.

If so, then la does not contain all your removed tweets in the case that you reach newsFeed.size()==10. since you return early.

To fix this, you should probably have your la.add(element) right up where you .poll()

huangapple
  • 本文由 发表于 2020年9月6日 16:56:07
  • 转载请务必保留本文链接:https://go.coder-hub.com/63762388.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定