查找队列中最新的n个记录

20 篇文章 0 订阅

每天产生的记录入队列,查找最新的n个记录

问题描述:

/**
 * 表示一个用户行为,包含type,timestamp, info信息
 */
interface Action {
    public String getType();

    public long getTimestamp();

    public String getInfo();
}

/**
 * 表示一个用户的行为历史
 */
interface ActionHistory {
    public void addNewAction(Action action);

    public List<Action> getRecentActions(int n);

    public List<Action> getRecentActions(String type, int n);
}

给定两个接口,实现getRecentActions(int n)和getRecentActions(String type, int n)的两个方法,(不断产生的记录数据是按照时间戳Timestamp来排序,时间戳值越大表示数据越新。)分别查找:不区分类型和区分特定类型的查找最新的n条记录。

具体实现如下:

package cetcocean.alibaba;

import java.util.*;
import java.util.Map.Entry;

/**
 * @description:
 * @author: fangchangtan
 * @create: 2019-02-21 08:46
 */


public class SolutionTest {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        MyActionHistory myActionHistory = new MyActionHistory();
        //添加各种记录
        for (int i = 1; i < 50; i = i + 2) {
            MyAciton myAcitonTem = new MyAciton("myScan", i, String.valueOf(i));
            myActionHistory.addNewAction(myAcitonTem);
        }
        for (int i = 0; i < 50; i = i + 2) {
            MyAciton myAcitonTem = new MyAciton("myClick", i, String.valueOf(i));
            myActionHistory.addNewAction(myAcitonTem);
        }

        //...test 单个参数......
        List<Action> listSumActions = myActionHistory.getRecentActions(20);
        System.out.println("listSumActions.size(): " + listSumActions.size() + "   | 获得全部类别的前n项值:");
        for (int i = 0; i < listSumActions.size(); i++) {
            Action action = listSumActions.get(i);
            System.out.println("type:" + action.getType() + " ;Timestamp:" + action.getTimestamp() + ";");
        }

        //...test 两个参数......
        System.out.println("\n" + "---------------我是分割线--------------------------");
        List<Action> listTypeActions = myActionHistory.getRecentActions("myClick", 20);
        System.out.println("listTypeActions.size(): " + listTypeActions.size() + "   | 获得特定type类别的前n项值:");
        for (int i = 0; i < listTypeActions.size(); i++) {
            Action action = listTypeActions.get(i);
            System.out.println("type:" + action.getType() + " ;Timestamp:" + action.getTimestamp() + ";");
        }


    }


}

/**
 * 表示一个用户行为,包含type,timestamp, info信息
 */
interface Action {
    public String getType();

    public long getTimestamp();

    public String getInfo();
}

/**
 * 表示一个用户的行为历史
 */
interface ActionHistory {
    public void addNewAction(Action action);

    public List<Action> getRecentActions(int n);

    public List<Action> getRecentActions(String type, int n);
}

class MyAciton implements Action, Comparable<MyAciton> {
    private String type;
    private long timeStamp;
    private String info;

    public MyAciton(String type, long timeStamp, String info) {
        super();
        this.type = type;
        this.timeStamp = timeStamp;
        this.info = info;
    }

    public String getType() {
        return type;

    }

    public long getTimestamp() {
        return timeStamp;

    }

    public String getInfo() {
        return info;

    }

    @Override
    public int compareTo(MyAciton o) {//升序排序
        return this.getTimestamp() > o.getTimestamp() ? -1 : (this.getTimestamp() < o.getTimestamp() ? 1 : 0);
    }
}

class MyActionHistory implements ActionHistory {

    private static Map<String, List<Action>> mapAcitonRecord = new HashMap<>();

    @Override
    public void addNewAction(Action action) {
        // TODO Auto-generated method stub
        if (mapAcitonRecord.containsKey(action.getType())) {
            mapAcitonRecord.get(action.getType()).add(action);
        } else {
            ArrayList<Action> arrayList = new ArrayList<Action>();
            arrayList.add(action);
            mapAcitonRecord.put(action.getType(), arrayList);
        }
    }

    @Override
    public List<Action> getRecentActions(int n) {
        // TODO Auto-generated method stub
        return getSumTopN(n);
    }

    @Override
    public List<Action> getRecentActions(String type, int n) {
        return getTypeTopN(type, n);
    }


    public Map<String, List<Action>> getMapRecord() {
        // TODO Auto-generated method stub
        return mapAcitonRecord;
    }

    /**
     * 获得指定类型的最新n条记录
     *
     * @param type
     * @param n
     * @return
     */
    public List<Action> getTypeTopN(String type, int n) {
        ArrayList<Action> resultList = new ArrayList<>();
        if (mapAcitonRecord.containsKey(type)) {
            List<Action> list = mapAcitonRecord.get(type);
            int size = list.size();
            //防止非法参数传入
            if (n < 0 || n > size) {
                return resultList;
            }
            for (int i = size - 1; i >= size - n; i--) {
                resultList.add(list.get(i));
            }
            return resultList;
        }
        return resultList;
    }

