[LeetCode-92] Reverse Linked List II(反转指定区间链表)

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

For example:
Given 1->2->3->4->5->NULLm = 2 and n = 4,

return 1->4->3->2->5->NULL.

Note:
Given mn satisfy the following condition:
1 ≤ m ≤ n ≤ length of list.

【分析】反转链表,但不是从头到尾的反转,给定了一个[m,n]范围,反转指定区间的链表。1 ≤ m ≤ n ≤ length of list.不满足条件的话,返回原链表

struct ListNode* reverseList(struct ListNode* head) 
{
    if((head == NULL) || (head->next==NULL))  //链表为空,或只有一个结点(无需反转),直接返回
        return head;

    struct ListNode *pre = NULL;//前一个
    struct ListNode *cur = NULL;//当前
    struct ListNode *ne = NULL;//后一个

    pre = head;         //将前面几个节点的地址依次保存在新定义的结构体指针
    cur = head ->next;

    while(cur) {
        ne = cur->next;  //如果当前节点不为空,则将其指针域赋给ne指针
        cur->next = pre; //直接将两个指针的指向反转
        pre = cur;       //将当前节点赋给pre,将三个指针在链表中的位子都往后移一位
        cur = ne;     
    }
    head->next = NULL;//将原来的第一个节点的指针域赋为空,作为尾节点
    head = pre;      //将原来的尾节点变成新链表的第一个节点
    return head;
}
struct ListNode* reverseBetween(struct ListNode* head, int m, int n) 
{
	/*1.Exception handling*/
    if(!head)
		return NULL;
	if(m <=0 || n<=0 || m>=n)
		return head;
	
	struct ListNode* headTemp = head;
	int LinkNodeLength = 0;
	struct ListNode* mStartLinkNode = head;
	struct ListNode* nEndLinkNode = NULL;
	struct ListNode* mStartPrivLinkNode = NULL;
	struct ListNode* nEndNextLinkNode = NULL;
	struct ListNode* reverseListNode = NULL;

	int i = 0;
	
	while(headTemp) {
		LinkNodeLength ++;
		headTemp = headTemp->next;
	}
	if(m>=LinkNodeLength||n>LinkNodeLength) 
		return head;
	/*2.Find the Start of LinkNode,and save the privLinkNode of mStartLinkNode*/
	for(i = 1;i<m;i++) {
		mStartPrivLinkNode = mStartLinkNode;/*Save the privLinkNode of mStartLinkNode*/
		mStartLinkNode = mStartLinkNode->next;
	}
	nEndLinkNode = mStartLinkNode;
	//printf("[%d] value:%d\n",__LINE__,mStartPrivLinkNode->val);/*OK*/
	//printf("[%d] value:%d\n",__LINE__,nEndLinkNode->val);/*OK*/
	for(i = m;i<n;i++) {
		nEndLinkNode = nEndLinkNode->next;
	}
	nEndNextLinkNode = nEndLinkNode->next;/*Save the nEndNextLinkNode of nEndLinkNode*/
	nEndLinkNode->next = NULL;/*For the reverseList*/
	//printf("[%d] value:%d\n",__LINE__,nEndLinkNode->val);
	reverseListNode = reverseList(mStartLinkNode);
	//printf("[%d] value:%d\n",__LINE__,reverseListNode->val);
	mStartLinkNode->next = nEndNextLinkNode;/*第n节点后面一个节点*/
	if(mStartPrivLinkNode) {
		mStartPrivLinkNode->next = reverseListNode;
	}
	else {
		head = reverseListNode;
	}

	return head;
	
}

全部代码如下:

// LeetCode92-Reverse Linked List II.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
/**
 * Definition for singly-linked list.
 **/
 struct ListNode {
      int val;
      struct ListNode *next;
 };

