LeetCode 25 - Reverse Nodes in k-Group


https://leetcode.com/problems/reverse-nodes-in-k-group/
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 kthen left-out nodes in the end should remain as it is.
    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
    Note:
    • Only constant extra memory is allowed.
    • You may not alter the values in the list's nodes, only nodes itself may be changed
    X.
    http://bangbingsyb.blogspot.com/2014/11/leetcode-reverse-nodes-in-k-group.html
    Swap Nodes in Pairs那题的升级版,算linked list指针操作题中难度最高最容易写错的之一。思路很简单,就是每次反转k个节点,如果还没反转到i<k个节点就遇到尾部了,则将这i个节点再反转回来。但要短时间内写正确却难度不小。这类题目一定要画图来验证解法是否正确。
    几乎用到linked list题所有的技巧。
    1. p指针总是指向每次要反转的k个节点的前一个节点。因为反转后仍然要接回这个节点之后。
    2. ln8:如果p指针后没有节点或只剩一个节点了,那么整个反转结束。
    3. ln11-17:尝试反转k个节点,如果遇到尾部,则提前结束。i记录了反转多少次。注意,要反转k个节点的话,实际反转指针只需要k-1次。
    4. ln19-24:如果成功反转k个节点,则i=k-1。此时将反转的k个节点两头接回,并将p移动到反转后k个节点的最后一个节点处,以备继续反转之后的k个节点。
    5. ln25-35:如果没能反转k个节点就遇到尾部。则逆向还原。
        ListNode *reverseKGroup(ListNode *head, int k) {
            if(k<2) return head;
            ListNode *dummy = new ListNode(0);
            dummy->next = head;
            ListNode *p = dummy;
            while(p->next && p->next->next) {
                ListNode *prev = p->next, *cur = prev->next;
                int i=0;
                while(cur && i<k-1) {
                    ListNode *temp = cur->next;
                    cur->next = prev;
                    prev = cur;
                    cur = temp;
                    i++;
                }
                
                if(i==k-1) {    // k nodes reversed
                    ListNode *temp = p->next;
                    p->next->next = cur;
                    p->next = prev;
                    p = temp;
                }
                else {  // less than k nodes reversed before reach end
                    cur = prev->next;
                    prev->next = NULL;
                    while(cur != p->next) {
                        ListNode *temp = cur->next;
                        cur->next = prev;
                        prev = cur;
                        cur = temp;
                    }
                    break; 
                }
            }
            return dummy->next;
        }
    https://zxi.mytechroad.com/blog/list/leetcode-25-reverse-nodes-in-k-group/
      ListNode *reverseKGroup(ListNode *head, int k) {
        if (!head || k == 1) return head;
        ListNode dummy(0);
        dummy.next = head;
        int len = 1;
        while (head = head->next) len++;
        ListNode* pre = &dummy;    
        for (int l = 0; l + k <= len; l += k) {
          ListNode* cur = pre->next;
          ListNode* nxt = cur->next;
          for (int i = 1; i < k; ++i) {
            cur->next = nxt->next;
            nxt->next = pre->next;
            pre->next = nxt;
            nxt = cur->next;
          }
          pre = cur;
        }
        return dummy.next;
      }
    http://www.cnblogs.com/grandyang/p/4441324.html
    这道题让我们以每k个为一组来翻转链表,实际上是把原链表分成若干小段,然后分别对其进行翻转,那么肯定总共需要两个函数,一个是用来分段的,一个是用来翻转的,我们就以题目中给的例子来看,对于给定链表1->2->3->4->5,一般在处理链表问题时,我们大多时候都会在开头再加一个dummy node,因为翻转链表时头结点可能会变化,为了记录当前最新的头结点的位置而引入的dummy node,那么我们加入dummy node后的链表变为-1->1->2->3->4->5,如果k为3的话,我们的目标是将1,2,3翻转一下,那么我们需要一些指针,pre和next分别指向要翻转的链表的前后的位置,然后翻转后pre的位置更新到如下新的位置:

     |        |  |
    pre      cur next
    
    -1->3->2->1->4->5
        |     |  |
       cur   pre next

    以此类推,只要cur走过k个节点,那么next就是cur->next,就可以调用翻转函数来进行局部翻转了,注意翻转之后新的cur和pre的位置都不同了,那么翻转之后,cur应该更新为pre->next,而如果不需要翻转的话,cur更新为cur->next:

    https://leetcode.com/problems/reverse-nodes-in-k-group/discuss/11413/Share-my-Java-Solution-with-comments-in-line
            public ListNode reverseKGroup(ListNode head, int k) {
                if (head==null||head.next==null||k<2) return head;
        
                ListNode dummy = new ListNode(0);
                dummy.next = head;
                
                ListNode tail = dummy, prev = dummy,temp;
                int count;
                while(true){
                    count =k;
                    while(count>0&&tail!=null){
                        count--;
                        tail=tail.next;
                    } 
                    if (tail==null) break;//Has reached the end
                    
        
                    head=prev.next;//for next cycle
                // prev-->temp-->...--->....--->tail-->....
                // Delete @temp and insert to the next position of @tail
                // prev-->...-->...-->tail-->head-->...
                // Assign @temp to the next node of @prev
                // prev-->temp-->...-->tail-->...-->...
                // Keep doing until @tail is the next node of @prev
                    while(prev.next!=tail){
                        temp=prev.next;//Assign
                        prev.next=temp.next;//Delete
                        
                        temp.next=tail.next;
                        tail.next=temp;//Insert
                        
                    }
                    
                    tail=head;
                    prev=head;
                    
                }
                return dummy.next;
                
            }
    https://leetcode.com/problems/reverse-nodes-in-k-group/discuss/11440/Non-recursive-Java-solution-and-idea


    First, build a function reverse() to reverse the ListNode between begin and end. See the explanation below:
       /**
         * Reverse a link list between begin and end exclusively
         * an example:
         * a linked list:
         * 0->1->2->3->4->5->6
         * |           |   
         * begin       end
         * after call begin = reverse(begin, end)
         * 
         * 0->3->2->1->4->5->6
         *          |  |
         *      begin end
         * @return the reversed list's 'begin' node, which is the precedence of node end
         */
    
    Then walk thru the linked list and apply reverse() iteratively. See the code below.
    public ListNode reverseKGroup(ListNode head, int k) {
        ListNode begin;
        if (head==null || head.next ==null || k==1)
        	return head;
        ListNode dummyhead = new ListNode(-1);
        dummyhead.next = head;
        begin = dummyhead;
        int i=0;
        while (head != null){
        	i++;
        	if (i%k == 0){
        		begin = reverse(begin, head.next);
        		head = begin.next;
        	} else {
        		head = head.next;
        	}
        }
        return dummyhead.next;
        
    }
    
    public ListNode reverse(ListNode begin, ListNode end){
    	ListNode curr = begin.next;
    	ListNode next, first;
    	ListNode prev = begin;
    	first = curr;
    	while (curr!=end){
    		next = curr.next;
    		curr.next = prev;
    		prev = curr;
    		curr = next;
    	}
    	begin.next = prev;
    	first.next = curr;
    	return first;
    }

    X.
    我们也可以使用递归来做,我们用head记录每段的开始位置,cur记录结束位置的下一个节点,然后我们调用reverse函数来将这段翻转,然后得到一个new_head,原来的head就变成了末尾,这时候后面接上递归调用下一段得到的新节点,返回new_head即可
        ListNode* reverseKGroup(ListNode* head, int k) {
            ListNode *cur = head;
            for (int i = 0; i < k; ++i) {
                if (!cur) return head;
                cur = cur->next;
            }
            ListNode *new_head = reverse(head, cur);
            head->next = reverseKGroup(cur, k);
            return new_head;
        }
        ListNode* reverse(ListNode* head, ListNode* tail) {
            ListNode *pre = tail;
            while (head != tail) {
                ListNode *t = head->next;
                head->next = pre;
                pre = head;
                head = t;
            }
            return pre;
        }
    https://www.geeksforgeeks.org/reverse-a-list-in-groups-of-given-size/
    https://www.geeksforgeeks.org/reverse-linked-list-groups-given-size-set-2/
    https://leetcode.com/problems/reverse-nodes-in-k-group/discuss/11423/Short-but-recursive-Java-code-with-comments
    public ListNode reverseKGroup(ListNode head, int k) {
        ListNode curr = head;
        int count = 0;
        while (curr != null && count != k) { // find the k+1 node
            curr = curr.next;
            count++;
        }
        if (count == k) { // if k+1 node is found
            curr = reverseKGroup(curr, k); // reverse list with k+1 node as head
            // head - head-pointer to direct part, 
            // curr - head-pointer to reversed part;
            while (count-- > 0) { // reverse current k-group: 
                ListNode tmp = head.next; // tmp - next head in direct part
                head.next = curr; // preappending "direct" head to the reversed list 
                curr = head; // move head of reversed part to a new node
                head = tmp; // move "direct" head to the next node in direct part
            }
            head = curr;
        }
        return head;
    }
    https://www.jiuzhang.com/solution/reverse-nodes-in-k-group/
        public ListNode reverseKGroup(ListNode head, int k) {
            if (head == null || k <= 1) {
                return head;
            }
            
            ListNode dummy = new ListNode(0);
            dummy.next = head;
            
            head = dummy;
            while (head.next != null) {
                head = reverseNextK(head, k);
            }
            
            return dummy.next;
        }
        
        // reverse head->n1->..->nk->next..
        // to head->nk->..->n1->next..
        // return n1
        private ListNode reverseNextK(ListNode head, int k) {
            // check there is enought nodes to reverse
            ListNode next = head; // next is not null
            for (int i = 0; i < k; i++) {
                if (next.next == null) {
                    return next;
                }
                next = next.next;
            }
            
            // reverse
            ListNode n1 = head.next;
            ListNode prev = head, curt = n1;
            for (int i = 0; i < k; i++) {
                ListNode temp = curt.next;
                curt.next = prev;
                prev = curt;
                curt = temp;
            }
            
            n1.next = curt;
            head.next = prev;
            return n1;
        }
    
    • 1

    Labels

    LeetCode (1432) GeeksforGeeks (1122) LeetCode - Review (1067) Review (882) Algorithm (668) to-do (609) Classic Algorithm (270) Google Interview (237) Classic Interview (222) Dynamic Programming (220) DP (186) Bit Algorithms (145) POJ (141) Math (137) Tree (132) LeetCode - Phone (129) EPI (122) Cracking Coding Interview (119) DFS (115) Difficult Algorithm (115) Lintcode (115) Different Solutions (110) Smart Algorithm (104) Binary Search (96) BFS (91) HackerRank (90) Binary Tree (86) Hard (79) Two Pointers (78) Stack (76) Company-Facebook (75) BST (72) Graph Algorithm (72) Time Complexity (69) Greedy Algorithm (68) Interval (63) Company - Google (62) Geometry Algorithm (61) Interview Corner (61) LeetCode - Extended (61) Union-Find (60) Trie (58) Advanced Data Structure (56) List (56) Priority Queue (53) Codility (52) ComProGuide (50) LeetCode Hard (50) Matrix (50) Bisection (48) Segment Tree (48) Sliding Window (48) USACO (46) Space Optimization (45) Company-Airbnb (41) Greedy (41) Mathematical Algorithm (41) Tree - Post-Order (41) ACM-ICPC (40) Algorithm Interview (40) Data Structure Design (40) Graph (40) Backtracking (39) Data Structure (39) Jobdu (39) Random (39) Codeforces (38) Knapsack (38) LeetCode - DP (38) Recursive Algorithm (38) String Algorithm (38) TopCoder (38) Sort (37) Introduction to Algorithms (36) Pre-Sort (36) Beauty of Programming (35) Must Known (34) Binary Search Tree (33) Follow Up (33) prismoskills (33) Palindrome (32) Permutation (31) Array (30) Google Code Jam (30) HDU (30) Array O(N) (29) Logic Thinking (29) Monotonic Stack (29) Puzzles (29) Code - Detail (27) Company-Zenefits (27) Microsoft 100 - July (27) Queue (27) Binary Indexed Trees (26) TreeMap (26) to-do-must (26) 1point3acres (25) GeeksQuiz (25) Merge Sort (25) Reverse Thinking (25) hihocoder (25) Company - LinkedIn (24) Hash (24) High Frequency (24) Summary (24) Divide and Conquer (23) Proof (23) Game Theory (22) Topological Sort (22) Lintcode - Review (21) Tree - Modification (21) Algorithm Game (20) CareerCup (20) Company - Twitter (20) DFS + Review (20) DP - Relation (20) Brain Teaser (19) DP - Tree (19) Left and Right Array (19) O(N) (19) Sweep Line (19) UVA (19) DP - Bit Masking (18) LeetCode - Thinking (18) KMP (17) LeetCode - TODO (17) Probabilities (17) Simulation (17) String Search (17) Codercareer (16) Company-Uber (16) Iterator (16) Number (16) O(1) Space (16) Shortest Path (16) itint5 (16) DFS+Cache (15) Dijkstra (15) Euclidean GCD (15) Heap (15) LeetCode - Hard (15) Majority (15) Number Theory (15) Rolling Hash (15) Tree Traversal (15) Brute Force (14) Bucket Sort (14) DP - Knapsack (14) DP - Probability (14) Difficult (14) Fast Power Algorithm (14) Pattern (14) Prefix Sum (14) TreeSet (14) Algorithm Videos (13) Amazon Interview (13) Basic Algorithm (13) Codechef (13) Combination (13) Computational Geometry (13) DP - Digit (13) LCA (13) LeetCode - DFS (13) Linked List (13) Long Increasing Sequence(LIS) (13) Math-Divisible (13) Reservoir Sampling (13) mitbbs (13) Algorithm - How To (12) Company - Microsoft (12) DP - Interval (12) DP - Multiple Relation (12) DP - Relation Optimization (12) LeetCode - Classic (12) Level Order Traversal (12) Prime (12) Pruning (12) Reconstruct Tree (12) Thinking (12) X Sum (12) AOJ (11) Bit Mask (11) Company-Snapchat (11) DP - Space Optimization (11) Dequeue (11) Graph DFS (11) MinMax (11) Miscs (11) Princeton (11) Quick Sort (11) Stack - Tree (11) 尺取法 (11) 挑战程序设计竞赛 (11) Coin Change (10) DFS+Backtracking (10) Facebook Hacker Cup (10) Fast Slow Pointers (10) HackerRank Easy (10) Interval Tree (10) Limited Range (10) Matrix - Traverse (10) Monotone Queue (10) SPOJ (10) Starting Point (10) States (10) Stock (10) Theory (10) Tutorialhorizon (10) Kadane - Extended (9) Mathblog (9) Max-Min Flow (9) Maze (9) Median (9) O(32N) (9) Quick Select (9) Stack Overflow (9) System Design (9) Tree - Conversion (9) Use XOR (9) Book Notes (8) Company-Amazon (8) DFS+BFS (8) DP - States (8) Expression (8) Longest Common Subsequence(LCS) (8) One Pass (8) Quadtrees (8) Traversal Once (8) Trie - Suffix (8) 穷竭搜索 (8) Algorithm Problem List (7) All Sub (7) Catalan Number (7) Cycle (7) DP - Cases (7) Facebook Interview (7) Fibonacci Numbers (7) Flood fill (7) Game Nim (7) Graph BFS (7) HackerRank Difficult (7) Hackerearth (7) Inversion (7) Kadane’s Algorithm (7) Manacher (7) Morris Traversal (7) Multiple Data Structures (7) Normalized Key (7) O(XN) (7) Radix Sort (7) Recursion (7) Sampling (7) Suffix Array (7) Tech-Queries (7) Tree - Serialization (7) Tree DP (7) Trie - Bit (7) 蓝桥杯 (7) Algorithm - Brain Teaser (6) BFS - Priority Queue (6) BFS - Unusual (6) Classic Data Structure Impl (6) DP - 2D (6) DP - Monotone Queue (6) DP - Unusual (6) DP-Space Optimization (6) Dutch Flag (6) How To (6) Interviewstreet (6) Knapsack - MultiplePack (6) Local MinMax (6) MST (6) Minimum Spanning Tree (6) Number - Reach (6) Parentheses (6) Pre-Sum (6) Probability (6) Programming Pearls (6) Rabin-Karp (6) Reverse (6) Scan from right (6) Schedule (6) Stream (6) Subset Sum (6) TSP (6) Xpost (6) n00tc0d3r (6) reddit (6) AI (5) Abbreviation (5) Anagram (5) Art Of Programming-July (5) Assumption (5) Bellman Ford (5) Big Data (5) Code - Solid (5) Code Kata (5) Codility-lessons (5) Coding (5) Company - WMware (5) Convex Hull (5) Crazyforcode (5) DFS - Multiple (5) DFS+DP (5) DP - Multi-Dimension (5) DP-Multiple Relation (5) Eulerian Cycle (5) Graph - Unusual (5) Graph Cycle (5) Hash Strategy (5) Immutability (5) Java (5) LogN (5) Manhattan Distance (5) Matrix Chain Multiplication (5) N Queens (5) Pre-Sort: Index (5) Quick Partition (5) Quora (5) Randomized Algorithms (5) Resources (5) Robot (5) SPFA(Shortest Path Faster Algorithm) (5) Shuffle (5) Sieve of Eratosthenes (5) Strongly Connected Components (5) Subarray Sum (5) Sudoku (5) Suffix Tree (5) Swap (5) Threaded (5) Tree - Creation (5) Warshall Floyd (5) Word Search (5) jiuzhang (5)

    Popular Posts