1. 程式人生 > 其它 >LeetCode:721.Accounts Merge賬戶合併(C語言)

LeetCode:721.Accounts Merge賬戶合併(C語言)

技術標籤:LeetCode

題目描述:
給定一個列表 accounts,每個元素 accounts[i] 是一個字串列表,其中第一個元素 accounts[i][0] 是 名稱 (name),其餘元素是 emails 表示該賬戶的郵箱地址。

現在,我們想合併這些賬戶。如果兩個賬戶都有一些共同的郵箱地址,則兩個賬戶必定屬於同一個人。請注意,即使兩個賬戶具有相同的名稱,它們也可能屬於不同的人,因為人們可能具有相同的名稱。一個人最初可以擁有任意數量的賬戶,但其所有賬戶都具有相同的名稱。

合併賬戶後,按以下格式返回賬戶:每個賬戶的第一個元素是名稱,其餘元素是按順序排列的郵箱地址。賬戶本身可以以任意順序返回。

示例 1:

輸入:
accounts = [[“John”, “[email protected]”, “[email protected]”], [“John”, “[email protected]”], [“John”, “[email protected]”, “[email protected]”], [“Mary”, “[email protected]”]]
輸出:
[[“John”, ‘[email protected]’, ‘[email protected]’, ‘[email protected]’], [“John”, “

[email protected]”], [“Mary”, “[email protected]”]]
解釋:
第一個和第三個 John 是同一個人,因為他們有共同的郵箱地址 “[email protected]”。
第二個 John 和 Mary 是不同的人,因為他們的郵箱地址沒有被其他帳戶使用。
可以以任何順序返回這些列表,例如答案 [[‘Mary’,‘[email protected]’],[‘John’,‘[email protected]’],
[‘John’,‘[email protected]’,‘[email protected]
’,‘[email protected]’]] 也是正確的。

提示:

accounts的長度將在[1,1000]的範圍內。
accounts[i]的長度將在[1,10]的範圍內。
accounts[i][j]的長度將在[1,30]的範圍內。

來源:力扣(LeetCode)
連結:https://leetcode-cn.com/problems/accounts-merge
著作權歸領釦網路所有。商業轉載請聯絡官方授權,非商業轉載請註明出處。
解答:

/**
 * Return an array of arrays of size *returnSize.
 * The sizes of the arrays are returned as *returnColumnSizes array.
 * Note: Both returned array and *columnSizes array must be malloced, assume caller calls free().
 */
#define MAXSTRLEN 35
struct HashMap{
    char key[MAXSTRLEN];
    char name[MAXSTRLEN];
    char parent[MAXSTRLEN];
    UT_hash_handle hh;
};
struct HashMap *g_hashHead = NULL;
char ***g_res = NULL;
int *g_col = NULL;
int g_resIndex = 0;
#define MAXNUM 10000

void InitMem(int accountsSize)
{
    g_hashHead = NULL;
    g_res = (char ***)malloc(sizeof(char **) * accountsSize);
    for(int i = 0; i < accountsSize; i++) {
        g_res[i] = calloc(MAXNUM, sizeof(char*));
    }
    g_col = calloc(accountsSize, sizeof(int));
    g_resIndex = 0;
    return;
}

void FreeMem()
{
    struct HashMap *s = NULL;
    struct HashMap *tmp = NULL;
    HASH_ITER(hh,g_hashHead,s,tmp) {
        HASH_DEL(g_hashHead,s);
        free(s);
    }
    return; 
}

struct HashMap *InsertHash(char *key, char *name, char *parent)
{
    struct HashMap *s = NULL;
    HASH_FIND_STR(g_hashHead,key,s);
    if(s == NULL) {
        s = malloc(sizeof(struct HashMap));
        strcpy(s->key, key);
        strcpy(s->name, name);
        strcpy(s->parent, parent);
        HASH_ADD_STR(g_hashHead,key,s);
    }
    return s;
}

struct HashMap *UpadatHash(char *key, char *name, char *parent)
{
    struct HashMap *s = NULL;
    HASH_FIND_STR(g_hashHead,key,s);
    if(s == NULL) {
        return NULL;
    }
    strcpy(s->name, name);
    strcpy(s->parent, parent);
    return s;
}

struct HashMap *Find(struct HashMap *x )
{
    struct HashMap *s = x;
    while(strcmp(s->key, s->parent) != 0) {
        char parent[MAXSTRLEN] = {0};
        strcpy(parent,s->parent);
        HASH_FIND_STR(g_hashHead,parent,s);
    }
    return s;
}

