首页 > 试题广场 >

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

[编程题]按照左右半区的方式重新组合单链表
  • 热度指数:1881 时间限制:C/C++ 3秒,其他语言6秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
给定一个单链表的头部节点 head,链表长度为 N,如果 N 是偶数,那么前 N / 2 个节点算作左半区,后 N / 2 个节点算作右半区;如果 N 为奇数,那么前 N / 2 个节点算作左半区,后 N / 2 + 1个节点算作右半区。左半区从左到右依次记为 L1->L2->...,右半区从左到右依次记为 R1->R2->...,请将单链表调整成 L1->R1->L2->R2->... 的形式。

输入描述:
单链表的头节点 head。


输出描述:
在给定的函数内返回链表的头指针。
示例1

输入

6
1 2 3 4 5 6

输出

1 4 2 5 3 6

备注:
保证链表的长度不大于1000000

1、思路

  • 找到单链表中点,将单链表分成两段;

  • 两条链表交叉合成一条新链表。

2、代码

list_node * findMid(list_node * head)   //取得单链表的中间节点,并保证后半部分长度大于等于前半部分
{
    auto fast = head->next, slow = head;

    while (fast->next != nullptr && fast->next->next != nullptr)
    {
        fast = fast->next->next;
        slow = slow->next;
    }

    return slow;
}

list_node * relocate(list_node * head)
{
    if (head == nullptr || head->next == nullptr) return head;

    auto mid = findMid(head);
    auto list1 = head, list2 = mid->next;
    mid->next = nullptr;        //断尾,切断list1尾部与list2头部的连接

    list_node *dummy = new list_node();
    auto *p = dummy;

    while (list1 != nullptr)    //list2的长度一定大于等于list1,故只需要判断list1即可
    {
        p = p->next = list1;    //交叉操作
        list1 = list1->next;

        p = p->next = list2;
        list2 = list2->next;
    }

    if (list2 != nullptr) p->next = list2;

    return dummy->next;
}
发表于 2022-05-14 13:55:29 回复(0)
用快慢指针的方式找到链表的中点,然后将链表断为左右两个子链,在遍历子链时交替输出节点值就好
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;

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

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int n = Integer.parseInt(br.readLine().trim());
        String[] strList = br.readLine().trim().split(" ");
        ListNode head = new ListNode(Integer.parseInt(strList[0]));
        ListNode cur = head;
        for(int i = 1; i < n; i++){
            cur.next = new ListNode(Integer.parseInt(strList[i]));
            cur = cur.next;
        }
        ListNode fast = head;
        ListNode prev = new ListNode(-1);
        ListNode slow = head;
        prev.next = slow;
        while(fast != null && fast.next != null){
            fast = fast.next.next;
            prev = prev.next;
            slow = slow.next;
        }
        prev.next = null;           //把左半区和右半区断开
        ListNode left = head;
        ListNode right = slow;
        int cursor = 0;
        // 交替输出左右半区的节点值
        while(left != null && right != null){
            if(cursor % 2 == 0){
                System.out.print(left.val + " ");
                left = left.next;
            }else{
                System.out.print(right.val + " ");
                right = right.next;
            }
            cursor ++;
        }
        while(left != null){
            System.out.print(left.val + " ");
            left = left.next;
        }
        while(right != null){
            System.out.print(right.val + " ");
            right = right.next;
        }
    }
}

发表于 2021-06-08 14:57:21 回复(0)
import java.util.Scanner;

public class Main {

    public static class Node {
        public int val;
        public Node next;
        Node() {}
        Node(int val, Node next) {
            this.val = val;
            this.next = next;
        }
    }

    public static Node reConstructList(Node head) {
        if (head == null || head.next == null) return head;
        Node p1 = head, p2 = head;
        while (p2.next != null && p2.next.next != null) {
            p1 = p1.next;
            p2 = p2.next.next;
        }
        p2 = p1.next;
        p1 = head.next;
        Node mid = p2;
        Node resHead = new Node();
        Node p3 = resHead;
        boolean flag = true;
        while (p1 != mid || p2 != null) {
            if (flag && p1 != mid) {
                p3.next = p1;
                p3 = p1;
                p1 = p1.next;
            } else {
                p3.next = p2;
                p3 = p2;
                p2 = p2.next;
            }
            flag = !flag;
        }
        return resHead;
    }

    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        int n = input.nextInt();
        Node head = new Node();
        Node p = head;
        for (int i = 0; i < n; i++) {
            int val = input.nextInt();
            Node node = new Node(val, null);
            p.next = node;
            p = node;
        }
        p = reConstructList(head).next;
        while (p != null) {
            System.out.print(p.val + " ");
            p = p.next;
        }
    }
}

