牛客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
}
相关推荐
是小胡嘛25 分钟前
数据结构之旅:红黑树如何驱动 Set 和 Map
数据结构·算法
m0_7482550229 分钟前
前端常用算法集合
前端·算法
呆呆的猫1 小时前
【LeetCode】227、基本计算器 II
算法·leetcode·职场和发展
Tisfy1 小时前
LeetCode 1705.吃苹果的最大数目:贪心(优先队列) - 清晰题解
算法·leetcode·优先队列·贪心·
余额不足121381 小时前
C语言基础十六:枚举、c语言中文件的读写操作
linux·c语言·算法
火星机器人life4 小时前
基于ceres优化的3d激光雷达开源算法
算法·3d
虽千万人 吾往矣4 小时前
golang LeetCode 热题 100(动态规划)-更新中
算法·leetcode·动态规划
arnold664 小时前
华为OD E卷(100分)34-转盘寿司
算法·华为od
ZZTC5 小时前
Floyd算法及其扩展应用
算法
lshzdq5 小时前
【机器人】机械臂轨迹和转矩控制对比
人工智能·算法·机器人