程序員面試金典Chapter2 Linked List

第一題 輸出鏈表中的倒數第n個結點

給出的結構體為:


struct ListNode {

  int val;

  struct ListNode *next;

  ListNode(int x) :

  val(x), next(NULL) {

    }
};

我覺得首先應該要把整個鏈表的長度先求出來,然后在不判斷不遍歷整個鏈表的情況下只比對數字。下面是示例代碼:


class Solution {
public:
    ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {
        ListNode* temp = pListHead;
        int count=0;
        while(temp){
            count++;
            temp=temp->next;
        }
        for(int i=0;i<count;){
            if(i == count-k){
                return pListHead;
                break;
            }
            pListHead=pListHead->next;
            i++;
        }
        return NULL;
    }
};
第二題 刪除單向鏈表中的一個節點

我覺得刪除節點分兩步,一個是刪除單向鏈表中上一個只想該節點的鏈接和該節點指向下一個節點的鏈接,而變成第n-1個節點->next指向原先的n+1個節點。第二步就是當刪除了鏈接并不代表當前刪除的節點不占用內存空間,所以就要free這個空間。下面是通過的代碼示例:

class Remove {
public:
    bool removeNode(ListNode* pNode) {
        // write code here
        if(pNode->next == NULL)
            return false;
        ListNode* temp=pNode->next;
        pNode->next=temp->next;
        free(temp);
        return true;
    }
};
第三題 分割鏈表

題目描述的是要將小于給定x值的節點與大于x值的節點分割成兩部分,而本身鏈表的順序不能夠改變。最后需要返回小于x值的鏈表+大于x值的鏈表的頭節點。
想法很單純,既然要分割鏈表就自然需要定義兩個新的鏈表,第一步遍歷整個給定的鏈表將每個節點的值與給定的x值作對比,當小于x的時候就把新定義的p1鏈表的下一個節點指向此時的temp節點,而當大于x值得時候自然就將此時的temp節點賦給p2的下一個節點。
在過程中需要保存兩個新定義鏈表的表頭,也就是要判斷一下p1和p2的頭結點以便最后返回頭節點。下面為最終的代碼示例:

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};*/
class Partition {
public:
    ListNode* partition(ListNode* pHead, int x) {
        // write code here
        ListNode* p1 = NULL;
        ListNode* p2 = NULL;
        ListNode* temp = NULL;
        ListNode* p1Head = NULL;
        ListNode* p2Head = NULL;
        while(pHead){
            temp = pHead->next;
            if(pHead->val<x){
                if(p1 == NULL){
                    p1=pHead;
                    p1Head=pHead;
                }
                   
                else{
                  p1->next=pHead;
                  p1=p1->next;  
                }
            }
            else{
                if(p2 == NULL){
                   p2=pHead;
                    p2Head=pHead;
                }
                    
                else{
                    p2->next=pHead;
                    p2=p2->next; 
                }   
            }
            pHead=temp;
        }
        if(p2)
            p2->next=NULL;
        if(p1 == NULL)
            p1Head=p2Head;
        else
            p1->next=p2Head;
        return p1Head;
    }
};
第四題 鏈表A+B

題目描述為相加兩個給出的鏈表A與B,比如說:{1,2,3} + {3,2,1}需要返回一個結果鏈表為{4,4,4}。
在中間的加法運算中主要分為兩步,第一步計算每每兩個數字相加的結果,第二部提取出相應結果的進位和需要保留的個位數結果。下面為這一部分實現的代碼示例:

val1 = a?a->val:0;
val2 = b?b->val:0;
int val = val1 + val2+carry;
carry = val/10;

定義兩個新的ListNode結構的新鏈表,一個用來做最后返回的鏈表頭,一個作為鏈表的存儲。因為不知道兩個給定的鏈表長度,所以判斷的時候兩個鏈表都判斷是否為NULL再進入循環來遍歷兩個鏈表。當遍歷時判斷一下最終返回鏈表的頭節點,下面為完整的代碼示例:


/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};*/
class Plus {
public:
    ListNode* plusAB(ListNode* a, ListNode* b) {
        // write code here
        ListNode* pNode = NULL;
        ListNode* pHead = NULL;
        int carry=0;
        if(a == NULL && b == NULL)
            return NULL;
        while(a || b || carry>0){
            int val1,val2;
            val1 = a?a->val:0;
            val2 = b?b->val:0;
            int val = val1 + val2+carry;
            carry = val/10;
            
            ListNode* temp = new ListNode(val%10);
            if(pNode == NULL){
                pNode = temp;
                pHead = pNode;
            }
            else{
                pNode->next = temp;
                pNode=pNode->next;
            }
            a=a?a->next:NULL;
            b=b?b->next:NULL;
        }
        pNode->next = NULL;
        return pHead;
    }
};
第五題 回文鏈表