struct ListNode* CreatLink(int aData[],int len)
 {
     if(!aData)
         return NULL;
     struct ListNode *head = NULL;
     struct ListNode *p = NULL;
     struct ListNode *Link= NULL;
     /*第一个节点*/
     head = (struct ListNode *)malloc(sizeof(struct ListNode));
     head->val = aData[0];
     head->next = NULL;
    // aData ++;
     Link = head; /*保存头结点*/
     int i = 1;

     while(i < len) {
         p = (struct ListNode *)malloc(sizeof(struct ListNode));
         p->val = aData[i];
         head->next = p;
         head = p;
         i ++;
     }

     head->next = NULL;
     return Link;
 }

 void printLink(struct ListNode *head)
 {
     while(head) {
         printf("%d",head->val);
         head = head->next;
     }
     printf("\n");
 }

struct ListNode* reverseList(struct ListNode* head) 
{
    if((head == NULL) || (head->next==NULL))  //链表为空,或只有一个结点(无需反转),直接返回
        return head;

    struct ListNode *pre = NULL;//前一个
    struct ListNode *cur = NULL;//当前
    struct ListNode *ne = NULL;//后一个

    pre = head;         //将前面几个节点的地址依次保存在新定义的结构体指针
    cur = head ->next;

    while(cur) {
        ne = cur->next;  //如果当前节点不为空,则将其指针域赋给ne指针
        cur->next = pre; //直接将两个指针的指向反转
        pre = cur;       //将当前节点赋给pre,将三个指针在链表中的位子都往后移一位
        cur = ne;     
    }
    head->next = NULL;//将原来的第一个节点的指针域赋为空,作为尾节点
    head = pre;      //将原来的尾节点变成新链表的第一个节点
    return head;
}
struct ListNode* reverseBetween(struct ListNode* head, int m, int n) 
{
	/*1.Exception handling*/
    if(!head)
		return NULL;
	if(m <=0 || n<=0 || m>=n)
		return head;
	
	struct ListNode* headTemp = head;
	int LinkNodeLength = 0;
	struct ListNode* mStartLinkNode = head;
	struct ListNode* nEndLinkNode = NULL;
	struct ListNode* mStartPrivLinkNode = NULL;
	struct ListNode* nEndNextLinkNode = NULL;
	struct ListNode* reverseListNode = NULL;

	int i = 0;
	
	while(headTemp) {
		LinkNodeLength ++;
		headTemp = headTemp->next;
	}
	if(m>=LinkNodeLength||n>LinkNodeLength) 
		return head;
	/*2.Find the Start of LinkNode,and save the privLinkNode of mStartLinkNode*/
	for(i = 1;i<m;i++) {
		mStartPrivLinkNode = mStartLinkNode;/*Save the privLinkNode of mStartLinkNode*/
		mStartLinkNode = mStartLinkNode->next;
	}
	nEndLinkNode = mStartLinkNode;
	//printf("[%d] value:%d\n",__LINE__,mStartPrivLinkNode->val);/*OK*/
	//printf("[%d] value:%d\n",__LINE__,nEndLinkNode->val);/*OK*/
	for(i = m;i<n;i++) {
		nEndLinkNode = nEndLinkNode->next;
	}
	nEndNextLinkNode = nEndLinkNode->next;/*Save the nEndNextLinkNode of nEndLinkNode*/
	nEndLinkNode->next = NULL;/*For the reverseList*/
	//printf("[%d] value:%d\n",__LINE__,nEndLinkNode->val);
	reverseListNode = reverseList(mStartLinkNode);
	//printf("[%d] value:%d\n",__LINE__,reverseListNode->val);
	mStartLinkNode->next = nEndNextLinkNode;/*第n节点后面一个节点*/
	if(mStartPrivLinkNode) {
		mStartPrivLinkNode->next = reverseListNode;
	}
	else {
		head = reverseListNode;
	}

	return head;
	
}


int _tmain(int argc, _TCHAR* argv[])
{
	int a[] = {1,2,3,4,5,6,7,8,9,10};
    struct ListNode *head1 = NULL;
	struct ListNode *head2 = NULL;
    head1 = CreatLink(a,sizeof(a)/sizeof(int));
	printLink(head1);
	head2 = reverseBetween(head1,2,6);
	printLink(head2);
	getchar();
	return 0;
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

狂奔的乌龟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值