首页 > 试题广场 >

链表中的节点每k个一组翻转

[编程题]链表中的节点每k个一组翻转
  • 热度指数:254364 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
将给出的链表中的节点每 k 个一组翻转,返回翻转后的链表
如果链表中的节点数不是 k 的倍数,将最后剩下的节点保持原样
你不能更改节点中的值,只能更改节点本身。

数据范围: ,链表中每个元素都满足
要求空间复杂度 ,时间复杂度
例如:
给定的链表是
对于 , 你应该返回
对于 , 你应该返回

示例1

输入

{1,2,3,4,5},2

输出

{2,1,4,3,5}
示例2

输入

{},1

输出

{}

说明:本题目包含复杂数据结构ListNode,点此查看相关信息
import java.util.*;

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

import java.util.*;
public class Solution {
    public ListNode reverseKGroup (ListNode head, int k) {
        //找到每次翻转的尾部
        ListNode tail = head;
        //遍历k次到尾部 
        for(int i = 0; i < k; i++){ 
            //如果不足k到了链表尾,直接返回,不翻转
            if(tail == null) 
                return head;
            tail = tail.next; 
        }
        //翻转时需要的前序和当前节点
        ListNode pre = null; 
        ListNode cur = head;
        //在到达当前段尾节点前
        while(cur != tail){ 
            //翻转
            ListNode temp = cur.next; 
            cur.next = pre;
            pre = cur;
            cur = temp;
        }
        //当前尾指向下一段要翻转的链表
        head.next = reverseKGroup(tail, k); 
        return pre;
    }
}

发表于 2024-02-20 23:13:29 回复(1)
遍历链表同时计数,当计数是k的倍数时,说明要反转k-1个数,反转时使用BM2中的例子,一次遍历反转,反转后更新pre和cur,确保下次反转时使用。
时间复杂度:O(n)    // 仅用一个for循环遍历链表,反转时与其覆盖
空间复杂度:O(1)    // 开辟常量级空间
import java.util.*;

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

public class Solution {
    /**
     *
     * @param head ListNode类
     * @param k int整型
     * @return ListNode类
     */
    public ListNode reverseKGroup (ListNode head, int k) {
        ListNode ans = new ListNode(0);    // 扩增一个头节点,方便反转
        ans.next  = head;
        if(k<=1 || head==null || head.next==null)
            return head;
        ListNode tmp = head; 
        ListNode pre = ans;         // 记录翻转前位置
        ListNode cur = pre.next;    // 记录当前要反转的位置
        // 使用tmp遍历链表
        for(int i=1;tmp!=null;i++){
            tmp = tmp.next;
            // 有k个数,翻转
            if(i%k==0){
                // 翻转k-1次
                for(int j=0;j<k-1;j++){
                    ListNode ct = cur.next; // 记录下个要反转的位置
                    cur.next= ct.next;
                    ct.next = pre.next;
                    pre.next = ct;
                }
                // 更新翻转位置
                pre = cur;
                cur = cur.next;
            }
        }
        return ans.next;
    }
}


发表于 2024-01-29 15:06:59 回复(0)
        if(head == null || head.next == null || k<2)return head;
        ListNode dummy = new ListNode(0);
        dummy.next = head;
        ListNode cur = head, pre = dummy, temp = cur;
        while(true)
        {
            //判断是否可分组
            for(int i=0;i<k;i++)
            {
                if(temp == null) return dummy.next;
                temp= temp.next;
            }

            //倒插法
            for(int i = 1; i<k;i++)
            {
                 temp = cur.next;
                 cur.next = temp.next;
                 temp.next = pre.next;
                 pre.next = temp;
            }

            //置位
            pre = cur;
            cur = pre.next;
            temp = cur;
        }

发表于 2024-01-11 11:08:54 回复(0)
public class Solution {
 