    /**
     * 获取全部类型的最近topN记录
     *
     * @param n
     * @return
     */
    public List<Action> getSumTopN(int n) {
        //计数已经弹出第count个元素;保证增长的count==n
        int count = 0;
        Map<String, Integer> currIndexMap = new HashMap<>();
        ArrayList<Action> resultList = new ArrayList<>();

        //初始化保存各个类型的最有各个元素的下标,到currIndexMap
        for (Entry<String, List<Action>> entry : mapAcitonRecord.entrySet()) {
            String type = entry.getKey();
            List<Action> queueList = entry.getValue();
            int index = queueList.size() - 1;
            currIndexMap.put(type, index);
        }

        int typeSize = currIndexMap.size();//总的类型type数量
        PriorityQueue<Action> priorityQueue = new PriorityQueue<>();//其实际上是一个大顶锥的实现
        for (Entry<String, List<Action>> entry : mapAcitonRecord.entrySet()) {
            String type = entry.getKey();
            List<Action> queueList = entry.getValue();
            //将各个类型type的最后一个元素添加到priorityQueue,实际一共typeSize个
            priorityQueue.offer(queueList.get(currIndexMap.get(type)));
        }

        while (!priorityQueue.isEmpty()) {
            Action maxAction = priorityQueue.poll();//弹出最大的元素:最新时间戳
            resultList.add(maxAction);
            count++;
            if (count == n) {//计数增加到n时候,就停止循环
                break;
            }
            //更新到下一个下标:并将下一个目标的元素添加到大顶堆中
            String type = maxAction.getType();
            int nextIndex = currIndexMap.get(type) - 1;
            //单个队列中向前找的过程中,没有其他元素的值了:此时防止空指针出现,此时,该类型已经不存在了,直接将该type的指针记录清空
            if (nextIndex < 0) {
                currIndexMap.remove(type);
            }else {
                currIndexMap.put(type, nextIndex);
                priorityQueue.offer(mapAcitonRecord.get(type).get(nextIndex));
            }
            //最终所有type的元素都弹出,此时currIndexMap为空,表示没有元素可以加入优先级队列了.此时直接弹出所有的元素。
            if (currIndexMap.size() == 0) {
                while (!priorityQueue.isEmpty()) {
                    Action maxActionTem = priorityQueue.poll();//弹出最大的元素:最新时间戳
                    resultList.add(maxActionTem);
                    count++;
                }
                return resultList;
            }
        }
        return resultList;
    }


}

思考:1.时间复杂度+空间复杂度
时间复杂度:其中n表示topN中的前n大,k表示type类型数量
O(nklogk)
2.堆排序使用PriorityQueue是java原始提供的内部采用堆排序的方式实现返回最大值(大顶锥)。实现不停的插入元素,并返回最大值【注意重写其中的方法】。
3.该问题是一个【业务设计】+【算法结构】的问题。

好的,让我来回答你的问题。关于使用C语言队列求解m*n迷宫问题,通常采用广度优先搜索算法,其具体步骤如下: 1.定义一个结构体表示迷宫的节点,包括节点的行、列、步数和从哪个节点到达该节点。 2.定义一个队列,用于存储待搜索的节点。 3.将起点加入队列,并将其步数设为0. 4.每次取出队头的节点,遍历其上下左右四个方向的节点,若该节点未被访问过且不是障碍物,则将其加入队列,并更新步数和父节点信息。 5.重复步骤4,直到队列为空。此时,所有可到达终点的路径已经被遍历过了。 6.输出从起点到终点的所有路径,以及路径的数量。 以下是C语言代码示例: ``` #include <stdio.h> #include <stdlib.h> #define MAXSIZE 100 struct node { int x,y; //节点所在的行和列 int step; //起点到该节点的步数 int pre; //从哪个节点到达该节点 }que[MAXSIZE]; int n,m,endx,endy; //迷宫大小、终点坐标 int maze[MAXSIZE][MAXSIZE]; //迷宫地图 int dx[4]={0,0,1,-1}; //用于计算四个方向相邻节点的行列坐标增量 int dy[4]={1,-1,0,0}; int vis[MAXSIZE][MAXSIZE]; //记录节点是否被访问过 int head=0,tail=0; //队头和队尾 void bfs() { int i; //将起点加入队列 que[tail].x=0; que[tail].y=0; que[tail].step=0; que[tail].pre=-1; tail++; vis[0][0]=1; while(head<tail) //队列不为空 { struct node p=que[head]; //取队头节点并出队 head++; if(p.x==endx && p.y==endy) //已到达终点 { int cnt=0; //记录可到达终点的路径数量 int path[MAXSIZE]={0}; //记录所有路径 //从终点一直查找父节点,直到到达起点 while(p.pre!=-1) { path[cnt++]=p.pre; p=que[path[cnt-1]]; } //反向输出路径 printf("Path %d: (%d,%d)",cnt,endx,endy); for(i=cnt-1;i>=0;i--) { p=que[path[i]]; printf(" -> (%d,%d)",p.x,p.y); } printf("\n"); } //遍历四个方向 for(i=0;i<4;i++) { int nx=p.x+dx[i]; int ny=p.y+dy[i]; if(nx>=0 && nx<n && ny>=0 && ny<m && !maze[nx][ny] && !vis[nx][ny]) //判断是否越界、是否是障碍物,是否已被访问过 { vis[nx][ny]=1; que[tail].x=nx; que[tail].y=ny; que[tail].step=p.step+1; que[tail].pre=head-1; tail++; //新节点入队 } } } } int main() { int i,j; printf("Input the size of the maze:\n"); scanf("%d %d",&n,&m); printf("Input the maze:\n"); for(i=0;i<n;i++) for(j=0;j<m;j++) scanf("%d",&maze[i][j]); printf("Input the coordinate of the end point:\n"); scanf("%d %d",&endx,&endy); bfs(); return 0; } ``` 以上就是使用C语言队列求解m*n迷宫问题的代码,可以输出解的个数及每个解。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值