leadcode的Hot100系列--347. 前 K 個高頻元素--hash表+直接選擇排序

来源:https://www.cnblogs.com/payapa/archive/2019/07/12/11173705.html
-Advertisement-
Play Games

這個看著應該是使用堆排序,但我圖了一個簡單,所以就簡單hash表加選擇排序來做了。 使用結構體: 思路: hash表用來存儲每個值對應的頻率,每讀到一個數字,對應的頻率就加1。 然後從表中再把這些數據讀取出來。 先創建兩個長度為k的數組,一個用來記錄頻率,一個用來記錄對應的數值。 讀取數據的時候,使 ...


這個看著應該是使用堆排序,但我圖了一個簡單,所以就簡單hash表加選擇排序來做了。
使用結構體:

typedef struct node
{
    struct node *pNext;
    int value;  // 數值
    int frequency;  // 頻率
}NODE_S;

思路:
hash表用來存儲每個值對應的頻率,每讀到一個數字,對應的頻率就加1。
然後從表中再把這些數據讀取出來。
先創建兩個長度為k的數組,一個用來記錄頻率,一個用來記錄對應的數值。
讀取數據的時候,使用頻率做排序,在排序的時候,也要對應的交換數值的數組。



/**
 * Note: The returned array must be malloced, assume caller calls free().
 */

#define HASH_LEN 10

typedef struct node
{
    struct node *pNext;
    int value;
    int frequency;
}NODE_S;

NODE_S *get_node(NODE_S **pstHead, int num) // 獲取num對應的節點
{
    int n;
    NODE_S *pstTemp;
    if (num<0)
        n = -num;
    else
        n = num;
    pstTemp = pstHead[n%HASH_LEN];
    
    while(NULL != pstTemp)
    {
        if (num == pstTemp->value)
            return pstTemp;
        else
            pstTemp = pstTemp->pNext;
    }
    return pstTemp;
}

void add_node(NODE_S **pstHashHead, int num)   // 添加一個num的節點
{
    NODE_S *pstTemp = NULL;
    NODE_S *pstNode = NULL;
    int i, n;
    
    if (num<0)     // 這裡是防止給的num是負數
        n = -num;
    else
        n = num;
    
    pstTemp = get_node(pstHashHead, num);
    if (NULL == pstTemp)
    {
        pstTemp = (NODE_S *)calloc(1, sizeof(NODE_S));
        if (NULL == pstTemp) return;
        pstTemp->value = num;
        pstTemp->frequency = 1;
        pstNode = pstHashHead[n%HASH_LEN];
        if (NULL == pstNode)
            pstHashHead[n%HASH_LEN] = pstTemp;   // 說明是第一個節點
        else
        {
            while (NULL != pstNode->pNext) // 往後面繼續掛鏈表
            {
                pstNode = pstNode->pNext;
            }
            pstNode->pNext = pstTemp;
        }
    }
    else
    {
        (pstTemp->frequency) ++; // 已經有該節點,則直接頻率加1
    }
    return;
}

void swap(int *frequency, int *value, int i, int k)  // 交換頻率的時候,也要交換對應的數值
{
    int temp = frequency[i];
    frequency[i] = frequency[k];
    frequency[k] = temp;
    temp = value[i];
    value[i] = value[k];
    value[k] = temp;
    return;
}

void selectSort(int *frequency, int *value, int len) // 選擇排序
{
    for(int i=0;i<len-1;i++)
    {
        int min = frequency[len-1-i];
        int local = len-1-i;
        for(int j=0;j<len-1-i;j++)
        {
            if(min > frequency[j])
            {
                min = frequency[j];
                local = j;
            }
        }

        if(local != (len-1-i))
            swap(frequency, value, local, len-1-i);
    }
}