    public ListNode reverseKGroup(ListNode head, int k) {
        // write code here
        if (k == 0 || head == null) {
            return head;
        }
        ListNode dummy = new ListNode(1001);
        dummy.next = head;
        ListNode pre = dummy;
        ListNode cur = pre.next;
        ListNode cur2=null;
        while (cur != null) {
            for (int i = 0; i < k-1; i++) {
                if (cur.next == null && i != k-1) {
                    cur = pre.next;
                    for (int j = 0; j < i; j++) {
                        cur2 = cur.next;
                        cur.next = cur2.next;
                        cur2.next = pre.next;
                        pre.next = cur2;
                    }
                    return dummy.next;

                } else {
                    cur2 = cur.next;
                    cur.next = cur2.next;
                    cur2.next = pre.next;
                    pre.next = cur2;
                }

            }

            pre = cur;
            cur = cur.next;

        }
        return dummy.next;
    }
}
发表于 2024-01-09 22:37:45 回复(0)
public class Solution {

    public ListNode reverseKGroup (ListNode head, int k) {
        ListNode dummy = new ListNode(-1);
        dummy.next = head;

        // 长度
        int n = 0;
        ListNode cur = head;
        while( cur != null ) {
            n ++;
            cur = cur.next;
        }

        // 已反转 + 未反转
        int remain = n;
        ListNode pre = null, nxt = null, last = dummy;  // last: 已反转的末尾
        cur = head;
        while ( remain >= k ) {
            remain -= k;

            // 反转 k 
            for (int i = 0; i < k; i++) {
                nxt = cur.next;
                cur.next = pre;
                pre = cur;
                cur = nxt;
            }

            // 接上前面
            nxt = last.next;    // 当前反转前的head, 也就是反转后的 tail
            last.next = pre;    //pre: 反转后的head

            // 接上后面
            last = nxt;
            last.next = cur;     // cur: 下一组待反转的 head
        }
        return dummy.next;
    }
}

发表于 2023-11-06 10:32:56 回复(0)
import java.util.*;

/*
 * public class ListNode {
 *   int val;
 *   ListNode next = null;
 *   public ListNode(int val) {
 *     this.val = val;
 *   }
 * }
 */

public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param head ListNode类 
     * @param k int整型 
     * @return ListNode类
     */
    public ListNode reverseKGroup (ListNode head, int k) {
        // write code here
        if(head==null){
            return head;
        }
        ArrayList<Integer> list=new ArrayList<>();
        Stack<Integer> stack=new Stack<>();
        ListNode tmpList=head;
        while(tmpList!=null){
            list.add(tmpList.val);
            tmpList=tmpList.next;
        }
        if(k>list.size()){
            return head;
        }
        ArrayList<Integer> result=new ArrayList<>();
        for(int i=0;i<list.size();i++){
            stack.push(list.get(i));
            if((i+1)%k==0){
                while(!stack.isEmpty()){
                    result.add(stack.pop());
                }
            }
        }
        ArrayList<Integer> tmp=new ArrayList<>();
        while(!stack.isEmpty()){
            tmp.add(stack.pop());
        }
        Collections.reverse(tmp);
        result.addAll(tmp);
        ListNode tmpNode=new ListNode(result.get(0));
        ListNode returnList=tmpNode;
        for(int i=1;i<result.size();i++){
            ListNode node=new ListNode(result.get(i));
            tmpNode.next=node;
            tmpNode=tmpNode.next;
        }
        return returnList;
    }
}

发表于 2023-11-01 10:20:04 回复(0)
import java.util.*;

/*
 * public class ListNode {
 *   int val;
 *   ListNode next = null;
 *   public ListNode(int val) {
 *     this.val = val;
 *   }
 * }
 */

public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param head ListNode类 
     * @param k int整型 
     * @return ListNode类
     */
    public ListNode reverseKGroup (ListNode head, int k) {
        // write code here
        int len=0;
        ListNode cur=head;
        while(cur!=null){
            len++;
            cur=cur.next;
        }
        // //res用于保存最终结果
        // ListNode res=new ListNode(-1);
        // ListNode tail=res;
        // ListNode p=head;
        // while(len>=k){
        //     len=len-k;
        //     ListNode s=null;
        //     for(int i=1;i<=k;i++){
        //         ListNode tmp=p.next;
        //         p.next=s;
        //         s=p;
        //         p=tmp;
        //     }
        //     //反转完,s拼接到tail后
        //     tail.next=s;
        //     //tail指针移动到最后
        //     ListNode ss=s;
        //     while(ss.next!=null){
        //         ss=ss.next;
        //     }
        //     tail=ss;
        // }
        // //不够k个的节点拼接到tail后
        // if(p!=null){
        //     tail.next=p;
        // }
        // return res.next;

        //res用于保存最终结果
        ListNode res = new ListNode(-1);
        ListNode tail=res;
        ListNode p=head;
        Stack<ListNode> stack = new Stack<>();
        while (len >= k) {
            len = len - k;
            for (int i = 0; i < k; i++) {
                stack.push(p);
                p=p.next;
            }
            for(int i=0;i<k;i++){
                ListNode node=stack.pop();
                tail.next=node;
                node.next=null;
                tail=node;
            }
        }
        tail.next=p;
        return res.next;
    }
}

