LeetCode算法練習——鏈表(一)

LeetCode206. 反轉鏈表

反轉一個單鏈表。

示例:

輸入: 1->2->3->4->5->NULL
輸出: 5->4->3->2->1->NULL

該題雖然爲鏈表的基礎操作,但是聽說面試很常考,邏輯也很容易出錯。我們需要兩個指針,一個作爲遊標,一個作爲反轉鏈表的頭節點,操作示意圖如下:

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        ListNode *pre = head, *cur = NULL;   
        while(pre){
            ListNode *tmp = pre->next;
            pre->next = cur;
            cur = pre;
            pre = tmp;
        }
        return cur;
    }
};

LeetCode2. 兩數相加

給出兩個非空的鏈表用來表示兩個非負的整數。其中,它們各自的位數是按照逆序的方式存儲的,並且它們的每個節點只能存儲 一位 數字。如果,我們將這兩個數相加起來,則會返回一個新的鏈表來表示它們的和。您可以假設除了數字 0 之外,這兩個數都不會以 0 開頭。

示例:

輸入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
輸出:7 -> 0 -> 8
原因:342 + 465 = 807

此題的思想和大數相加類似,兩個鏈表同時進行遍歷,相應數值累加,我們需要考慮一個進位carry。

class Solution {
public:
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        ListNode *l3 = new ListNode(0);
        ListNode *curr = l3;
        int carry = 0;
        while(l1 != NULL || l2 != NULL){
            int sum = 0;
            int x = 0, y = 0;
            //遍歷兩個鏈表
            if(l1){
                x = l1->val;
                l1 = l1->next;
            }
            if(l2){
                y = l2->val;
                l2 = l2->next;
            }
            sum = x + y + carry;                    //數位求和
            carry = sum/10;                         //進位計算
            curr->next = new ListNode(sum % 10);    //申請新節點並賦值
            curr = curr->next;                      //新節點遍歷
        }
        if(carry){                                  //如果最高位需要進位
            curr->next = new ListNode(1);
        }
        return l3->next;  
    }
};

LeetCode19. 刪除鏈表的倒數第N個節點

給定一個鏈表,刪除鏈表的倒數第 個節點,並且返回鏈表的頭結點。

示例:

給定一個鏈表: 1->2->3->4->5, 和 n = 2.

當刪除了倒數第二個節點後,鏈表變爲 1->2->3->5.

此題思路很簡單,我們需要兩個指針,0第一個指針在原鏈表上遍歷k次,隨後兩個指針同時向後遍歷,當第一個遍歷結束時,第二個指針也就到達了倒數第k個位置。當然,此題我們也可以將節點摘取存入容器內進入操作,代碼也在下面給出了。

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode *tmp = new ListNode(0);
        tmp->next = head;
        ListNode *p = tmp;
        ListNode *q = tmp;
        for(int i = 0; i < n; i++){
            p = p->next;
        }
        while(p->next){
            p = p->next;
            q = q->next;
        }
        q->next = q->next->next;
        return tmp->next;
        /*方法2
        vector<ListNode*> vec;
        while(head->next != nullptr)
        {
            vec.push_back(head);                //把鏈表中的所有節點放到vector中
            head = head->next;
        }
        vec.push_back(head);                    //別忘了最後一個節點
        vec.erase(vec.begin() + vec.size() - n);    //刪掉要求的那個節點
        if(vec.size() == 0){return nullptr;}
        for(int i = 0 ; i < vec.size()-1 ; i ++)
        {
            vec[i]->next = vec[i + 1];            //將容器內的點前後相連
        }
        vec[vec.size() - 1]->next = nullptr;      //最後一個節點確保next爲空
        return vec[0];                          //返回第一個節點即可
        */
    }
};

 

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