leetcode 題解

92. 反轉鏈表 II

方法一:

提交程式碼:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
// 由於leetcode提交默認的是沒有頭結點的,故需要內部創建一個頭結點方便使用 struct ListNode* reverseBetween(struct ListNode* head, int m, int n) { if(n < m) return; if(n == m) return head; struct ListNode h = {0, head}; //設置一個頭節點【普通結構體變數】,處理m=1的情況 struct ListNode* pre = &h; //指針變數賦值 struct ListNode *p = pre ->next,*q,*t; int i = 1; while(i < m) { pre = p; p = p->next; ++i; } t = p; //t 記錄翻轉部分的起點 if(m < n) { p = p->next; ++i; } while(i <= n) { q = p; p = p->next; ++i; q->next = pre->next; pre->next = q; // 每次將第一步找到的結點指向反轉後的頭結點 } t->next = p; //將反轉的起點next指向反轉後面的結點 return h.next; }

codeblocks中運行程式碼:

#include <stdio.h>
#include <stdlib.h>

typedef struct Node
{
    int data;
    struct Node* next;
} Node;
void create(Node *head)
{
    //創建鏈表 【尾插法】
    Node *temp,*p;
    int x;
    printf("請輸入鏈表元素:\n");
    scanf("%d",&x);
    p = head;   //p為尾結點
    while(x != 9999)
    {
        temp = (Node *)malloc(sizeof(Node));
        temp ->data = x;
        p ->next = temp;
        p = p ->next;
        scanf("%d",&x);
    }
    temp ->next = NULL;
}
void input(Node *head)
{
    Node *p = head ->next;  //p為工作指針
    while(p != NULL)
    {
        printf("%d\t",p ->data);
        p = p ->next;
    }
}
int reverseBetween(Node *head,int m,int n)
{
    if(n < m)
        return 0;
    if(n == m)
        return head;
    Node *pre,*p,*q,*t;
    int i = 1;
    p = head->next;
    pre = head;
    while(i < m)
    {
        pre = p;
        p = p->next;
        ++i;
    }
    t = p;  //t 記錄翻轉部分的起點
    if(m < n)
    {
         p = p->next;
         ++i;
    }
    while(i <= n)
    {
        q = p;
        p = p->next;
        ++i;
        q->next = pre->next;
        pre->next = q;   // 每次將第一步找到的結點指向反轉後的頭結點
    }
    t->next = p;  //將反轉的起點next指向反轉後面的結點
    return head;
}
int main()
{
    Node * head;
    head = (Node *)malloc(sizeof(Node));  //head為頭結點
    head ->data = NULL;
    head ->next = NULL;
    create(head);
    input(head);
    printf("\n逆置後:\n");
    head = reverseBetween(head,2,5);
    input(head);
}

方法二:

提交程式碼:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode* reverseBetween(struct ListNode* head, int m, int n) {
    if(m == n)
        return head; // 不用管的情況
    struct ListNode h = {0, head}; //設置一個頭節點,處理m=1的情況
    struct ListNode* p = &h;  //指針變數賦值
    struct ListNode* tail;
    for(int i = 1; i <= n; i++)
        if(i < m) // p指向第n-1個節點位置
            p = p->next;
        else if(i == m) // tail指向第第n個節點,這個節點反轉後處在反轉部分的最後一個
            tail = p->next;
        else { //每次將tail後面一個節點拿出來,放在item後面
            struct ListNode* item = tail->next;
            tail->next = tail->next->next;
            item->next = p->next;
            p->next = item;
        }
    return h.next;
}

codeblocks中運行程式碼:

#include <stdio.h>
#include <stdlib.h>

