1. 程式人生 > 實用技巧 >連結串列問題(演算法題)

連結串列問題(演算法題)

1、從已排序的連結串列中刪除重複的單元。如:

輸入:1->1->2,輸出:1->2

如:

輸入:1->1->2->2->3,輸出 1->2->3

思路:

雙指標;

快指標先往後移動,如果快指標的值不等於慢指標的值,就釋放掉中間的指標空間,並且將慢指標next指向快指標,把快指標賦值給快指標。

Node* deleteDuplicationNodeFromSortedList(Node* &pHead)
{
    if (pHead == NULL || pHead->next == NULL)
    {
        
return pHead; } Node* node_slow = pHead; Node* node_fast = pHead; while (node_fast != NULL) { if (node_fast->value != node_slow->value) { freeNodeBetweenTwoPointer(node_slow, node_fast); node_slow->next = node_fast; node_slow
= node_fast; } node_fast = node_fast->next; } if (node_slow->next != node_slow) { node_slow->next = node_fast; } return pHead; }

2、給定有序連結串列,刪除出現三次以上的元素。如:

輸入:1->1->2->3->3->3

返回:1->1->2

思路:雙指標

如果快指標的值不等於慢指標的值,那麼快慢指標就都往前走一步;如果遇到相同的數,快指標就繼續往前走,同時計數,超過三次以後就接著走直到碰到新數字以後修改慢指標的next

//這個還是有點複雜的,我想了挺久的
//主要難點在於如果沒有頭結點的連結串列進來第一個結點值是大於3的怎麼處理
//在慢指標的值不等於快指標的值的時候
Node* deleteDuplicationNodeThreeTimes(Node* &pHead)
{
    if (pHead == NULL || pHead->next == NULL)
    {
        return pHead;
    }

    Node* node_slow = pHead;
    Node* node_before = node_slow;
    Node* node_fast = pHead->next;


    while (node_fast != NULL)
    {
        int delete_cnt = 1;
        int delete_num = node_fast->value;

        while (node_fast->next != NULL && delete_num == node_fast->next->value)
        {
            delete_cnt++;
            node_fast = node_fast->next;
        }

        if (delete_cnt >= 3)
        {
            node_slow->next = node_fast->next;
        }
        else
        {
            node_slow = node_fast;
        }

        node_fast = node_fast->next;

    }

    return pHead;

}
Node* deleteDuplicationNodeThreeTimes(Node* &pHead)
{
    if (pHead == NULL || pHead->next == NULL)
    {
        return pHead;
    }

    Node* node_slow = pHead;
    Node* node_before = node_slow;
    Node* node_fast = pHead->next;


    while (node_fast != NULL)
    {
        int cnt = 0;
        while (node_fast != NULL && node_slow->next->value == node_fast->value)
        {
            cnt++;
            node_fast = node_fast->next;
        }

        if (cnt >= 3)
        {
            node_slow->next = node_fast;
        }
        else
        {
            while (node_slow->next != node_fast)
            {
                node_slow = node_slow->next;
            }
        }
    }

    return pHead;

}

3、給定無序連結串列,刪除出現三次以上的元素。

思路:hash演算法

兩次遍歷,第一次遍歷統計元素出現的次數,第二次遍歷檢視對應的value值出現次數是否大於3,是就刪除,否則就繼續走。

//預設傳進來的連結串列是帶有頭結點的
Node* deleteNodeThreeTimesFromUnordered(Node* &pHead)
{
    if (pHead == NULL || pHead->next == NULL )
    {
        return pHead;
    }

    unordered_map<int, int> hash_value;
    Node* node_tmp = pHead->next;

    while(node_tmp != NULL)
    {
        hash_value[ node_tmp->value ]++;
        node_tmp = node_tmp->next;
    }

    node_tmp = pHead;
    while (node_tmp->next != NULL)
    {
        if (hash_value[node_tmp->next->value] >= 3)
        {
            Node* node_free = node_tmp->next;
            node_tmp->next = node_free->next;
            free(node_free);
        }
        else
        {
            node_tmp = node_tmp->next;
        }
    }
    
    return pHead;
}

4、無序列表,要求出現次數不能超過本身的value值。

思路:hash

兩次遍歷。第一次遍歷統計元素次數,第二次遍歷查看出現次數是否超過value值,超過就刪除,並且把對應的hash的value值減1.

Node* deleteNodeOverValueTimesFromUnordered(Node* &pHead)
{
    if (pHead == NULL || pHead->next == NULL)
    {
        return pHead;
    }

    unordered_map<int, int> hash_value;
    Node* node_tmp = pHead->next;

    while (node_tmp != NULL)
    {
        hash_value[ node_tmp->value ]++;
        node_tmp = node_tmp->next;
    }

    node_tmp = pHead;
    while (node_tmp->next != NULL)
    {
        if (node_tmp->next->value < hash_value[ node_tmp->next->value ] )
        {
            hash_value[ node_tmp->next->value ]--;
            Node* node_free = node_tmp->next;
            node_tmp->next = node_free->next;
            free(node_free);
        }
        else
        {
            node_tmp = node_tmp->next;
        }
    }

    return pHead;
}