leetcode25. Reverse Nodes in k-Group

Hard程度題

題目:

Given a linked list, reverse the nodes of a linked list k at a time and return its modified list.

k is a positive integer and is less than or equal to the length of the linked list. If the number of nodes is not a multiple of k then left-out nodes in the end should remain as it is.

You may not alter the values in the nodes, only nodes itself may be changed.

Only constant memory is allowed.

For example,
Given this linked list: 1->2->3->4->5

For k = 2, you should return: 2->1->4->3->5

For k = 3, you should return: 3->2->1->4->5

爲之前的題目Swap Nodes In Pairs兩個兩個交換的更一般情況,有了這題的基礎,這裏只要稍加改進即可,每次改造節點後都判斷餘下的節點數是否小於K

AC解

class Solution {
public:
    ListNode* reverseKGroup(ListNode* head, int k) 
    {
        int a = k;
        ListNode *temp = head;//temp用來偵測後面節點是否大於等於K
        while (temp != nullptr)
        {
            temp = temp->next;
            a--;
        }
        if (a > 0 || k == 1)//如果節點個數少於K或者K == 1時直接返回
            return head;
            
        ListNode dummy(-1);
        dummy.next = head;
        ListNode *p = &dummy,*prev = head,*cur = head->next,*head2 = head;
        
        while (true)
        {
            for (int i = k ; i > 1; i--)
            {//改造節點
                head2->next = cur->next;
                cur->next = prev;
                prev = cur;
                cur = head2->next;
            }
            
            p->next = prev;//第一次執行時,將返回鏈表的頭結點存入dummy.next,後面執行時將兩段鏈表連接起來
            p = head2;//p用來存儲當前的head2頭結點,當接下來的K個節點改造完畢後
            head2 = cur;//head2指向剩餘未改造的鏈表頭
            
            //偵測後面節點是否大於等於K
            a = k;
            temp = head2;
            while (temp)
            {
                temp = temp->next;
                a--;
            }
            if (a > 0)
                return dummy.next;//如果節點數小於K返回
                
            //將prev cur賦值 準備開始下次改造節點
            prev = head2;
            cur = prev->next;
        }
    }
};

代碼可讀性差,參照別人解法,思想一致,但代碼更優美

AC解

class Solution {
public:
    ListNode* reverseKGroup(ListNode* head, int k) 
    {
        if (head == nullptr || head->next == nullptr || k < 2)
            return head;
        ListNode dummy(-1);
        dummy.next = head;
        
        for (ListNode *prev = &dummy,*end = head; end; end = prev->next)
        {
            for (int i = 1; i < k && end; i++)
                end = end->next;
            if (end == nullptr)//不足K個
                break;
                
            prev = reverse(prev,prev->next,end);
        }
        
        return dummy.next;
    }
    //prev是begin前的一個節點
    //返回反轉後的最後一個節點,用於連接連續兩個反轉的鏈表
    ListNode *reverse(ListNode *prev,ListNode *begin,ListNode *end)
    {
        ListNode *end_next = end->next;
        for (ListNode *p = begin,*cur = p->next,*next = cur->next;
                cur != end_next;
                p = cur,cur = next,next = next ? next->next:nullptr)
            cur->next = p;
            
        begin->next = end_next;
        prev->next = end;
        return begin;
    }
    
};





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章