int* topKFrequent(int* nums, int numsSize, int k, int* returnSize){
    NODE_S *pstHashHeadValue[HASH_LEN] = {0};
    NODE_S *pstTemp = NULL;
    int *pTmp, i;
    int *piFrequency = NULL, *piValue = NULL;
    
    for (i=0; i<numsSize; i++)  // 把所有元素都插入到hash表中
    {
        add_node(pstHashHeadValue, nums[i]);
    }
    
    // 這裡生成兩個數組,一個頻率數組,一個數值數組,頻率數組用來排序, 數值數組用來返回
    piFrequency = (int *)calloc(k, sizeof(int));   
    if (NULL == piFrequency) return NULL;
    piValue = (int *)calloc(k, sizeof(int));
    if (NULL == piValue) return NULL;
    
    int count = 0;
    for (i=0; i<HASH_LEN; i++)
    {
        if (NULL != pstHashHeadValue[i])
        {
            NODE_S *pstTemp = pstHashHeadValue[i];
            while (NULL != pstTemp)
            {
                if (count<k)
                {
                    piFrequency[count] = pstTemp->frequency;
                    piValue[count] = pstTemp->value;
                    count ++;
                    if (count == k)
                        selectSort(piFrequency, piValue, k);  // 把數組填滿之後,先做一次排序
                }
                else
                {
                    if (pstTemp->frequency > piFrequency[k-1])   // 只有當該頻率大於當前存儲最小頻率的時候,才需要進行重新排序
                    {
                        piFrequency[k-1] = pstTemp->frequency;
                        piValue[k-1] = pstTemp->value;
                        selectSort(piFrequency, piValue, k);
                    }
                }
                pstTemp = pstTemp->pNext;
            }
        }
    }

    *returnSize = k;
    return piValue;
    
}


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • python零基礎系統學習路線圖,Python語言無所不包,能做非常多的事情,適合各類企業的開發工作,學好Python,前途寬廣! python零基礎系統學習路線圖,Python語言無所不包,能做非常多的事情,適合各類企業的開發工作,學好Python,前途寬廣! python零基礎系統學習路線圖,P ...
  • 看過這篇文章,大廠面試你「雙親委派模型」,硬氣的說一句,你怕啥? 讀該文章姿勢 1. 打開手頭的 IDE,按照文章內容及思路進行代碼跟蹤與思考 2. 手頭沒有 IDE,先收藏,回頭看 (萬一哪次面試問了呢) 3. 需要查看和拷貝代碼,點擊文章末尾出「閱讀原文」 文章內容相對較長,所以添加了目錄,如果 ...
  • 第二種方法:對進行奇數倍n分頻時鐘,首先進行n/2分頻(帶小數,即等於(n-1)/2+0.5),然後再進行二分頻得到。得到占空比為50%的奇數倍分頻。下麵講講進行小數分頻的設計方法。 小數分頻:首先講講如何進行n+0.5分頻,這種分頻需要對輸入時鐘進行操作。基本的設計思想:對於進行n+0.5分頻,首 ...
  • 題目 "P1349 廣義斐波那契數列" 解析 把普通的矩陣乘法求斐波那契數列改一改,隨便一推就出來了 $$\begin{bmatrix}f_2\\f_1 \end{bmatrix}\begin{bmatrix} p&q\\ 1&0\\ \end{bmatrix}^{n 2}=\begin{bmatr ...
  • 當前的運行環境為,PHP7.2.2以 FastCGI 模式運行,預設埠為:9000,Nginx1.15.6 打開nginx配置文件 具體位置根據安裝情況可能會有所差異 在 server{}代碼段里新增以下代碼就可以支持 php 的訪問了 ...
  • 推送的方式: 簡訊推送(第三方) 郵件推送 微信推送 公眾號:認證的公眾號(個人的認證公眾號每天只能發一篇文章),粉絲可以跟公眾號聊天, 未認證公眾號 服務號:企業認證(營業執照),沙箱環境測試 主動給用戶發消息(推送),用戶要接收到推送消息前提是需要關註對應的服務號才行 企業號 微信小程式 公眾號 ...
  • 1、線程的使用步驟 2、第一種定義線程類的方法:繼承java.lang.Thread類 MyThread 文件: public class MyThread extends Thread { private int count=0; @Override public void run() { Sys ...
  • 回車鍵:開始游戲,空格鍵:暫停 / 繼續,方向鍵 或 WSAD 鍵:控制移動方向 下載地址 ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...