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);
}

  

  

版权声明:本文为pam-sh原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/pam-sh/p/12757978.html