发表于 2023-09-11 12:15:49 回复(0)
import java.util.*;

public class Solution {
    public ListNode reverseKGroup (ListNode head, int k) {
        ListNode returnNode = new ListNode(-1);
        returnNode.next = head;
        ListNode pre = returnNode;
        int all = 0;
        while(head!=null){
            all++;//记录总结点数
        }
        int n = all/k;//记录有多少组k
        while(n!=0){//每个组都运行下面
            ListNode cur = pre.next;
            ListNode curNext;
            for(int i=0;i<k-1;i++){
                curNext = cur.next;
                cur.next = curNext.next;
                curNext.next = pre.next;
                pre.next = curNext;
            }
            pre = cur;
            n--;
        }
        return returnNode.next;
    }
}
大家帮忙看一下这样写为什么会报错啊。
我的思路是一直遍历  每k个进行翻转。

发表于 2023-09-07 15:32:02 回复(0)
    public static ListNode reverseKGroup(ListNode head, int k) {
        if (k <= 1) {
            return head;
        }
        ListNode p = new ListNode(0);


        p.next = head;
        // write code here
        int m = 1;

        //每次翻转开始结点的前一个结点
        ListNode prePre = p;

        //开始翻转的结点
        ListNode pre = null;
        //结束结点
        ListNode end = null;


        ListNode a = head;

        //计算长度
        int size = 0;
        while (a != null) {
            size++;
            a = a.next;
        }


        a = head;

        int i = 0;
        while (i < size && a != null) {

            //找到翻转起点
            if (m % k == 1) {
                pre = a;
            }
            //找到翻转终点
            if (m % k == 0) {
                end = a;
            }
            //开始翻转
            if (pre != null && end != null) {

                ListNode curr = pre;
                ListNode prec = end.next;
                ListNode endEnd = end.next;

                //结点进入 终点的下一个结点就结束
                while (curr != endEnd) {
                    ListNode tmp = curr.next;
                    curr.next = prec;
                    prec = curr;
                    curr = tmp;
                }

                //结束的时候,翻转开始结点需要执行 翻转终点
                prePre.next = prec;

                //下一个开始结点的前一个结点
                prePre = pre;
                a = pre;

                pre = null;
                end = null;

            }
            a = a.next;
            i++;
            m++;
        }

        return p.next;
    }

发表于 2023-08-14 17:51:58 回复(0)
public ListNode reverseKGroup (ListNode head, int k) {
        if (head == null || head.next == null) {
            return head;
        }
        ListNode n1 = new ListNode(-1);//用来指向头结点
        n1.next = head;
        int c = 1;
        while ((head = head.next) != null) {//计算链表长度
            c++;
        }
        return reverseBetween(n1.next, 1, k, c, k);
    }

    /**
     * 反转指定区间内的链表
     *
     * @param head
     * @param m 左区间
     * @param n 右区间
     * @param c 链表长度
     * @param k 到下一个区间的长度
     * @return 
     */
    public  ListNode reverseBetween(ListNode head, int m, int n, int c, int k) {
        if (n > c) {//如果右侧区间大于链表长度
            return head;
        }
        ListNode n1 = new ListNode(-1);//用来指向头结点
        n1.next = head;
        ListNode prev = n1;//记录反转区间的前一个元素
        int i = 1;

        while (i < m) { //找到反转区间开始的前一个节点,并保存反转区间的第一个节点,也就是当前节点
            prev = head;
            head = head.next;
            i++;
        }
        //反转区间内链表(每次循环,head和prev没有改变)
        int left = m;//保存左侧区间
        while (m < n) {
            ListNode next = head.next;
            head.next = next.next;//head指向他的下一个的下一个节点
            next.next = prev.next;//head的下一个的下一个节点要指向prev的next
            prev.next = next;//prev指向head的下一个节点
            m++;
        }
        m = left;
        
        return reverseBetween(n1.next, m + k, n + k, c, k);//递归调用继续反转后一区间链表
    }


