链表翻转。给出一个链表和一个数K,按照分组逆置。

链表翻转。给出一个链表和一个数K,比如链表1->2->3->4->5->6->NULL,K=2,翻转后 2->1->4->3->6->5->NULL,若K=3,翻转后3->2->1->6->5->4->NULL,若K=4,翻转后4->3->2->1->5->6->NULL,用程序实现ListNode* RotateList(ListNode* list, size_t k)

递归实现

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *reverseKGroup(ListNode *head, int k) {
        // 为空或一个结点或 K 不符合 规范直接返回原head
        if( NULL == head || NULL == head->next || k < 2)
            return head;

        // 以k为步数,找到逆置前下一组的头指针
        ListNode* next_group_head = head;
        for(int i = 0; i < k; ++i){
            if(next_group_head)   
                next_group_head = next_group_head->next;
            else // 剩余结点数小于K 不够分一组时,下一组的头指针就是head
                return head;
        }

        // 递归去处理剩余组,直到不够 K 个结点,即求出下一组逆置后的头指针
        ListNode* new_next_group_head = reverseKGroup(next_group_head, k);
        ListNode* prev = NULL ,* cur = head;
        // 开始逆置处理当前组,从 head --- next_group_head下一组逆置前的第一个结点
        while(cur != next_group_head){
            ListNode* next = cur->next; // 保存下一个结点
            if(prev == NULL)      // 为空则将当前组的一个结点指向下一组逆置后的第一个结点
                cur->next = new_next_group_head;
            else                  // 不为空则表示逆置当前组的结点,指向prev即可
                cur->next = prev;
            prev = cur;   // 向后推进,直到走完当前组
            cur = next;           
        }
        // 返回逆置后的头指针
        return prev;
    }
};

迭代解法

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
     ListNode *reverseKGroup(ListNode *head, int k)
    {
        // 特殊情况处理
        if (NULL == head || NULL == head->next || k < 2)
            return head;

        ListNode* prev = NULL, *pcur = head, *newhead = NULL;

        // 遍历链表,处理每一组
        while (pcur){

            // 找到下一组的头
            ListNode* next_group_head = pcur;
            int i = 0;
            for (; next_group_head && i < k; i++){
                next_group_head = next_group_head->next;
            }
            // 处理不足K 个元素的组
            if (i < k ){
                // 防止K 大于链表结点
                if (newhead == NULL)
                    newhead = head;
                break;
            }
            // 将当前分组[pcur, next_group_head) 逆置,并返回逆置后的头指针
            ListNode* tmp = reverse(pcur, next_group_head);

            if (prev == NULL) // 第一个分组需要更新新的头指针
                newhead = tmp;
            else  // 后续只需要将上一个分组的最后一个结点next 指向当前分组逆序后的的头指针
                prev->next = tmp;
            // 当前分组的最后一个结点next 指向下一个分组开始
            pcur->next = next_group_head;
            // prev 保存当前分组的最后一个结点
            prev = pcur;
            // pcur 向后推进到下一个分组的开始
            pcur = next_group_head;
        }
        return newhead;
    }
    //    [start, end)
    ListNode* reverse(ListNode* start, ListNode* end)
    {
        ListNode* prev = NULL;
        ListNode* pcur = start;
        while (pcur != end){
            ListNode* next = pcur->next;
            pcur->next = prev;
            prev = pcur;
            pcur = next;
        }
        return prev;
    }
};
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页