#反轉連結串列_C++版 #反轉連結串列_Java版 @FDDLC

凡我出品,皆屬精品發表於2020-10-12

問題描述:輸入一個連結串列,反轉連結串列後,輸出新連結串列的表頭。

 

方法一(C++版):使用vector並反轉

#include <bits/stdc++.h>
using namespace std;

struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
            val(x), next(NULL) {
    }
};

class Solution {
public:
    ListNode* ReverseList(ListNode* pHead) {
        if(!pHead) return NULL;

        vector<ListNode*> v;

        for(ListNode* pCurrent = pHead; pCurrent; pCurrent = pCurrent->next) {
            v.push_back(pCurrent);
        }

        //反轉 vector<ListNode*> v
        reverse(v.begin(), v.end());

        //構造一個新的連結串列
        int i_end = v.size()-1;
        for(int i = 0; i < i_end; i++) {
            v[i]->next = v[i+1];
        }
        v[i_end]->next = NULL;  //最後一個結點的指標域為空

        return v[0];
    }
};

//輸出連結串列
void printList(ListNode* pHead) {
    for(ListNode* pCurrent = pHead; pCurrent; pCurrent = pCurrent->next) {
        cout<<pCurrent->val<<" ";
    }
    cout<<endl;
}

int main() {
    ListNode node1 = ListNode(1);
    ListNode node2 = ListNode(2);
    ListNode node3 = ListNode(3);
    node1.next = &node2;
    node2.next = &node3;
    node3.next = NULL;

    //反轉前
    printList(&node1);

    //進行反轉
    Solution solution;
    ListNode* pHead = solution.ReverseList(&node1);

    //反轉後
    printList(pHead);

    return 0;
}

 

方法二(C++版):原來是結點i的指標域存著結點i+1的地址,現在只要讓結點i的指標域存結點i-1的地址即可。

#include <bits/stdc++.h>
using namespace std;

struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
            val(x), next(NULL) {
    }
};

class Solution {
public:
    ListNode* ReverseList(ListNode* pHead) {
        //注意:不要輕易使用pHead->next,因為pHead如果為空,那麼pHead->next就會報錯!
        ListNode *pPre = NULL;
        ListNode *pCurrent = pHead;

        while(pCurrent) {
            ListNode *pNext = pCurrent->next; //備份結點i的指點域(即結點i+1的地址),因為在下一步會被重寫

            //結點i的指標域存它前1個結點(即結點i-1)的地址
            pCurrent->next = pPre;

            //在上一步中結點i-1已經完成了它的使命,現在可以把結點i的地址賦給它了
            pPre = pCurrent;

            //在前兩步中結點i已經完成了它的使命,現在可以把備份的結點i+1的地址賦給它了
            //有請下一位:結點i+1
            pCurrent = pNext;
        }

        //迴圈結束後pCurrent為NULL,pPre為最後一個結點
        return pPre;
    }
};

//輸出連結串列
void printList(ListNode* pHead) {
    for(ListNode* pCurrent = pHead; pCurrent; pCurrent = pCurrent->next) {
        cout<<pCurrent->val<<" ";
    }
    cout<<endl;
}

int main() {
    ListNode node0 = ListNode(0);
    ListNode node1 = ListNode(1);
    ListNode node2 = ListNode(2);
    node0.next = &node1;
    node1.next = &node2;
    node2.next = NULL;

    //反轉前
    printList(&node0);

    //進行反轉
    Solution solution;
    ListNode* pHead = solution.ReverseList(&node0);

    //反轉後
    printList(pHead);

    return 0;
}

附上1個錯誤版本(其實先來個 if(pHead == null) return null; 就OK了):

 

方法三(Java版本):

public class Solution {
    public class ListNode {
        int val;
        ListNode next = null;

        ListNode(int val) {
            this.val = val;
        }
    }

    public ListNode ReverseList(ListNode head) {
        ListNode pre = null;
        ListNode current = head;
        ListNode next;

        while(current != null) {
            next = current.next;
            current.next = pre;
            pre = current;
            current = next;
        }

        return pre;
    }

    public void printList(ListNode node) {
        while(node != null) {
            System.out.print(node.val + " ");
            node = node.next;
        }
        System.out.println();
    }

    public static void main(String args[]) {
        Solution solution = new Solution();
        ListNode node0 = solution.new ListNode(0);
        ListNode node1 = solution.new ListNode(1);
        ListNode node2 = solution.new ListNode(2);
        node0.next = node1;
        node1.next = node2;
        node2.next = null;

        //反轉前
        solution.printList(node0);

        ListNode head = solution.ReverseList(node0);

        //反轉後
        solution.printList(head);
    }
}

 

相關文章