2014年微软校园招聘笔试题最后编程题Reorder List

本文介绍了一种在O(1)空间复杂度下对单链表进行重组的算法,通过将链表一分为二、反转后半部分并交错合并两部分来达到目标。提供了完整的Java代码实现及运行结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.问题

Given a singly linked list L: (L0 , L1 , L2...Ln-1 , Ln). Write a program to reorder it so that it becomes(L0 , Ln , L1 , Ln-1 , L2 , Ln-2...).
struct Node  
{  
    int val_;  
    Node* next;  
};  
Notes:
1)Space Complexity should be O(1) 
2)Only the ".next" field of a node is modifiable.
该题目和LeetCode中的Reorder List 题目完全一样:
Given a singly linked list L: L0→L1→…→Ln-1→Ln,
reorder it to: L0→Ln→L1→Ln-1→L2→Ln-2→…
You must do this in-place without altering the nodes' values.

For example,
Given {1,2,3,4}, reorder it to {1,4,2,3}.

2.分析

如果采用空间复杂度为O(n)和时间复杂度为O(1)的方法解决Reorder List问题,主要分为以下三步:
1)将单链表分为前后两个链表;
2)逆序分开后的第二个链表;
3)再将前后链表合并成一个单链表。

3.程序实现


/*
 *@题目描述: Given a singly linked list L: L0→L1→…→Ln-1→Ln,
			reorder it to: L0→Ln→L1→Ln-1→L2→Ln-2→…
			You must do this in-place without altering the nodes' values.
			For example,
			Given {1,2,3,4}, reorder it to {1,4,2,3}.
*@问题分析:1.将链表分成两部分;
*			2.将第二个链表逆转;
*			3.将两个链表合并。
 */
//链表的数据结构
class ListNode{
	ListNode next;
	int val;
	public ListNode(int val) {
		// TODO Auto-generated constructor stub
		this.val=val;
		next=null;
	}
}

public class ReorderList {
	public static ListNode reverseList(ListNode head){
		if(head==null || head.next==null)
			return head;
		ListNode preNode=head;
		ListNode currNode=head.next;
		while(currNode!=null){
			ListNode tempNode=currNode.next;
			currNode.next=preNode;
			preNode=currNode;
			currNode=tempNode;
		}
		head.next=null;
		return preNode;
	}
	public static void  reorderList(ListNode head){
		if(head!=null && head.next!=null){
			//将两个链表从中间分为两个链表
			ListNode slowNode=head;
			ListNode fastNode=head;
			while(fastNode!=null&&fastNode.next!=null&&fastNode.next.next!=null){
				slowNode=slowNode.next;
				fastNode=fastNode.next.next;
			}
			ListNode secondListHead=slowNode.next;
			slowNode.next=null;
			//逆转第二个链表
			secondListHead=reverseList(secondListHead);
			ListNode pHead1=head;
			ListNode pHead2=secondListHead;
			//合并两个分开的链表
			while(pHead2!=null){
				ListNode pTempNode1=pHead1.next;
				ListNode pTempNode2=pHead2.next;
				pHead1.next=pHead2;
				pHead2.next=pTempNode1;
				pHead1=pTempNode1;
				pHead2=pTempNode2;
			}
		}
	}
	public static void printListInfo(ListNode head){
		System.out.println("*****开始分隔符*****");
		while(head!=null){
			System.out.print(head.val);
			head=head.next;
		}
		System.out.println("\n*****结束分隔符*****");
	}
	public static void main(String args[]){
		ListNode listHead=new ListNode(3);
		ListNode listNode1=new ListNode(4);
		ListNode listNode2=new ListNode(5);
		ListNode listNode3=new ListNode(6);
		ListNode listNode4=new ListNode(7);
		listHead.next=listNode1;
		listNode1.next=listNode2;
		listNode2.next=listNode3;
		listNode3.next=listNode4;
		System.out.println("Before Reorder list: ");
		printListInfo(listHead);
		reorderList(listHead);
		System.out.println("after Reorder List:");
		printListInfo(listHead);
	}
}

运行结果如下:
Before Reorder list: 
*****开始分隔符*****
34567
*****结束分隔符*****
after Reorder List:
*****开始分隔符*****
37465
*****结束分隔符*****


 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值