BM2 链表内指定区间反转

总结:
收获1:不要忘记while循环内的自变量自增
收获2:这道题只考虑了n的边界条件,没有考虑m的边界条件(m=1),以后要考虑全面

// 逆置链表
struct ListNode* ReverseList(struct ListNode* head ) { 
    if (head == NULL) return head;
    struct ListNode* tmpHead = (struct ListNode*)malloc(sizeof(struct ListNode));
    tmpHead -> next = NULL;
    struct ListNode* pcur = head;
    head = head->next;
    while (head != NULL) {
        pcur->next = tmpHead->next;
        tmpHead->next = pcur;
        pcur = head;
        head = head->next;
    }
    pcur->next = tmpHead->next;
    tmpHead->next = pcur;
    return tmpHead->next;
}
 
// 求出链表长度
int listLength(struct ListNode* head) {
    int len = 0;
    while (head != NULL) {
        len++;
        head = head->next;
    }
    return len;
}
 
// 找到节点的前驱
struct ListNode* find_node_pre(struct ListNode* head, int m) {
    struct ListNode* p = head;
    int i = 1;
    while (i < m - 1) {
        p = p->next;
        i++;
    }
    return p;
}
 
// 找到节点的后继
struct ListNode* find_node_next(struct ListNode* head, int m, int n) {  
// 这里折磨我很久很久... m要分情况讨论,否则当 m==1 时node_n_next指向的是第n个元素的下一个元素,
// 就会导致下面的“从头到中”这一情况出错
    struct ListNode* q;// q指向第 m 个元素                               
    if(m == 1)                                                          
    {
        q = find_node_pre(head, m);
    } 
    else
    {
        q= find_node_pre(head, m)->next;
    }
    int i = m;
    while (i < n + 1 && q != NULL)// 要保证q不能为空
    {
        q = q->next;
        i++;
    }
    return q;
}
 
// 找到某一链表的最后节点
struct ListNode* lastNode(struct ListNode* head) 
{
    struct ListNode* plast = head;
    while (plast->next != NULL) {
        plast = plast->next;
    }
    return plast;
}
 
// 逆置[m,n]范围链表
struct ListNode* reverseBetween(struct ListNode* head, int m, int n ) {
    struct ListNode* tmp_ptr = (struct ListNode*)malloc(sizeof(struct ListNode)); // 临时节点
        struct ListNode* node_m_pre = find_node_pre(head, m); // m的前一个节点
        struct ListNode* node_n_next = find_node_next(head, m,n); // n的后一个节点
        struct ListNode* node_m = find_node_pre(head, m + 1); // 第m个节点
        struct ListNode* node_n = find_node_pre(head, n + 1); // 第n个节点
    if (m == 1) {
        if (n == 1) // 从点到点
            return head;
        else if (node_n_next != NULL) { // 从头到中
            node_n->next = NULL;
            head = ReverseList(head);
            lastNode(head)->next = node_n_next;
            return head;
        } else  // 从头到尾
            return ReverseList(head);
    } else { // m != 1
        if (m == n) // 从点到点
            return head;
        else if (node_n_next != NULL) { // 从中到中
            node_n->next = NULL; // 这两句话把[m,n]的链表断开
            tmp_ptr = ReverseList(node_m); // 翻转中间的链表
            // 接上前后的链表
            lastNode(tmp_ptr)->next = node_n_next;
            node_m_pre->next = tmp_ptr;
            return head;
        } else  // 从中到尾
            node_m_pre->next = ReverseList(
                                   node_m);// 前面接上后面翻转过后的链表
        return head;
    }
}

 上述代码,即为本人所思考出的本题答案

  • 10
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值