題目描述是這樣的,需要判斷一個給定的鏈表是否為回文鏈表,若給定鏈表如{1,2,3,2,1}則返回true,反之返回false。想法應該說并不難,但是我在鏈表的地址和賦值之間來回徘徊了很久才大概明白代碼測試一直不能通過是因為什么,下面先來看這個代碼

class Palindrome {
public:
    bool isPalindrome(ListNode* pHead) {
        // write code here·
        ListNode* reverseNode = NULL;
        ListNode* originalNode = pHead;
        ListNode* temp = NULL;
        ListNode* next = NULL;
        if(pHead == NULL)
            return false;
        while(pHead){
            next = pHead->next;
            temp = reverseNode;//temp=current
            reverseNode = pHead;//prev=current
            reverseNode->next = temp;//next=current
            pHead = next;
        }
        while(originalNode && reverseNode){
            if(originalNode->val != reverseNode->val){
                return false;
                break;
            }
            originalNode = originalNode->next;
            reverseNode = reverseNode->next;
        }
        return true;
    }
};

首先定義了兩個鏈表節點分別指向第一個給定節點和NULL,然后遍歷給定的鏈表將鏈表反轉。在遍歷的過程中,將reverse這個想象中是反轉后的鏈表先傳給一個temp以做保留,將reverse指向遍歷當前的節點,而reverse->next指向先前的地址也就是temp,然而此時我想也就破壞了給定鏈表指向next的這個節點鏈接了。
先貼一個正常反轉鏈表并返回反轉之后鏈表表頭的leetcode上通過的代碼:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        ListNode* temp,*current,*next;
        ListNode* reverse = NULL;
        current = head;
        //prev = NULL;
        while(current){
            next = current->next;
            temp = reverse;
            reverse = current;
            reverse->next = temp;
            current = next;
        }
        return reverse;
    }
};

同樣將這段代碼整齊的貼進這道題再去遍歷做比較,依然會不能通過測試,始終返回true,以我的專業出身和智商還沒有真正深究出原因,不過我猜想是因為永遠指向同一個地址那么比較的時候肯定會不如人意,當在反轉時有必要將反轉之后的鏈表reverse和在遍歷當前給定鏈表的時候new一個新的ListNode而不是在同一條地址鏈上進行多次的重復操作以至于最后比對的original鏈表丟失。這也是為什么當只是單純做反轉鏈表的時候遍歷第一步就要保存好當前節點next指向的地址。
所以重新定義并new一個鏈表reverse為NULL,然后遍歷整個給定的鏈表,將當前節點值給該次循環中的reverse節點,將該被改動的reverse節點的next指向上一循環中的reverse節點,以此類推,直到把NULL推到最后一個位置。這個方法我很熟悉,跟做硬件編譯時傳輸10101010....類的數據相差不大,都是按照一定的順序你推我我推你到窮盡。

這里很想插一句

一直以來人們給所謂程序員配的圖滿是10101010.....,看黑客帝國就知道了,我想說沒錯,計算機是接受二進制,可是在我自學Nodejs開發和這些滿滿的上層軟件面向對象碰到過10101010現象的機會遠遠不如我作為公司的一名新晉嵌入式開發來的平常。

程序員分很多種,我希望我哪種都不是,我不是一名程序員或者軟件、硬件工程師,我只是一名普通人,懂得少學得慢。

好吧,插了一句嘴,下面來貼上糾結了我一下午的最終通過代碼示例:

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};*/
class Palindrome {
public:
    bool isPalindrome(ListNode* pHead) {
        // write code here
        
        ListNode* temp = NULL;
        ListNode* current = pHead;
        ListNode* reverse = new ListNode(NULL);
        if(pHead == NULL)
            return false;
        while(current){
            //temp = reverse;
            //reverse->next = temp;
            //reverse = current->next;
            temp=reverse;
            ListNode* nextnode = new ListNode(current->val);//reverse = current->next;
            reverse = nextnode;
            reverse->next = temp;
            current = current->next;
        }
         
        while(pHead){
            if(pHead->val!=reverse->val)
                {
                return false;
                break;
            }
                
            pHead=pHead->next;
            reverse=reverse->next;
        }
        return true;
    }
};

原文地址、戳我

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,565評論 6 539
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,115評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,577評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,514評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,234評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,621評論 1 326
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,641評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,822評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,380評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,128評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,319評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,879評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,548評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,970評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,229評論 1 291
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,048評論 3 397
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,285評論 2 376

推薦閱讀更多精彩內容