對於線性表的操做過程有有多問題能夠探究,在不少的題目裏有的甚至會對操做的時間進行規定,這就很是考究算法的效率。根據不一樣的狀況對排序方法或者是對鏈表或順序表的選擇,能夠節省其運行時間。而算法又是比較有難度的一部分,對初次認識一種算法的人仍需時間去理解,能夠說這就是人與計算機不可兼得的一方面。
對於鏈表的操做,時刻都要考慮指向非法區域的狀況,這也是我常常不自覺要忽略的一點。python
設計函數分別求兩個一元多項式的乘積與和。
輸入格式:程序員
輸入分2行,每行分別先給出多項式非零項的個數,再以指數遞降方式輸入一個多項式非零項係數和指數(絕對值均爲不超過1000的整數)。數字間以空格分隔。
輸出格式:算法
輸出分2行,分別以指數遞降方式輸出乘積多項式以及和多項式非零項的係數和指數。數字間以空格分隔,但結尾不能有多餘空格。零多項式應輸出0 0。
對於這道題目我嘗試了兩種解決方法:數組
這種方法對時間和空間的消耗都是魔鬼,可是對程序員倒是十分友好,這也是我一開始使用這種方法的緣由。
簡而言之,十分暴力。
設計思想:構造一個儘可能大的數據,而且使用static使得全部初值均爲0,這樣就能判斷每一項是否是存在。而後將加法和乘法的每一項結果都存進以指數爲下標的數組裏。要輸出的時候就遍歷所有數組,非0就輸出。很暴力呢函數
!--如下僞代碼都將採用python縮進表示語句塊的方法--<學習
定義存儲多項式的數組a[MAX],b[MAX] 以及用來存儲的數組plus[MAX],Mult[MAX] //對於全部數組都用靜態,這樣他們就都是0了,方便判斷是否爲空 //還有就是數組下標就表明有幾回方,其內容就是係數 //下面開始對結果計算的操做: //乘法: for i = 0 to MAX-1: if a[i]: for j = 0 to MAX-1: if b[i]: Mult[i + j] += a[i] * b[j] //係數相乘,指數相加 //加法 for i = 0 to MAX-1 if a[i] or b[j]: plus[i] += (a[i] + b[i]) //如上便完成了操做過程
//代碼這東西,不是電腦難受,就是我難受(小聲嘀咕)
設計思想:初始化一個新元素elem,而後一樣地將每次計算加法或者乘法的結果存入elem,再利用一個Insert函數將elem插入到結果鏈表中。動畫
//先丟出結構體 typedef struct LNode { int coe; int index; LNode * next; }*LinkList; //常規的建表輸出表就不貼啦 //我先設計了兩個初級函數,用於計算每一項的結果,並調用Insert函數插入結果鏈表中: void Multply(LinkList L1, LinkList L2, LinkList result) LinkList p = L1, q while p->next://遍歷 初始化q爲L2 while q->next://遍歷 爲elem分配空間,而後將p,q節點的計算結果存儲到elem if elem->coe == 0: elem->index = 0 p = p->next void Add(LinkList L1, LinkList L2, LinkList result) //Add函數也比較簡單,把每一個鏈表的節點丟給Insert函數就好啦 //這兩個函數的大體功能相似,只不過是一個節點中轉站 //接下來是Insert函數,其大體思想就是利用輸入數據的指數遞減的特色,嘗試查找比elem指數小的節點 void Insert(LinkList elem, LinkList &result) while p->next: if p->next->index == elem->index://說明找到 將elem的係數與當前p->next相加 delete elem return; //return 很重要 else if p->next->index < elem->index://找過頭了仍是沒有找到 將elem插入在當前p->next的前面 return; p = p->next //通過上述循環仍沒找到說明應該插在末尾 插在末尾
數組實現:
網站
鏈表實現:
設計
WA1:忘記考慮係數爲0時指數不爲0的狀況
Solution:在Insert以前加個if語句判斷就行了3d
WA2:我覺得題目的「0 0」狀況是有係數爲0的就用合併輸出。。
Solution:去和以前寫的數組法對比了一下差異,再回過頭來看看題目才發現
已知兩個遞增鏈表序列L1與L2,2個鏈表都是帶頭結點鏈表。設計函數實現L1,L2的合併,合併的鏈表仍然遞增有序,頭結點爲L1的頭結點。 合併後須要去除重複元素。 * 輸入格式: 輸入分兩行,先輸入數據項個數,再輸入數據項,數字用空格間隔。 * 輸出格式: 在一行中輸出合併後新的遞增鏈表,數字間用空格分開,結尾不能有多餘空格;
你須要實現的函數爲:
void MergeList(LinkList &L1,LinkList L2);//合併鏈表
這題不算難,可是手上有一個有趣的解法就拿出來分享一下,其大體原理如圖
設計思想:比較L1和L2頭元素的大小,將二者之中最小的元素拆下來使用尾插法插入結果鏈表,而且讓拆過的鏈表頭指向下一節點。
void MergeList(LinkList &L1, LinkList L2) 新建一個結果鏈表L3 head = L3 while L1 or L2: if L1->data == head->data: L1=L1->next else if L2同上: else: 使head->next指向L1, L2中的最小值節點 並使該節點指向它的下一個 head->next = NULL L1 = L3
WA1:寫這題時也不知怎麼了,感受腦子忽然不在線了,出現不少低級錯誤,好比定義告終果鏈表L3,可是都沒用過就給人家L1=L3,太智障了我。。
Solution:讓腦子冷靜一下。。。
WA2:發現有的重複數據仍是沒有過濾掉
Solution:設置斷點調試,最後發現是隻考慮了L1,L2有共同元素卻沒有考慮單個鏈表中重複的狀況。
本題要求實現一個函數,將給定單向鏈表逆置,即表頭置爲表尾,表尾置爲表頭。鏈表爲帶頭結點鏈表。請實現逆轉函數。
輸入說明:
第一個數輸入單鏈表結點個數n,後面輸入n個正整數。
輸出說明:
輸出逆轉後的單鏈表內容,數和數之間空格隔開,尾部不能有空格。若鏈表爲空,輸出 空鏈表!
設計思想:感受就像橋樑施工隊同樣,爲了防止後面的橋樑坍塌,必須把後面的吊住,這就是操做變量after的功能,利用before和p實現兩個節點之間的逆轉,原先是before下一個指向p,修改爲p下一個指向before。
void ReverseList(LinkList &L) p = L->next; 定義操做變量before = NULL,after while p: //移動after的位置 after = p->next //先改變p的指向 p->next 移動before和p L->next = before
這個感受實在是太抽象了,僞代碼不太好表達,因此用PPT作了個動畫,應該會比較好懂
元素解釋:紅色表明操做變量,黃色表明鏈表的每個節點,藍色表明指針指向
WA1:多是太累了,一直沒給L頭節點,而後輸出函數也是寫的沒頭節點,一直在納悶。
Solution:經歷太多失敗恍然大悟
給定一個鏈表,判斷鏈表中是否有環。 爲了表示給定鏈表中的環,咱們使用整數 pos 來表示鏈表尾鏈接到鏈表中的位置(索引從 0 開始)。 若是 pos 是 -1,則在該鏈表中沒有環。
多種思路:
(這裏就直接照搬題解了)
思路想象一下,兩名運動員以不一樣的速度在環形賽道上跑步會發生什麼?
經過使用具備 不一樣速度 的快、慢兩個指針遍歷鏈表,空間複雜度能夠被下降至 O(1)O(1)O(1)。慢指針每次移動一步,而快指針每次移動兩步。
若是列表中不存在環,最終快指針將會最早到達尾部,此時咱們能夠返回 false。
這種解法會破壞鏈表,大體思路就是每走一步就而後讓每一個節點本身指本身,這樣若是存在環勢必會遇到一個自攻自受的節點,這就是答案了
1.快慢指針法
2.無限循環法
感受常常逛一逛這些網站仍是挺有意思的,能看見各類不一樣的奇葩思路,也很是適合用來對新學習的語言進行練手,由於它支持不少種編譯器,牛逼