发表于 2020-08-06 09:36:04 回复(0)
先找到中点,然后断链,然后按顺序merge两个链表。
list_node * relocate(list_node * head)
{
    //////在下面完成代码
    if(head == NULL || head->next == NULL) return head;
    list_node * pre = head;
    list_node * cur = head;
    list_node * preMid = NULL;
    while(cur && cur->next){
        preMid = pre;
        pre = pre->next;
        cur = cur->next->next;
    }
    preMid->next = NULL; //断开链表
    cur = head;
    list_node * dummy = new list_node();
    list_node * preNode = dummy;
    int flag = 0;
    while(pre && cur){
        if(flag == 0){
            preNode->next = cur;
            cur = cur->next;
            flag = 1;
        }else{
            preNode->next = pre;
            pre = pre->next;
            flag = 0;
        }
        preNode = preNode->next;
    }
    preNode->next = pre ? pre : cur;
    return dummy->next;
}


发表于 2020-08-05 15:34:17 回复(0)
既然牛客只给了数组,又想让咱练习链表和树的题。那么咱就要有一套输入输出的模板,让思路聚焦在如何解题上。分享下我读入链表和输出链表的模板和使用样例。
class Node {
    int val;
    Node next;

    Node(int val) {
        this.val = val;
    }
}

    /*

    private static Node input(Scanner sc, int n) {
        Node head = null, p = null;
        while(n-- > 0) {
            if (head == null) {
                head = p = new Node(sc.nextInt());
            } else {
                p.next = new Node(sc.nextInt());
                p = p.next;
            }
        }
        return head;
    }

    private static void output(Node head) {
        Node p = head;
        StringBuilder cache = new StringBuilder();
        while(p != null) {
            cache.append(p.val).append(" ");
            p = p.next;
        }
        if (cache.length() > 0) {
            cache.deleteCharAt(cache.length() - 1);
        }
        System.out.println(cache);
    }
     */
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        Node head = input(sc, n);
        head = merge(head);
        output(head);
    }

    static Node merge(Node head) {
        if (head == null || head.next == null) return head;
        Node fast = head, slow = head;
        Node pre = null;
        while(fast != null) {
            fast = fast.next;
            if (fast != null) {
                fast = fast.next;
                pre = slow;
                slow = slow.next;
            }
        }
        if (pre != null) {
            pre.next = null;
        }
        Node p = head, q = slow, next = null;
        while(p != null) {
            pre = q;
            next = q.next;
            q.next = p.next;
            p.next = q;
            p = q.next;
            q = next;
        }
        pre.next = q;
        return head;
    }

    private static Node input(Scanner sc, int n) {
        Node head = null, p = null;
        while(n-- > 0) {
            if (head == null) {
                head = p = new Node(sc.nextInt());
            } else {
                p.next = new Node(sc.nextInt());
                p = p.next;
            }
        }
        return head;
    }

    private static void output(Node head) {
        Node p = head;
        StringBuilder cache = new StringBuilder();
        while(p != null) {
            cache.append(p.val).append(" ");
            p = p.next;
        }
        if (cache.length() > 0) {
            cache.deleteCharAt(cache.length() - 1);
        }
        System.out.println(cache);
    }

}



