L2-002 鏈表去重-團體程序設計天梯賽GPLT

題目來源:團體程序設計天梯賽-練習集
題目地址:L2-002 鏈表去重

problem

題目大意

將鏈表數據域的值相同(包含絕對值相同)的節點去掉,然後將去掉的節點又重新組成一條鏈表,最後輸出去重後的鏈表和被去掉的節點組成的鏈表。樣例表示如下:
1

題目分析

這道題的題目難度相對較低,只要你熟悉鏈表的遍歷和刪除操作,就可以順利完成這道題。雖然話是那麼說,但是用對了數據結構可以讓解題事半功倍。

  • lblb 數組用於存儲輸入的鏈表,我們可以用數組下標表示當前節點地址,就可以避免遍歷時尋址的麻煩
  • rere 數組用於存儲被去除節點組成的鏈表,這時我們可以直接順序存儲被去除的節點,而且只需要存儲節點的地址和數據域,這樣我們就可以利用順序知道每個下個節點的地址了。
  • 事實上,我們可以發現 lblb 相當於鏈表,而 rere 相當於順序表。它們的存儲示意圖如下:
    2

瞭解到上面這些,寫代碼已經順利了(默認你會鏈表的遍歷和刪除),最後再說一下寫題目踩到的坑:

  • 地址直接用 intint 類型存儲,沒必要用 stringstring,否則無法用上上述存儲結構(別跟我說用 mapmap ,我第一發就是這樣超時的)。
  • 格式控制符 “%05d” 表示如果輸出的字符少於5位時,在左邊補 00 (默認是補空格)。
  • 刪除操作需要用到前驅節點 prepre 的指針 ,prepre 在每次遇到不需要刪除的節點時就要更新,如果單純的直接用上一個節點,就可能用到被去除節點的地址。

代碼如下

#include <bits/stdc++.h>

using namespace std;
const int maxn = 1e5 + 10;
int n, cnt;
int one, s, pre;
/**
  * lb用於存儲原始鏈表
  * re用於存儲原始鏈表中的重複節點
  */
pair<int, int> lb[maxn];
pair<int, int> re[maxn];
set<int> vis;

int main()
{
    cin >> one >> n;
    for (int i = 1; i <= n; i++) {
        int address, num, next;
        cin >> address >> num >> next;
        lb[address] = make_pair(num, next);
    }
    cnt = 0;
    //遍歷鏈表,s表示當前節點的地址
    for (s = one; s != -1; s = lb[s].second) {
        int num = lb[s].first;
        if (!vis.count(abs(num))) {
            vis.insert(abs(num));
            //pre記錄下一個節點的前驅節點地址
            pre = s;
        } else {
            //鏈表刪除重複節點操作
            lb[pre].second = lb[s].second;
            //將刪除的節點存到另一條鏈表
            re[cnt].first = num;
            re[cnt].second = s;
            cnt++;
        }
    }

    for (s = one; s != -1; s = lb[s].second) {
        printf("%05d %d ", s, lb[s].first);
        if (lb[s].second != -1) printf("%05d\n", lb[s].second);
        else printf("-1\n");
    }
    for (int i = 0; i < cnt; i++) {
        printf("%05d %d ", re[i].second ,re[i].first);
        if (i != cnt - 1) printf("%05d\n", re[i + 1].second);
        else printf("-1\n");
    }
    return 0;
}

如果本文對你有所幫助,別忘了點贊哦~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章