博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Leetcode: Reverse Nodes in k-Group
阅读量:4310 次
发布时间:2019-06-06

本文共 5316 字,大约阅读时间需要 17 分钟。

Given a linked list, reverse the nodes of a linked list k at a time and return its modified 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->5For k = 2, you should return: 2->1->4->3->5For k = 3, you should return: 3->2->1->4->5

Analysis: Linked List节点倒序,Naive的方法就是用Stack,这样的话只需要K层Stack,不满足constant memory的条件;

第二遍方法(采用解法)两个指针:walker指向需改序序列的上一个节点,runner指向需改序序列最后节点,每次把walker下一个节点移到runner下一点处,直到walker.next = runner

1 /** 2  * Definition for singly-linked list. 3  * public class ListNode { 4  *     int val; 5  *     ListNode next; 6  *     ListNode(int x) { 7  *         val = x; 8  *         next = null; 9  *     }10  * }11  */12 public class Solution {13     public ListNode reverseKGroup(ListNode head, int k) {14         ListNode dummy = new ListNode(-1);15         dummy.next = head;16         ListNode walker = dummy;17         ListNode runner = dummy;18         while (runner.next != null) {19             int count = k;20             while (count > 0 && runner.next != null) {21                 runner = runner.next;22                 count--;23             }24             if (count == 0) walker = reverse(walker, runner);25             else break;26             runner = walker;27         }28         return dummy.next;29     }30     31     public ListNode reverse(ListNode walker, ListNode runner) {32         ListNode store = walker.next;33         while (walker.next != runner) {34             ListNode cur = walker.next;35             ListNode next = cur.next;36             cur.next = runner.next;37             runner.next = cur;38             walker.next = next;39         }40         return store;41     }42 }

第二遍方法(另一种方法,可以但是不如第一种方法好写):精髓在于reverse子函数,输入的两个参数分别是prev: 需改续序列的上一个节点,end: 需改续序列的下一个节点

reverse函数中设计比较精巧的地方在于,需要一开始保存一个start.next节点,最后作为start的新位置返回去更新start,这就是新的需改续序列的上一个节点位置(我一开始也就是卡在这里,不知如何更新start)

1 public class Solution { 2     public ListNode reverseKGroup(ListNode head, int k) { 3         ListNode dummy = new ListNode(0); 4         dummy.next = head; 5   6         ListNode start = dummy; 7         ListNode end = head; 8         while (end != null) { 9             int count = k;10             for (; count>0 && end!=null; count--) {11                 end = end.next;12             }13             if (count == 0) {14                 start = reverse(start, end);15             }16         }17         return dummy.next;18     }19     20     public ListNode reverse(ListNode start, ListNode end) {21         ListNode pre = end;22         ListNode store = start.next;23         ListNode cur = store;24         while (cur != end) {25             ListNode next = cur.next;26             cur.next = pre;27             pre = cur;28             cur = next;29         }30         start.next = pre;31         return store;32     }33 }

Naive方法:使用Stack, 但不满足constant memeory的条件

1 /** 2  * Definition for singly-linked list. 3  * public class ListNode { 4  *     int val; 5  *     ListNode next; 6  *     ListNode(int x) { 7  *         val = x; 8  *         next = null; 9  *     }10  * }11  */12 public class Solution {13     public ListNode reverseKGroup(ListNode head, int k) {14         if (head == null) return null;15         ListNode prev = new ListNode(-1);16         prev.next = head;17         ListNode current = prev;18         while (head != null) {19             Stack
store = new Stack
();20 ListNode temp = head;21 int i = 0;22 for (; i < k; i++) {23 if (head == null) break;24 store.push(head.val);25 head = head.next;26 }27 if (i == k) {28 while (!store.empty()) {29 current.next = new ListNode(store.pop());30 current = current.next;31 }32 }33 else current.next = temp;34 }35 return prev.next;36 }37 }

Gode Ganker的改指针做法(与我的第二遍方法2相仿),输入给reverse函数的参数分别是:prev: 需改续序列的前一个节点,end: 需改续序列的后一个节点

基本思路是这样的,我们统计目前节点数量,如果到达k,就把当前k个结点reverse,这里需要reverse linked list的subroutine。这里我们需要先往前走,到达k的时候才做reverse,所以总体来说每个结点会被访问两次。总时间复杂度是O(2*n)=O(n),空间复杂度是O(1)。

1 public ListNode reverseKGroup(ListNode head, int k) { 2     if(head == null) 3     { 4         return null; 5     } 6     ListNode dummy = new ListNode(0); 7     dummy.next = head; 8     int count = 0; 9     ListNode pre = dummy;10     ListNode cur = head;11     while(cur != null)12     {13         count ++;14         ListNode next = cur.next;15         if(count == k)16         {17             pre = reverse(pre, next);18             count = 0;   19         }20         cur = next;21     }22     return dummy.next;23 }24 private ListNode reverse(ListNode pre, ListNode end)25 {26     if(pre==null || pre.next==null)27         return pre;28     ListNode head = pre.next;29     ListNode cur = pre.next.next;30     while(cur!=end)31     {32         ListNode next = cur.next;33         cur.next = pre.next;34         pre.next = cur;35         cur = next;36     }37     head.next = end;38     return head;39 }

 

转载于:https://www.cnblogs.com/EdwardLiu/p/3792086.html

你可能感兴趣的文章
实验一
查看>>
Ubuntu配置SSH免密码登陆
查看>>
SOA
查看>>
UVA10561 Treblecross 组合游戏/SG定理
查看>>
查询Oracle定时Job
查看>>
root账户不能使用密码只能使用密钥远程登陆
查看>>
浅谈WPF中对控件的位图特效(虚化效果、外辉光效果)
查看>>
[翻译] TensorFlow Programmer's Guide之Frequently Asked Questions(问得频率最多的几个问题)...
查看>>
JavaWeb基础—会话管理之Cookie
查看>>
kettle学习笔记(六)——kettle转换步骤
查看>>
5、Node.js 回调函数
查看>>
由于启动用户实例的进程时出错,导致无法生成 SQL Server 的用户实例 解决办法...
查看>>
ActiveMQ之topic主题模式
查看>>
15 可视化工具 Navicat的简单使用
查看>>
神兵利器:Burpsuite工具分享与使用简介
查看>>
xml
查看>>
使用 Left Join 的一个错误说明
查看>>
[Java] Oracle的JDBC驱动的版本说明
查看>>
ASP.NET内置对象之Request对象
查看>>
Spring学习笔记5——注解方式AOP
查看>>