发表于 2021-08-14 20:34:00 回复(0)
n=int(input())
number_list=list(map(int,input().split()))
#分左右区
left_list=number_list[:n//2]
right_list=number_list[n//2:]
ans=[]
for i in range(len(left_list)):
    ans.append(left_list[i])
    ans.append(right_list[i])
#多了一个元素
if n%2!=0:
    ans.append(right_list[-1])
print(' '.join(map(str,ans)))

发表于 2021-07-13 10:58:51 回复(0)
快慢指针 + 链表合并
list_node * relocate(list_node * head)
{
    //////在下面完成代码
    if(!head||!head->next) return head;
    list_node *s=head,*f=head;
    while(f&&f->next){
        f=f->next->next;
        s=s->next;
    }
    list_node *l=head,*r=s,*pre=head,*next; //pre不用设置dummy节点,在循环时自动更正
    while(l!=s){        //等于右半区起点s时结束
        next=l->next;
        pre->next=l;
        l->next=r;
        l=next;
        pre=r;
        r=r->next;
    }
    return head;
}
发表于 2021-06-16 16:41:29 回复(0)
// 思路不是很难,难的就是指针的指向,有时候容易导致越界
# include <bits/stdc++.h>
using namespace std;

struct list_node{
    int val;
    struct list_node * next;
};


list_node * input_list(int* p)
{
    int n, val;
    list_node * phead = new list_node();
    list_node * cur_pnode = phead;
    scanf("%d", &n);
    *p = n;
    for (int i = 1; i <= n; ++i) {
        scanf("%d", &val);
        if (i == 1) {
            cur_pnode->val = val;
            cur_pnode->next = NULL;
        }
        else {
            list_node * new_pnode = new list_node();
            new_pnode->val = val;
            new_pnode->next = NULL;
            cur_pnode->next = new_pnode;
            cur_pnode = new_pnode;
        }
    }
    return phead;
}


list_node * relocate(list_node * head,int len)
{
    //////在下面完成代码
    if(head == nullptr || head->next == nullptr || head->next->next == nullptr){
        return head;
    }

    int temp = len/2;
    list_node * ans = head;
    list_node* p1 = head;
    list_node* p2 = head;
    list_node* p3 = p1->next;
    // 找到中间位置
    while(temp--){
        p2 = p2->next;
    }
    list_node* p5 = p2; // 后期作为判断循环退出条件
    list_node* p4 = p2->next;
    int time = len/2;
    while(time--){
        p1->next = p2;
        p1 = p3;
        p3 = p3->next;
        
        if(p1 == p5)break;
        if(p2->next != nullptr){
            p2 -> next = p1;
        }
        p2 = p4;
        if(p4 != nullptr){
            p4 = p4->next;
        }
    }
    return ans;

}


void print_list(list_node * head)
{
    while (head != NULL) {
        printf("%d ", head->val);
        head = head->next;
    }
    puts("");
}


int main ()
{   
    int len = 0;
    int* p = &len;
    list_node * head = input_list(p);
    list_node * new_head = relocate(head,len);
    print_list(new_head);
    return 0;
}

发表于 2020-07-07 22:35:41 回复(0)
import java.io.*;

public class Main {
    static int n;

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
        n = Integer.parseInt(br.readLine());
        Node h1 = new Node(-1);
        Node p = h1;
        String[] s1 = br.readLine().split(" ");
        for (int i = 0; i < n; i++) {
            p.next = new Node(Integer.parseInt(s1[i]));
            p = p.next;
        }
        h1 = h1.next;//真实头结点

        Node h = solve(h1);
        while (h != null) {
            bw.write(h.val + " ");
            h = h.next;
        }
        bw.flush();
        bw.newLine();
    }

    private static Node solve(Node h) {
        Node hh = new Node(-1);//虚拟头结点
        Node p = hh;//游走指针
        Node l = h, r = h, pre = null;//pre是r的前驱
        int cnt = 1;//计数器,是奇数就连左半区
        for (int i = 0; i < n / 2; i++) {
            pre = r;
            r = r.next;
        }
        pre.next = null;//此时pre是左半区的尾节点
        while (l != null) {
            if (cnt % 2 == 1) {
                p.next = l;
                l = l.next;
            } else {
                p.next = r;
                r = r.next;
            }
            p = p.next;
            cnt++;
        }//还有右半区的最后1个或2个节点没处理
        //直接连起来即可
        if (r != null) pre.next = r;
        return hh.next;
    }
}
class Node {
    int val;
    Node next;

    public Node(int val) {
        this.val = val;
    }
}
编辑于 2020-07-04 09:33:39 回复(0)
list_node * relocate(list_node * head)
{
    //////在下面完成代码
    list_node *l,*f,*temp;
    list_node *new_head = new list_node();
    list_node *cur = new_head;
    l = f = head;
    while(f->next && f->next->next){
        l = l->next;
        f = f->next->next;
    }
    f = head;
    if(n % 2 == 0) l = l->next;// 如果是偶数,l在中间左边,为了让在右边,向前进一个单位
    list_node *tag = l;
    int i = 1;
    //因为左半区插入先行,当f == tag,实际上与之对应的右半区第N/2个节点
    //还没有插入,所以加了个i的判断
    while(1){
        if(f == tag && i%2 == 1) break;
        if(i % 2 == 1){
            temp = f;
            f = f->next;
            temp->next = cur->next;
            cur->next = temp;
        }
        if(i % 2 == 0){
            temp = l;
            l = l->next;
            temp->next = cur->next;
            cur->next = temp;
        }
        cur = cur->next;
        i++;
    }
    if(l != NULL){
        cur->next = l;
    }
    return new_head->next;
}

发表于 2020-07-02 16:02:56 回复(0)
这题似乎不用链表啊啊啊啊啊,主要输入看不太懂,链表的话就双指针,1个n1个n*2,这样只要遍历一次
发表于 2020-06-13 17:17:31 回复(0)
import java.util.Scanner;
public class Main{
    static class ListNode{
        int data;
        ListNode next;
        public ListNode(int data){
            this.data = data;
            this.next = null;
        }
    }
    public static void printList(ListNode list){
        ListNode ref = list;
        if(ref == null){
            System.out.println();
            return;
        }
        StringBuilder result = new StringBuilder("");
        while(ref != null){//优化printList之后,测试用例直接从75% ->100%成功跑过所有测试用例
            result.append(ref.data).append(" ");
            //System.out.print( ref.data + " ");
            ref = ref.next;
        }
        System.out.println(result.toString());
    }
    public static ListNode refactorLinkedList(ListNode list){
        if(list == null || list.next == null || list.next.next == null){
            return list;
        }
        ListNode leftSection = list;
        ListNode rightSection = list;
        ListNode slow = list;
        ListNode fast = list;
        ListNode rear = null;
        while(fast != null && fast.next != null){
            rear = slow;
            slow = slow.next;
            fast = fast.next.next;
        }
        rear.next = null;
        rightSection = slow;
        ListNode temp;
        while(leftSection.next != null){
            temp = leftSection.next;
            leftSection.next = rightSection;
            rightSection = rightSection.next;//
            leftSection.next.next = temp;
            leftSection = temp;
        }
        leftSection.next = rightSection;
        return list;
    }
    public static void main(String[] args){
        ListNode list = null;
        ListNode tail = null;
        Scanner scanner = new Scanner(System.in);
        int num = Integer.parseInt(scanner.nextLine());
        String input = scanner.nextLine();
        String[] para = input.split("\\p{javaWhitespace}+");
        ListNode node = new ListNode(Integer.parseInt(para[0]));
        list = node;
        tail = node;
        for(int i = 1; i < num; i++){//优化初始化单链表的代码之后,测试用例从25 pecrcent -> 75 percent.
            node = new ListNode(Integer.parseInt(para[i]));
            tail.next = node;
            tail = node;
        }
        list =refactorLinkedList(list);
        printList(list);
        scanner.close();
    }
}

发表于 2020-04-07 13:34:56 回复(0)
# include <bits/stdc++.h>
using namespace std;

struct list_node{
    int val;
    struct list_node * next;
};


list_node * input_list(void)
{
    int n, val;
    list_node * phead = new list_node();
    list_node * cur_pnode = phead;
    scanf("%d", &n);
    for (int i = 1; i <= n; ++i) {
        scanf("%d", &val);
        if (i == 1) {
            cur_pnode->val = val;
            cur_pnode->next = NULL;
        }
        else {
            list_node * new_pnode = new list_node();
            new_pnode->val = val;
            new_pnode->next = NULL;
            cur_pnode->next = new_pnode;
            cur_pnode = new_pnode;
        }
    }
    return phead;
}


list_node * relocate(list_node * head)                   //占用内存70M.......
{
    //////在下面完成代码
    int i=0,flag=0;
    list_node *new_head,*head1,*head2,*head3,*first;
    new_head=new list_node();
    head1=new list_node();
    head2=new list_node();
    head3=new list_node();
    first=new list_node();
    new_head=head;
    while(head!=NULL)
    {
        flag++;
        head=head->next;
    }
    head=new_head;
    head3->val=0;
    head3->next=NULL;
    first=head3;
    if(flag%2==0)
    {
        for(i=0;i<flag/2;i++)
        {
            head=head->next;
        }
        head2=head;
        head1=new_head;
        head=new_head;
        for(i=0;i<flag/2;i++)
        {
            list_node *temp1=new list_node();
            temp1->val=head1->val;
            temp1->next=NULL;
            head3->next=temp1;
            head3=head3->next;
            list_node * temp2=new list_node();
            temp2->val=head2->val;
            temp2->next=NULL;
            head3->next=temp2;
            head3=head3->next;
            head1=head1->next;
            head2=head2->next;
        }
    }
    else if(flag%2!=0)
    {
        for(i=0;i<flag/2;i++)
        {
            head=head->next;
        }
        head2=head;
        head1=new_head;
        head=new_head;
        for(i=0;i<flag/2;i++)
        {
            list_node *temp1=new list_node();
            temp1->val=head1->val;
            temp1->next=NULL;
            head3->next=temp1;
            head3=head3->next;
            list_node *temp2=new list_node();
            temp2->val=head2->val;
            temp2->next=NULL;
            head3->next=temp2;
            head3=head3->next;
            head1=head1->next;
            head2=head2->next;
        }
        head3->next=head2;
    }
    first=first->next;
    return first;
}


void print_list(list_node * head)
{
    while (head != NULL) {
        printf("%d ", head->val);
        head = head->next;
    }
    puts("");
}


int main ()
{
    list_node * head = input_list();
    list_node * new_head = relocate(head);
    print_list(new_head);
    return 0;
}

发表于 2020-03-27 14:30:32 回复(0)
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Main {

    public static class Node {

        public int value;
        public Node next;

        public Node(int value) {
            this.value = value;
        }
    }
    
    public static Node listGenerator(int length, String[] numbers) {
        Node head = new Node(Integer.parseInt(numbers[0]));
        Node cur = head;
        for (int i = 1; i < length; i++) {
            cur.next = new Node(Integer.parseInt(numbers[i]));
            cur = cur.next;
        }
        cur.next = null;
        return head;
    }
    
    public static void printList(Node head) {
        while (head != null) {
            System.out.print(head.value +" ");
            head = head.next;
        }
        System.out.println();
    }
    
    public static void relocate(Node head) {
        if (head == null || head.next == null) {
            return;
        }
        Node fast = head.next;
        Node slow = head;
        while (fast.next != null && fast.next.next != null) {
            fast = fast.next.next;
            slow = slow.next;
        }
        fast = slow.next;
        slow.next = null;
        mergeLR(head, fast);
    }

    private static void mergeLR(Node left, Node right) {
        Node next;
        while (left.next != null) {
            next = left.next;
            left.next = right;
            right = right.next;
            left.next.next = next;
            left = next;
        }
        left.next = right;
    }

    public static void main(String[] args) throws IOException {
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
        int n = Integer.parseInt(bufferedReader.readLine());
        String[] numbers = bufferedReader.readLine().split(" ");
        Node head = listGenerator(n, numbers);
        relocate(head);
        printList(head);
    }
}

发表于 2020-02-16 17:53:49 回复(0)
题目有点问题,N为奇数时,测试用例是把前 N / 2看做算作左半区,后N/2+1作为右区域。
# include <iostream>
#include <stdio.h>
#pragma warning( disable : 4996)
using namespace std;

struct list_node{
    int val;
    struct list_node * next;
};


list_node * input_list(int n)
{
    int val;
    list_node * phead = new list_node();
    list_node * cur_pnode = phead;
    
    for (int i = 1; i <= n; ++i)
    {
        scanf("%d", &val);
        if (i == 1)
        {
            cur_pnode->val = val;
            cur_pnode->next = NULL;
        }
        else
        {
            list_node * new_pnode = new list_node();
            new_pnode->val = val;
            new_pnode->next = NULL;
            cur_pnode->next = new_pnode;
            cur_pnode = new_pnode;
        }
    }
    return phead;
}


list_node * relocate(list_node * head,int N)
{
    list_node *p1 = head;
    list_node *p2 = head;
    list_node *p = head;
    
    int idx = 1;
    int lenl = N  / 2;
    while (lenl>1)
    {
        p = p->next;
        lenl --;
    }
    p2 = p->next;
    p->next = NULL;

    while ((p1->next)&&(p2->next))
    {
        list_node *pp1, *pp2;
        pp1 = p1->next;
        pp2 = p2->next;
        p1->next = p2;
        p2->next = pp1;
        p1 = pp1;
        p2 = pp2; 
    }
        p1->next = p2;        
    return head;
}


void print_list1(list_node * head)
{
    while (head != NULL)
    {
        printf("%d ", head->val);
        head = head->next;
    }
    puts("");
}


int main()
{
    int N;
    cin >> N;
    list_node * head = input_list(N);
    list_node * new_head = relocate(head,N);
    print_list1(new_head);
    return 0;
}


如果按题目应为:
list_node * relocate(list_node * head,int N)
{
    list_node *p1 = head;
    list_node *p2 = head;
    list_node *p = head;
    
    int idx = 1;
    int lenl = (N + 1) / 2;
    while (lenl>1)
    {
        p = p->next;
        lenl --;
    }
    p2 = p->next;
    p->next = NULL;

    while (p1&&p2)
    {
        list_node *pp1, *pp2;
        pp1 = p1->next;
        pp2 = p2->next;
        p1->next = p2;
        p2->next = pp1;
        p1 = pp1;
        p2 = pp2; 
    }
    return head;
}

发表于 2019-10-23 15:00:49 回复(0)

问题信息

上传者:小小
难度:
15条回答 2573浏览

热门推荐

通过挑战的用户

查看代码