• 构造TopRecord结构问题解法


    问题描述

    请实现如下结构:
            TopRecord{
                    public TopRecord(int K) :         构造时事先指定好K的大小,构造后就固定不变了
                    public void add(String str) :         向该结构中加入一个字符串,可以重复加入
                    public List top() :         返回之前加入的所有字符串中,词频最大的K个
            }
    要求:
            add方法,复杂度O(log K);
            top方法,复杂度O(K)

    思路

            Node类,把字符串以及其出现的次数进行封装。

            在TopRecord类中定义了四个变量,分别为Node数组heap用于表示小根堆(固定大小)、heapSize表示小根堆此时里面装的数据数量、strNodeMap表示字符串与Node节点的对应关系,即词频表、nodeIndexMap表示小根堆中Node节点在堆中的位置,若节点不在小根堆中则对应关系的value值用-1表示。

            TopRecord方法对小根堆的大小进行固定。

            add方法流程:

    1.         任意添加一个字符串时,我们首先把它在小根堆对应表nodeIndexMap的值preIndex统一固定为-1。
    2.         我们查询词频表strNodeMap看该字符串之前是否有过,若之前没有进来过,初始化该字符串的Node,把Node的times值设置为1,放入词频表strNodeMap,设置该节点小根堆对应关系xMap中的对应关系设置为-1,这时的preIndex任然保持-1不变。若之前来过我们在词频表strNodeMap取出对应字符串的Node,查询出该node的词频并加一,在对应关系nodeIndexMap中查找出节点在小根堆中的位置赋值给preIndex。
    3.         此时我们查看preIndex的是否为-1既可以判断出该节点现在是否在小根堆上(若为-1表示节点不在小根堆上)。若preIndex不为-1即为节点在小根堆上,此时我们需要从preIndex到 heapSize的位置heapify调整小根堆。若preIndex为-1,分为两种情况:一种是小根堆未满,另一种是小根堆满了。对于小根堆未满情况,我们把该节点放在小根堆最后的位置,记录此时节点在小根堆中的对应关系,从该位置开始向上调整堆heapInsert。

             top方法:此时小根堆中的Node节点即为加入的所有字符串中,词频最大的K个。

            注意:我们在heapify方法和heapInsert方法中交换两个数字位置的时候,我们同时也需要交换heapInsert表中小根堆位置的对应表中的信息。

    代码  

    1. public static class Node {
    2. public String str;
    3. public int times;
    4. public Node(String s, int t) {
    5. str = s;
    6. times = t;
    7. }
    8. }
    9. public static class TopKRecord {
    10. private Node[] heap;
    11. private int heapSize;
    12. private HashMap strNodeMap;
    13. private HashMap nodeIndexMap;
    14. public TopKRecord(int K) {
    15. heap = new Node[K];
    16. heapSize = 0;
    17. strNodeMap = new HashMap<>();
    18. nodeIndexMap = new HashMap<>();
    19. }
    20. public void add(String str) {
    21. Node curNode = null;
    22. int preIndex = -1;//str之前在堆上的位置
    23. //查询词频表,看看有没有关于这个str的记录
    24. if (!strNodeMap.containsKey(str)) {
    25. curNode = new Node(str, 1);
    26. strNodeMap.put(str, curNode);
    27. nodeIndexMap.put(curNode, -1);
    28. } else {//str之前进来过
    29. curNode = strNodeMap.get(str);
    30. curNode.times++;
    31. preIndex = nodeIndexMap.get(curNode);
    32. }
    33. //词频表修改完毕
    34. if (preIndex == -1) {//不在堆上
    35. if (heapSize == heap.length) {//堆满了
    36. if (heap[0].times < curNode.times) {
    37. nodeIndexMap.put(heap[0], -1);
    38. nodeIndexMap.put(curNode, 0);
    39. heap[0] = curNode;
    40. heapify(0, heapSize);
    41. }
    42. } else {//堆没有满
    43. nodeIndexMap.put(curNode, heapSize);
    44. heap[heapSize] = curNode;
    45. heapInsert(heapSize++);
    46. }
    47. } else {//str已经在堆上
    48. heapify(preIndex, heapSize);
    49. }
    50. }
    51. public void printTopK() {
    52. System.out.println("TOP: ");
    53. for (int i = 0; i != heap.length; i++) {
    54. if (heap[i] == null) {
    55. break;
    56. }
    57. System.out.print("Str: " + heap[i].str);
    58. System.out.println(" Times: " + heap[i].times);
    59. }
    60. }
    61. private void heapInsert(int index) {
    62. while (index != 0) {
    63. int parent = (index - 1) / 2;
    64. if (heap[index].times < heap[parent].times) {
    65. swap(parent, index);
    66. index = parent;
    67. } else {
    68. break;
    69. }
    70. }
    71. }
    72. private void heapify(int index, int heapSize) {
    73. int l = index * 2 + 1;
    74. int r = index * 2 + 2;
    75. int smallest = index;
    76. while (l < heapSize) {
    77. if (heap[l].times < heap[index].times) {
    78. smallest = l;
    79. }
    80. if (r < heapSize && heap[r].times < heap[smallest].times) {
    81. smallest = r;
    82. }
    83. if (smallest != index) {
    84. swap(smallest, index);
    85. } else {
    86. break;
    87. }
    88. index = smallest;
    89. l = index * 2 + 1;
    90. r = index * 2 + 2;
    91. }
    92. }
    93. private void swap(int index1, int index2) {
    94. nodeIndexMap.put(heap[index1], index2);
    95. nodeIndexMap.put(heap[index2], index1);
    96. Node tmp = heap[index1];
    97. heap[index1] = heap[index2];
    98. heap[index2] = tmp;
    99. }
    100. }

  • 相关阅读:
    【算法新题】TJOI2017-异或和
    作为一个程序员,如何高效的管理时间?
    编程思维是一种什么思维?
    解决Netty那些事儿之Reactor在Netty中的实现(创建篇)-下
    RabbitMQ快速使用代码手册
    【SUMO学习】初级 SUMOlympics
    广东省2022下半年软考报名时间已定!
    Jmeter压测入门教程
    机器学习笔记之指数族分布——最大熵原理与softmax激活函数的关系
    三角定位是什么
  • 原文地址:https://blog.csdn.net/z1171127310/article/details/127727180