发表于 2023-07-27 16:06:03 回复(0)
public ListNode reverseKGroup (ListNode head, int k) {
        ListNode tail=head;//tail为分组界限
        for(int i=0;i<k;i++){   //如果不足k个
            if(tail==null) return head;
            tail=tail.next;
        }
        //如果足k个,反转链表
        ListNode pre=null;
        ListNode cur=head;
        while(cur!=tail){//因为下一段的头是tail
            ListNode tmp=cur.next;
            cur.next=pre;
            pre=cur;
            cur=tmp;
        }
        head.next=reverseKGroup(tail,k);
        return pre;
    }

发表于 2023-07-19 09:41:24 回复(2)
import java.util.*;

/*   考虑时间复杂度O(n) 空间复杂度O(1)
 * public class ListNode {
 *   int val;
 *   ListNode next = null;
 *   public ListNode(int val) {
 *     this.val = val;
 *   }
 * }
 */

public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     *
     * @param head ListNode类
     * @param k int整型
     * @return ListNode类
     */
    public ListNode reverseKGroup (ListNode head, int k) {
        // write code here
        ListNode start = new ListNode(0);
        ListNode end = new ListNode(0);
        ListNode tmp = new ListNode(0);
        ListNode tmpStartNext = new ListNode(0);
        int length = 0;
        start = head;
        if(head==null)return head;//当传入为空
        //非空
        for (length = 0; true; length++) {
            if ((start.next) == null) {
                break;
            }
            start = start.next;
        }//length从0开始计数
 
        Boolean reverseYes = length+1>=k ;//数据长度够一次翻转
        start = new ListNode(0);
        for (int i = 0; true;) {//i是end节点所在的位置,也就是按要求排号的元素的位置
            //第一次开始,先让start做头节点
            if (i == 0) {
                end = head;
                start.next = end;
            }
            //判断是否需要反转,和是否元素还够一次反转
            if (k >= 2 && reverseYes) {
                tmp = end.next;
                tmpStartNext = start.next;
                start.next = tmp;
                end.next = tmp.next;
                tmp.next = tmpStartNext;
                i++;
            } else {
                break;
            }
            //翻转了k个元素
            if ((i+1)%k==0) {
                //判断这是第一反转,是的话需要把head重新指向链表头
                if (i+1==k) {
                    head = start.next;
                }
                start = end ;//这一轮翻转的最后一个元素是下一轮的头节点
                end = start.next;
                i++;
                //判断是否还有下一轮翻转
                reverseYes = length-i>=k ;
            }
        }
        return head;
    }
}
发表于 2023-07-18 21:25:57 回复(0)
按照轮询的压入栈,若轮询不够直接加到队尾部
import java.util.*;

/*
 * public class ListNode {
 *   int val;
 *   ListNode next = null;
 *   public ListNode(int val) {
 *     this.val = val;
 *   }
 * }
 */

public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param head ListNode类 
     * @param k int整型 
     * @return ListNode类
     */
   public static ListNode reverseKGroup(ListNode head, int k) {
        ListNode newHead = null;
        ListNode temp = null;
        ListNode L = null;
        // write code here
        a:while (head != null) {
            Stack<ListNode> stack = new Stack<ListNode>();
            temp = head;
            for (int i = 1; i <= k; i++) {
                if (head == null) {
                    if (L != null)
                        L.next = temp;
                    if (newHead == null) {
                        newHead = temp;
                    }
                    break a;
                }
                System.out.println(head.val);
                stack.push(head);
                head = head.next;
            }

            while (!stack.isEmpty()) {
                if (newHead == null) {
                    newHead = stack.pop();
                    L = newHead;
                } else {
                    L.next = stack.pop();
                    L = L.next;
                    L.next = null;
                }
            }

        }

        return newHead;
    }
}


