【算法】将单链表的每K个节点之间逆序

【算法】将单链表的每K个节点之间逆序


头条的一道面试题,折磨死我了,为了下次不再被折磨贴一下……
(LeetCode 25)

将单链表的每K个节点之间逆序

限定语言:C、Python、C++、Javascript、Python 3、Java、Go

给定一个单链表,实现一个调整单链表的函数,使得每 K 个节点之间的值逆序,如果最后不够 K 个节点一组,则不调整最后几个节点。

示例1

输入

[1,2,3,4,5],3

输出

{3,2,1,4,5}

思路

我的想法比较朴素,用一个节点从头到尾遍历链表,并计数,每k个数字执行一次逆序操作。要记录上一个链表的末尾以及当前操作逆序链表的头,来使这两部分相连接。最后退出循环时,分两种情况,一种是数字个数刚好是k的整数倍,一种是还有富余,即退出循环时还需要处理剩余的数据。

看着没什么很复杂的东西,但是写代码的时候其实挺坑的…… 复杂度过大,通过率为0,通过率90%+复杂度过大,老铁,扎不扎心。。

代码:

import java.util.*;

/*
 * public class ListNode {
 *   int val;
 *   ListNode next = null;
 * }
 */

public class Solution {
    /**
     * 
     * @param head ListNode类 the head
     * @param k int整型 the k
     * @return ListNode类
     */
    public ListNode reverseLinkedlist (ListNode head, int k) {
        if(head == null) return null;
        if(head.next == null) return head;
        if(k==1) return head;
        ListNode p =head;
        int tcnt = 0;;
        //ch记录当前这部分链表的头 fh记录上一部分链表的头(逆序之后变成尾了,千万注意……)
        ListNode ch = head, fh = null;
        while(p!=null) {
            tcnt++;
            if(ch == null) ch = p;
            if(tcnt % k ==0) {
                //处理这k个元素
                ListNode prev =ch, cur=ch.next, next=null;
                int lcnt=0;
                //先逆序,常规的链表逆序操作
                while(cur!=null && lcnt<k-1) {
                    next = cur.next;
                    cur.next = prev;
                    prev = cur;
                    cur = next;
                    lcnt++;
                }
                //串联链表,需要将前一部分和这一部分链表连接起来
                if(fh == null) {
                    head=prev;
                    //fh = ch;
                } else {
                    fh.next = prev;
                    //fh = ch;
                }
                fh=ch;;
                ch = null;
                //对于遍历的指针也要留心,这里不单独处理的话就死循环了
                p=cur;
            } else {
                p = p.next;
            }
        }
        //退出循环后的处理 分两种情况
        if(tcnt % k != 0) {
            //连接剩余的数据
            fh.next = ch;
        } else {
            //一定要置为null,不然只要遍历这个返回结果就死循环
            fh.next = null;
        }
        return head;
    }
}

21.1.25: 优雅点的实现
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode reverseKGroup(ListNode head, int k) {
        ListNode pHead = new ListNode();
        pHead.next = head;
        if(k==1) return head;
        ListNode p = head, lastTail = pHead, thisHead = null;
        int count = 0;
        while(p!=null) {
            if(thisHead == null) {
                thisHead = p;
            }
            if(++count % k==0) {
                //反转
                ListNode next = p.next;

                ListNode pre = thisHead, cur = pre.next, mNext = null;
                while(cur != null && cur != next) {
                    mNext = cur.next;
                    cur.next = pre;
                    pre = cur;
                    cur = mNext;
                }
                
                thisHead.next = next;
                lastTail.next = p;

                //
                lastTail = thisHead;
                thisHead = null;
                p = next;
            } else {
                //否则继续遍历即可
                p = p.next;
            }
        }
        lastTail.next = thisHead;
        return pHead.next;
    }
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值