当前位置: 代码迷 >> 综合 >> leetcode_25:Nodes in k-Group
  详细解决方案

leetcode_25:Nodes in k-Group

热度:32   发布时间:2023-12-10 22:43:01.0

这个题目应该比较经典,虽说是hard级别,可是并没有那么难。下面看一下我的解法和经典的解法。

1. 我的解法(费时费力)

既然是逆转,我先想到的是使用,比如三个为一组,那么我只要把这三个节点往栈里放,然后依次弹出并连接不就好了,然后弹出最后一个后再递归进行后面此类操作。当然,这个写起程序来还是比较简单无脑的,但是费时费力,因为用到了递归,如果链表很长…不能想象。不过还是要上一下代码:

    public ListNode reverseKGroup(ListNode head, int k) {
    Stack<ListNode> stack = new Stack<>();int num = k;ListNode oldHead = head;	//记住旧链表的头,以便没有k个元素时直接返回while (head != null && num > 0) {
    stack.push(head);head = head.next;--num;}if (num > 0)	//最后一组节点数量小于k个,直接返回原链表的头结点return oldHead;ListNode nextHead = head;	//因为上一步中head若满足则一定指向下一个链表的头ListNode newHead = stack.pop(), p = newHead;	//逆转后新链表的头部为栈顶while (!stack.empty()) {
    	//将栈中剩余元素连接起来p.next = stack.pop();p = p.next;}p.next = null;	//中断最后一个节点的nextp.next = reverseKGroup(nextHead, k);	//递归逆转后面的链表return newHead;		//返回新的}
2. 经典解法(省时省力)

其实经典解法说起来也就是没有用递归,而只需要循环遍历就行,也不难理解。关键的思路在于逆转链表的时候要使用头插法。记住某一个子链表的头结点,然后一个指针向后移动,并将这个指针所指的节点进行头插即可。只是这个过程因为要记住的东西太多了,所以定义的临时变量会有点多,但是思路确是比较容易理解的。代码如下:

    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;}

2020.2.20更

3.更简洁好看的

我不知道为什么已经看不懂第二种是什么鬼了,分享一下看到的更容易懂的解法。首先我们要有一个函数翻转部分链表,在反转链表中我们讲过迭代的方法,它是翻转整个链表,那么我们把结束的条件改一下,就可以让它翻转部分链表,代码如下:

/** 反转区间 [a, b) 的元素,注意是左闭右开 */
ListNode reverse(ListNode a, ListNode b) {
    ListNode pre, cur, nxt;pre = null; cur = a; nxt = a;// while 终止的条件改一下就行了,也就是说我们对于b是不进行翻转的while (cur != b) {
    nxt = cur.next; //先把下一个存起来,更新nxtcur.next = pre;  //翻转pre = cur;  //更新pre和curcur = nxt;}// 返回反转后的头结点return pre;
}ListNode reverseKGroup(ListNode head, int k) {
    if (head == null) return null;// 区间 [a, b) 包含 k 个待反转元素ListNode a, b;a = b = head;for (int i = 0; i < k; i++) {
    // 不足 k 个,不需要反转,base caseif (b == null) return head;b = b.next;}// 反转前 k 个元素,此时区间为[a,b),而且新的尾结点就是原来的头结点aListNode newHead = reverse(a, b);// 递归反转后续链表并连接起来,即将尾结点a.next指向后面的翻转a.next = reverseKGroup(b, k);return newHead;
}
  相关解决方案