typedef struct Node
{
    int data;
    struct Node* next;
} Node;
void create(Node *head)
{
    //創建鏈表 【尾插法】
    Node *temp,*p;
    int x;
    printf("請輸入鏈表元素:\n");
    scanf("%d",&x);
    p = head;   //p為尾結點
    while(x != 9999)
    {
        temp = (Node *)malloc(sizeof(Node));
        temp ->data = x;
        p ->next = temp;
        p = p ->next;
        scanf("%d",&x);
    }
    temp ->next = NULL;
}
void input(Node *head)
{
    Node *p = head ->next;  //p為工作指針
    while(p != NULL)
    {
        printf("%d\t",p ->data);
        p = p ->next;
    }
}
int reverseBetween(Node *head,int m,int n)
{
    if(n < m)
        return 0;
    if(m == n)
        return head; // 不用管的情況
    struct Node* p = head,* tail;
    int i ;
    for(i = 1; i <= n; i++)
        if(i < m) // p指向第n-1個節點位置
            p = p->next;
        else if(i == m) // tail指向第第n個節點,這個節點反轉後處在反轉部分的最後一個
            tail = p->next;
        else   //每次將tail後面一個節點拿出來,放在item後面
        {
            struct Node* item = tail->next;
            tail->next = tail->next->next;
            item->next = p->next;
            p->next = item;
        }
    return head;
}
int main()
{
    Node * head;
    head = (Node *)malloc(sizeof(Node));  //head為頭結點
    head ->data = NULL;
    head ->next = NULL;
    create(head);
    input(head);
    printf("\n反轉後:\n");
    head = reverseBetween(head,2,4);
    input(head);
}

擴展:【逆置鏈表】

例子: 1 2 3 4 5 6 —— > 6 5 4 3 2 1

方法一:

將頭結點摘下,然後從一個結點開始,依次前插入到頭結點的後面【頭插法建立鏈表】,直到最後一個結點結束為止

#include <stdio.h>
#include <stdlib.h>

typedef struct Node
{
    int data;
    struct Node* next;
} Node;
void create(Node *head)
{
    //創建鏈表 【尾插法】
    Node *temp,*p;
    int x;
    printf("請輸入鏈表元素:\n");
    scanf("%d",&x);
    p = head;   //p為尾結點
    while(x != 9999)
    {
        temp = (Node *)malloc(sizeof(Node));
        temp ->data = x;
        p ->next = temp;
        p = p ->next;
        scanf("%d",&x);
    }
    temp ->next = NULL;
}
void input(Node *head)
{
    Node *p = head ->next;  //p為工作指針
    while(p != NULL)
    {
        printf("%d\t",p ->data);
        p = p ->next;
    }
}
void reverse(Node * head)
{
    Node *p ,*r;  //p為工作指針,r為p的後繼
    p = head ->next;
    head ->next = NULL;  //將頭結點的next設為NULL
    //依次將元素結點摘下
    while(p != NULL)
    {
        r = p ->next;  // 暫存p的後繼
        // 將p結點插入head之後
        p ->next = head ->next;
        head ->next = p;
        p = r;
    }
}
int main()
{
    Node * head;
    head = (Node *)malloc(sizeof(Node));  //head為頭結點
    head ->data = NULL;
    head ->next = NULL;
    create(head);
    input(head);
    printf("\n逆置後:\n");
    reverse(head);
    input(head);
}

方法二:

 設定三個指針:pre,p,r指向相鄰的結點

#include <stdio.h>
#include <stdlib.h>

typedef struct Node
{
    int data;
    struct Node* next;
} Node;
void create(Node *head)
{
    //創建鏈表 【尾插法】
    Node *temp,*p;
    int x;
    printf("請輸入鏈表元素:\n");
    scanf("%d",&x);
    p = head;   //p為尾結點
    while(x != 9999)
    {
        temp = (Node *)malloc(sizeof(Node));
        temp ->data = x;
        p ->next = temp;
        p = p ->next;
        scanf("%d",&x);
    }
    temp ->next = NULL;
}
void input(Node *head)
{
    Node *p = head ->next;  //p為工作指針
    while(p != NULL)
    {
        printf("%d\t",p ->data);
        p = p ->next;
    }
}
void reverse(Node * head)
{
    //將結點指針翻轉
    Node *p = head ->next ,*pre,*r = p ->next;
    p ->next = NULL;   // 處理第一個結點
    while(r != NULL)    // r為空,說明p為最後一個結點
        pre = p;
        p = r;
        r = r ->next;
        p ->next = pre;   // p指向前驅pre
    }
    head ->next =p;    // 處理最後一個結點
}
int main()
{
    Node * head;
    head = (Node *)malloc(sizeof(Node));  //head為頭結點
    head ->data = NULL;
    head ->next = NULL;
    create(head);
    input(head);
    printf("\n逆置後:\n");
    reverse(head);
    input(head);
}

  

  

Tags: