牛客NC97 字符串出现次数的TopK问题【中等 哈希+优先级队列 Java/Go】

题目

题目链接:

https://www.nowcoder.com/practice/fd711bdfa0e840b381d7e1b82183b3ee

核心

	哈希,优先级队列

Java代码

java 复制代码
import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * return topK string
     * @param strings string字符串一维数组 strings
     * @param k int整型 the k
     * @return string字符串二维数组
     */
    public String[][] topKstrings (String[] strings, int k) {
        //哈希 ,优先级队列
        Map<String, Integer> smap = new HashMap<>();
        for (String s : strings) {
            if (!smap.containsKey(s)) {
                smap.put(s, 0);
            }
            smap.put(s, smap.get(s) + 1);
        }

        PriorityQueue<Integer> pq1 = new PriorityQueue<>(new Comparator<Integer>() {
            @Override
            public int compare(Integer a, Integer b) {
                return b - a;
            }
        });
        Map<Integer, PriorityQueue<String>> pqm = new HashMap<>();

        Set<Integer> unique = new HashSet<>();

        for (String s : smap.keySet()) {
            int cnt = smap.get(s);

            if (!unique.contains(cnt)) {
                unique.add(cnt);
                pq1.add(cnt);
                pqm.put(cnt, new PriorityQueue<>());
            }

            pqm.get(cnt).add(s);
        }
        String[][] ans = new String[k][2];
        int prevcnt = pq1.poll();
        PriorityQueue<String> prevpq = pqm.get(prevcnt);
        int idx = 0;
        while (idx < k) {

            while (idx < k && prevpq.size() > 0) {
                String cur = prevpq.poll();
                ans[idx][0] = cur;
                ans[idx][1] = String.valueOf(prevcnt);
                idx++;

            }

            if (idx == k) break;

            prevcnt = pq1.poll();
            prevpq = pqm.get(prevcnt);
        }

        return ans;
    }
}

Go代码

go 复制代码
package main

import (
	"sort"
	"strconv"
	"strings"
)

/**
 * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
 *
 * return topK string
 * @param strings string字符串一维数组 strings
 * @param k int整型 the k
 * @return string字符串二维数组
 */
func topKstrings(strings []string, k int) [][]string {
		//哈希,优先级队列
	smap := map[string]int{}
	for _, s := range strings {
		_, ok := smap[s]
		if !ok {
			smap[s] = 0
		}

		smap[s] = smap[s] + 1
	}

	times := []int{}
	pqm := map[int]*PQAsc{}
	unique := map[int]bool{}
	for k, v := range smap {
		_, ok := unique[v]
		if !ok {
			times = append(times, v)
			pqm[v] = &PQAsc{Arr: make([]string, 10), Size: 0}
			unique[v] = true
		}

		pqm[v].add(k) //k是字符串
	}

	ans := make([][]string, k)
	sort.Ints(times)
	idx := 0

	for i := len(times) - 1; i >= 0; i-- {
		curcnt := times[i]
		pq := pqm[curcnt]

		for idx < k && pq.Size > 0 {

			ans[idx] = make([]string, 2)
			ans[idx][0] = pq.remove()
			ans[idx][1] = strconv.Itoa(curcnt)
			idx++
		}

	}

	return ans
}

// 上升堆  下标0也就是堆顶元素最小
type PQAsc struct {
	Arr  []string
	Size int
}

// 扩容代码
func (pq *PQAsc) ensurecap(cap int) {
	oldsize := len(pq.Arr)
	if oldsize >= cap {
		return
	}

	newsize := oldsize + oldsize>>1
	newarr := make([]string, newsize)
	for i := 0; i < oldsize; i++ {
		newarr[i] = pq.Arr[i]
	}
	pq.Arr = newarr

}

func (pq *PQAsc) add(s string) {
	pq.ensurecap(pq.Size + 1)
	pq.Arr[pq.Size] = s
	pq.shiftup(pq.Size)
	pq.Size++
}

// 上滤
func (pq *PQAsc) shiftup(idx int) {
	base := pq.Arr[idx]
	for idx > 0 {
		pid := (idx - 1) >> 1
		parent := pq.Arr[pid]

		/*
			如果字符串相等(s1 == s2),则返回0
			如果字符串1大于字符串2(s1> s2),则返回1。
			如果字符串1小于字符串2,则返回-1
		*/
		if strings.Compare(base, parent) >= 0 {
			break
		}

		pq.Arr[idx] = parent
		idx = pid
	}
	pq.Arr[idx] = base
}

func (pq *PQAsc) remove() string {
	ans := pq.Arr[0]
	pq.Arr[0] = pq.Arr[pq.Size-1]
	pq.Size--
	pq.shiftdown(0)
	return ans
}

// 下钻
func (pq *PQAsc) shiftdown(idx int) {
	half := pq.Size >> 1
	base := pq.Arr[idx]
	for idx < half {
		childidx := idx<<1 + 1
		right := childidx + 1
		child := pq.Arr[childidx]

		if right < pq.Size && strings.Compare(child, pq.Arr[right]) >= 0 {
			childidx = right
			child = pq.Arr[right]
		}

		if strings.Compare(base, child) <= 0 {
			break
		}

		pq.Arr[idx] = child
		idx = childidx
	}
	pq.Arr[idx] = base
}
相关推荐
程序猿小柒29 分钟前
leetcode hot100【LeetCode 4.寻找两个正序数组的中位数】java实现
java·算法·leetcode
雨中rain1 小时前
贪心算法(1)
算法·贪心算法
不爱学习的YY酱1 小时前
【操作系统不挂科】<CPU调度(13)>选择题(带答案与解析)
java·linux·前端·算法·操作系统
平头哥在等你1 小时前
求一个3*3矩阵对角线元素之和
c语言·算法·矩阵
飞滕人生TYF1 小时前
动态规划 详解
算法·动态规划
_OLi_1 小时前
力扣 LeetCode 106. 从中序与后序遍历序列构造二叉树(Day9:二叉树)
数据结构·算法·leetcode
ahadee2 小时前
蓝桥杯每日真题 - 第18天
c语言·vscode·算法·蓝桥杯
地平线开发者2 小时前
CPU& 内存加压工具 stress-ng 介绍
算法·自动驾驶
XY.散人2 小时前
初识算法 · 分治(2)
算法
DanielYQ2 小时前
LCR 001 两数相除
开发语言·python·算法