《程序员代码面试指南》按照左右半区的方式重新组合单链表——java实现

本文探讨了一种链表重构算法,通过将链表分为左右半区并进行重组,实现特定的元素排列。文章提供了两种实现思路,一种是借助数组进行元素位置变换,另一种是使用快慢指针技巧直接在链表上操作。代码示例清晰地展示了如何在不同长度的链表上应用此算法。
摘要由CSDN通过智能技术生成

按照左右半区的方式重新组合单链表

题目描述:

给定一个链表list,
如果:
list = 1 调整之后1。
list = 1->2->3 调整之后1->2->3
list = 1->2->3->4 调整之后1->3->2->4
list = 1->2->3->4->5->6 调整之后1->4->2->5->3->6
list = 1->2->3->4->5->6->7 调整之后1->4->2->5->3->6->7
根据上面的规律,调整一个任意长度的链表。

题目难度:
medium

题目思路:

思路一:
对于链表相关的题目,第一想法应该是,把链表元素存入到数组中,然后再用一个新的help数组来记录,变化之后的每个位置的元素。最后把help数组中的元素一次串成新的链表。
思路二:
采用快慢指针的方式记录从哪个位置开始,之后的节点需要插入到之前的节点。然后再用链表指针变换的方式记录新组合的新的链表。

代码实现:

思路一:

public static Node changeList1(Node head) {
        if (head == null || head.next == null || head.next.next == null) {
            return head;
        }
        Node cur = head;
        Node last = null;   //用来记录奇数个时的最后一个节点
        int size = 0;
        while (cur != null) {
            size++;
            last = cur;     //最后一个节点
            cur = cur.next;
        }
        Node[] arr = new Node[(size & 1) == 0 ? size : size - 1]; //记录偶数个节点
        cur = head;
        for (int i = 0; i < arr.length; i++) {
            arr[i] = cur;       //链表的每个节点都存入到数组中
            cur = cur.next;
        }
        Node[] help = new Node[arr.length]; //把数组中的每个节点按照题目变换位置
        for (int i = 0; i < help.length; i++){
            if (i < help.length/2){
                help[2*i] = arr[i];
            }else {
                help[(i-help.length/2)*2+1] = arr[i];
            }
        }
        int i =1;
        while (i < help.length){  
           help[i-1].next = help[i];  //将数组中的元素转为链表
           i++;
        }
        if ((size & 1)!= 0){
            help[help.length - 1] .next = last;
        }
        return help[0];   //返回链表头结点
    }

思路二:

public static Node changeList2(Node head){
        if (head == null || head.next == null || head.next.next == null){
            return head;
        }
        Node mid = head;        //慢指针
        Node right = head.next;  //快指针
        while (right.next != null && right.next.next != null){
            mid = mid.next;
            right = right.next.next;
        }
        right = mid.next; //需要重新插入的头结点
        mid.next = null;  //中间尾节点指向空
        mergeRL(head,right);  //合并前后两个节点
        return head;
    }

    private static void mergeRL(Node left, Node right) {
        Node next = null;
        while (left.next != null){
            next = right.next;
            right.next = left.next;
            left.next = right;
            left = right.next;
            right = next;
        }
        left.next = right;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值