1. 程式人生 > >LeetCode算法系列:92&&206 Reverse Linked List

LeetCode算法系列:92&&206 Reverse Linked List

題目描述:

92

Reverse a linked list from position m to n. Do it in one-pass.

Note: 1 ≤ m ≤ n ≤ length of list.

Example:

Input: 1->2->3->4->5->NULL, m = 2, n = 4
Output: 1->4->3->2->5->NULL

206

Example:

Input: 1->2->3->4->5->NULL
Output: 5->4->3->2->1->NULL

Follow up:

A linked list can be reversed either iteratively or recursively. Could you implement both?

演算法實現:

這兩個問題很是類似,206可以說是92的一個子問題,比較基礎

/**
 * 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 *L = head;
        ListNode *p = NULL;
        ListNode *pp;
        while(L != NULL){
            pp = L -> next;
            L -> next = p;
            p = L;
            L = pp;           
        }
        return p;
    }
};

對於第92題,只需要找到要反轉部分的第一個節點,反轉部分前後的相鄰節點,兩種方法

  • 一種是直接找到反轉部分的後一節點,反轉時直接將反轉部分的頭節點連結到這一節點
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* reverseBetween(ListNode* head, int m, int n) {
        if(m >= n)return head;
        ListNode *suanz = new ListNode(0);
        suanz -> next = head;
        int i = 0;
        //記錄反轉連結串列的第一個節點
        ListNode *L;
        //記錄反轉連結串列之前的第一個節點
        ListNode *p = suanz;
        //記錄反轉連結串列之後的第一個節點
        ListNode *pe;
        while(i < m - 1 && p != NULL){
            p = p -> next;
            i ++;
        }
        L =  p -> next;
        i ++;
        pe = L;
        while(i < n + 1 && pe != NULL){
            pe = pe -> next;
            i ++;
        }
        i = m;
        ListNode *pp;
        // cout << pe -> val << endl;
        // cout << L -> val << endl;
        while(i <= n){
            pp = L -> next;
            L -> next = pe;
            pe = L;
            L = pp;
            i ++;
        }
        p -> next = pe;
        return suanz -> next;        
    }

};
  • 另一種是稍微進行了優化,不找到反轉部分的後一節點,反轉時先將反轉部分的頭節點指向反轉部分的前一節點,反轉過程完成後再修正這個地方,這樣操作少搜尋了依次反轉部分
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* reverseBetween(ListNode* head, int m, int n) {
        if(m >= n)return head;
        ListNode *suanz = new ListNode(0);
        suanz -> next = head;
        int i = 0;
        //記錄反轉連結串列的第一個節點
        ListNode *L,*Lp;
        //記錄反轉連結串列之前的第一個節點
        ListNode *p = suanz;
        //記錄反轉連結串列之後的第一個節點
        ListNode *pe;
        while(i < m - 1 && p != NULL){
            p = p -> next;
            i ++;
        }
        L =  p -> next;
        i ++;
        // pe = L;
        // while(i < n + 1 && pe != NULL){
        //     pe = pe -> next;
        //     i ++;
        // }
        pe = p;
        Lp = L;
        i = m;
        ListNode *pp;
        // cout << pe -> val << endl;
        // cout << L -> val << endl;
        while(i <= n){
            pp = L -> next;
            L -> next = pe;
            pe = L;
            L = pp;
            i ++;
        }
        p -> next = pe;
        Lp -> next = pp;
        return suanz -> next;        
    }
};