题解 | NO.3#链表中的节点每k个一组翻转#1.29

链表中的节点每k个一组翻转

https://www.nowcoder.com/practice/b49c3dc907814e9bbfa8437c251b028e

/**
 * struct ListNode {
 *  int val;
 *  struct ListNode *next;
 * };
 */
/**
 * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
 *
 *
 * @param head ListNode类
 * @param k int整型
 * @return ListNode类
 */
struct ListNode* reverseKGroup(struct ListNode* head, int k ) {
    if (k == 1 || head == NULL) {  //间隔为1,顺序不改变,直接返回;空链也直接返回
        return head;
    }
    int i = 1;  //用于计数
    struct ListNode* left = head;  //当前待排区间的第一个结点
    struct ListNode* right = head;  //当前待排区间的最后一个结点
    struct ListNode* cur = head;  //当前待插入结点
    struct ListNode* pre = NULL;  //上一个被插入结点
    struct ListNode* nex = head;  //下一个带插入结点
    struct ListNode* pre_tail = NULL;  //上一段区间的尾结点
    struct ListNode* first = NULL;  //整个链表重排之后的第一个结点

    for (i = 1; i < k && right != NULL; i ++) {  //划分出第一个待排区间
        right = right->next;
    }
    if (right == NULL) {  //第一个待排区间结点个数小于k,直接返回原链表
        return head;
    } else {  //第一个待排区间结点个数不小于k
        first = right;  //标记重排后链表第一个结点
        pre = right->next;  //便于找下一个区间的位置
        for (i = 1; i <= k; i ++) {  //将待排区间重排,采用头插法
            nex = cur->next;
            cur->next = pre;
            pre = cur;
            cur = nex;
        }
        pre_tail = left;  //标记第一个区间的尾结点
        left = left->next;
        right = left;
    }

    while (right != NULL) {  //当链表未重排完成时,循环
        for (i = 1; i < k && right != NULL; i ++) {  //找到待排区间
            right = right->next;
        }
        if (right != NULL) {  //当重排未完成
            pre = right->next;
            for (i = 1; i <= k; i ++) {  //头插法重排区间
                nex = cur->next;
                cur->next = pre;
                pre = cur;
                cur = nex;
            }
            pre_tail->next = right;  //将该区间连接到前面排好的链表之后
            pre_tail = left;  //标记该区间的尾结点
            left = left->next;  //找到下一个区间
            right = left;
        } else {
            pre_tail->next = left;  //该区间节点个数小于k,无需重排
        }
    }
    return first;  //返回重排链表的第一个结点
}
/*
1.没有将第一个区间单独处理,导致程序段出错,因为pre_tail->next使用错误,此时pre_tail==NULL,没有next。单独处理第一段还有一个用处,就是标记好first。
2.nex的处理,最开始是直接让nex=head->next,然后先头插法插入结点后,再nex=nex->next,也是跟第一个问题一样,会碰到nex=NULL,nex->next不存在的情况。
3.没有在当前区间重排之前,标记好后边的链表,这样会导致找不到后边的链表,在重排之前,将pre设置为right->next即可。

全部评论

相关推荐

点赞 评论 收藏
分享
04-17 23:48
西北大学 Java
陈好好wy:加油加油 字节和心脏谁先跳动
字节跳动开奖383人在聊
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务