发表于 2023-07-14 14:21:03 回复(0)
public ListNode reverseKGroup (ListNode head, int k) {
        // write code here
        if (head == null){
            return null;
        }
        //len记录链表长度
        int len = 0;
        //eg用于遍历链表
        ListNode eg = head;
        while (eg != null){
             len++;
             eg = eg.next;
        }
        if (len < k){
        //如果长度小于k,返回当前链表
            return head;
        }
        int num = len / k;
        //ListNode用于标记每一组的第一个节点
        ListNode headeg = head;
        //eg用于记录每一组翻转后的最后一个节点
        eg = head;
        for (int i = 1; i <= num; i++){
        //为每一组的翻转做准备工作
            ListNode eg0 = headeg;
            ListNode eg1 = headeg.next;
            headeg.next = null;
            int egi = k;
            while(egi - 1!= 0){
            //对每一组进行翻转
                egi--;
                ListNode eg2 = eg1.next;
                eg1.next = headeg;
                headeg = eg1;
                eg1 = eg2;
            }
            if (i == 1){
   //移动头节点,使其指向翻转后的第一个节点,只能在第一次翻转时执行一次
                head = headeg;
            }else{
       //连接翻转后的前一组与翻转后的当前组
                eg.next = headeg;
                eg = eg0;
            }
            //连接翻转后的当前组与下一组
            eg0.next = eg1;
            //使headeg始终指向下一组的头节点
            headeg = eg1;
        }
       return head;
    }

发表于 2023-04-18 17:23:18 回复(0)
import java.util.*;

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

public class Solution {
    /**
     *
     * @param head ListNode类
     * @param k int整型
     * @return ListNode类
     */
    public ListNode reverseKGroup (ListNode head, int k) {
        // write code here
        if (head == null || k == 1) {
            return head;
        }
        //加个哨兵节点
        ListNode node = new ListNode(0);
        node.next = head;
        head = node;

        ListNode l, h, r, start, last;
        start = head;   //  翻转序列的前一个
        l = head.next;
        h = head.next;  //  翻转后子序列的头结点
        r = h.next;     // 翻转后头结点的后一个结点
        int i;
        do {
            i = 0;
            for (; i < k -1 && r != null; i++) { //向后找k个翻转,并且数量够
                h = r;
                r = r.next;
                h.next = l;
                l = h;
            }
            if (i == k-1) { //数量够
                last = start.next;
                start.next.next = r;
                start.next = h;
                start = last;
                l = r;
                h = r;
                r = r != null?r.next:r;
            }else{  // 数量不够,恢复
                l = r;
                r = h.next;
                h.next = l;
                l = h;
                for(int j = 0; j < i-1; j++){
                    h = r;
                    r = r.next;
                    h.next = l;
                    l = h;
                }
                break;
            }
        } while (r != null);

        return head.next;
    }
}
发表于 2023-04-11 14:41:14 回复(0)
import java.util.*;

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

public class Solution {
    /**
     *
     * @param head ListNode类
     * @param k int整型
     * @return ListNode类
     */
    public ListNode reverseKGroup (ListNode head, int k) {
        // write code here\
        ListNode node = head;
        int size = 0;
        while (node != null) {
            size++;
            node = node.next;
        }
        ListNode temp = head;
        for (int i = 1; i + k - 1 < size; i = i + k) {
           temp = reverseBetween(temp, i, i+k-1);
        }
        if(size == k){
            temp = reverseBetween(temp, 1, k);
        }
        return temp;
    }

    // 反转指定区间节点
    public ListNode reverseBetween (ListNode head, int m, int n) {
        ListNode res = new ListNode(0);
        ListNode prestart = res;
        ListNode start = head;
        prestart.next = start;

        for (int i = 1; i < m; i++) {
            prestart = start;
            start = start.next;
        }

        // reverse
        for (int i = 0; i < n - m; i++) {
            ListNode node = start.next;
            start.next = node.next;
            node.next = prestart.next;
            prestart.next = node;
        }
        return res.next;
    }
}


发表于 2023-03-31 14:57:33 回复(0)