void Union(struct HashMap *a, struct HashMap *b) 
{
    struct HashMap *aParent = Find(a);
    struct HashMap *bParent = Find(b);
    //printf("FIND a %s parent  %s %s\r\n",a->key,aParent->key,aParent->parent);
    //printf("FIND b %s parent  %s %s\r\n",b->key,bParent->key,bParent->parent);
    if(strcmp(aParent->parent, bParent->parent) != 0) {
        (void)UpadatHash(bParent->key, aParent->name, aParent->parent);
        (void)UpadatHash(b->key, aParent->name, aParent->parent);
    }
    return;
}

void ProcessAccount(char *** accounts, int accountsSize, int* accountsColSize)
{
    struct HashMap *a = NULL;
    struct HashMap *b = NULL;
    for (int i = 0; i < accountsSize; i++) {
        a = NULL;
        b = NULL;
        char *name = accounts[i][0];
        char *key = accounts[i][0];
        char *parent = accounts[i][0];
        for(int j = 1; j < accountsColSize[i]; j++) {
            key = accounts[i][j];
            parent = accounts[i][j];
            if(j == 1) {
                a = InsertHash(key, name, parent);
                continue;
            }else{
                b = InsertHash(key, name, parent);
            }
            Union(a,b);
        }
    }
    return;
}

bool IsSameParent(char *aKey, char *bKey)
{
    struct HashMap *a = NULL;
    struct HashMap *b = NULL;
    HASH_FIND_STR(g_hashHead,aKey,a);
    HASH_FIND_STR(g_hashHead,bKey,b);
    struct HashMap *aParent = Find(a);
    struct HashMap *bParent = Find(b);
    if(aParent != bParent) {
        return false;
    }
    return true;
}

int SortCmp(const void *a, const void *b)
{
    char *aPtr = *(char**)a;
    char *bPtr = *(char**)b;
    return strcmp(aPtr,bPtr); 
}

int GetResIndex(char *key)
{
    struct HashMap *s = NULL;
    HASH_FIND_STR(g_hashHead,key,s);
    for(int i = 0; i < g_resIndex; i++) {
        if(g_col[i] > 1) {
            if(IsSameParent(s->parent, g_res[i][1])) {
                return i;
            }
        }
    }
    return -1;
}

void OutPutRes() 
{
    struct HashMap *s = NULL;
    struct HashMap *tmp = NULL;
    char parent[MAXSTRLEN] = {0};
    HASH_ITER(hh,g_hashHead,s,tmp) {
        int resIndex = GetResIndex(s->key);
        if(resIndex == -1) {
            g_res[g_resIndex][0] = calloc(MAXSTRLEN, sizeof(char));
            strcpy(g_res[g_resIndex][0],s->name);
            g_res[g_resIndex][1] = calloc(MAXSTRLEN, sizeof(char));
            strcpy(g_res[g_resIndex][1],s->key);
            g_col[g_resIndex] = 2;
            g_resIndex++;
        }else{
            int index = g_col[resIndex];
            g_res[resIndex][index] = calloc(MAXSTRLEN, sizeof(char));
            strcpy(g_res[resIndex][index],s->key);
            g_col[resIndex]++;
        }
    }
    return;
}

void PrintHash()
{
    struct HashMap *s = NULL;
    struct HashMap *tmp = NULL;
    printf("PrintHash:\r\n");
    HASH_ITER(hh,g_hashHead,s,tmp) {
        printf("hash: %s %s %s\r\n",s->name,s->key,s->parent);
    }
    return;
}

void PrintRes()
{
    for (int i = 0; i < g_resIndex; i++) {
        for(int j = 0; j < g_col[i]; j++) {
            printf("%s ",g_res[i][j]);
        }
        printf("\r\n");
    }
    return;
}

void SortRes()
{
    for(int i = 0; i < g_resIndex; i++) {
        qsort(&g_res[i][1], g_col[i] - 1, sizeof(char*), SortCmp);//去掉NAME後 開始排序
    }
    return;
}

char *** accountsMerge(char *** accounts, int accountsSize, int* accountsColSize, int* returnSize, int** returnColumnSizes){
    InitMem(accountsSize);
    ProcessAccount(accounts, accountsSize, accountsColSize);
    //PrintHash();
    OutPutRes();
    SortRes();
    //PrintRes();
    FreeMem();
    *returnSize = g_resIndex;
    *returnColumnSizes = g_col;
    return g_res;
}

執行結果:
在這裡插入圖片描述

Notes:
參考文件:https://leetcode-cn.com/problems/accounts-merge/solution/cyu-yan-bing-cha-ji-hashjie-fa-by-tan-shao-yu-dou-/