C实现 LeetCode->Reverse Linked List II (双指针大法)(单链表反转)

本文介绍了一种在单链表中高效地反转从位置m到n部分的方法,采用双指针技巧,仅使用常量内存,并在一次遍历内完成操作。通过实例演示了如何实现这一功能,特别强调了算法的时间复杂度为O(k),适用于LeetCode挑战。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


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.

 





//
//  ReverseLinkedListII.c
//  Algorithms
//
//  Created by TTc on 15/6/22.
//  Copyright (c) 2015年 TTc. All rights reserved.
//
/**
 *  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->NULL, m = 2 and n = 4,
 return 1->4->3->2->5->NULL.
 Note:
 Given m, n satisfy the following condition:
 1 ≤ m ≤ n ≤ length of list.
 只要用跟编号ReverseNodesInk-Group一模一样的Reverse()函数就可以了。
 当然这题要用递归做也可以。
 */
#include "ReverseLinkedListII.h"
#include <stdlib.h>
#include <string.h>
#include "List.h"


/********************************************************************/
// LeetCode 答案
/********************************************************************/
struct ListNode {
    int val;
    struct ListNode *next;
};

//双指针大法
/*Since only constant memory is allowed, time cost is O(k) */
static struct ListNode*
Reverse(struct ListNode *begin, struct ListNode *end){
    struct ListNode* prev = begin->next;
    struct ListNode* curr = prev->next;
    
    while(curr != end){
        prev->next = curr->next;
        curr->next = begin->next;
        begin->next = curr;
        curr = prev->next;
    }
    return prev;
}


struct ListNode*
reverseBetween(struct ListNode* head, int m, int n) {
    if(head == NULL) return head;
    
    struct ListNode *dummyHead = (struct ListNode *)malloc(sizeof(*dummyHead));
    dummyHead->next = head;
    
    struct ListNode *iter = head;
    struct ListNode *prev = dummyHead;
    struct ListNode *curr = head;
    
    int count = 1;
    while(iter->next != NULL){
        if(count < m) prev = prev->next;
        if(count < n) curr = curr->next;
        iter = iter->next;
        ++count;
    }
    
    Reverse(prev, curr->next);
    
    return dummyHead->next;
}

/********************************************************************/
/********************************************************************/
/********************************************************************/
// List.c 是范性类 单链表
/********************************************************************/
//反转单链表中  begin  到 end 节点

static ListElmt*
tt_Reverse(ListElmt *begin, ListElmt *end){
    ListElmt* prev = begin->next;
    ListElmt* curr = prev->next;
    
    while(curr != end){
        prev->next = curr->next;
        curr->next = begin->next;
        begin->next = curr;
        curr = prev->next;
    }
    return prev;
}


ListElmt*
tt_reverseBetween(ListElmt* head, int m, int n) {
    if(head == NULL) return head;
    
    ListElmt *dummyHead = (ListElmt *)malloc(sizeof(*dummyHead));
    dummyHead->next = head;
    
    ListElmt *iter = head;
    ListElmt *prev = dummyHead;
    ListElmt *curr = head;
    
    int count = 1;
    while(iter->next != NULL){
        if(count < m) prev = prev->next;
        if(count < n) curr = curr->next;
        iter = iter->next;
        ++count;
    }
    tt_Reverse(prev, curr->next);
    return dummyHead->next;
}


void
test_reverseBetween(){
    List l1;
    list_init(&l1, free);
    int *data ;
    int array[15] = {100,200,300,400,500,600,700,800,900,1000};
    for (int i = 0; i< 10; i++) {
        if ((data = (int *)malloc(sizeof(int))) == NULL)
            return ;
        *data = array[i];
        if (list_ins_next(&l1, NULL, data) != 0)  //逐个插入元素
            return;
    }
    print_list(&l1);
    ListElmt *result = tt_reverseBetween(list_head(&l1),0,10);
    printf("result->val===%d\n",*(int *)result->data);
    print_listNode(result);
}









评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值