public class LinkModify {
/**
* 问题描述:2014 Microsoft 校招最后一题:
* 给定一个单链表L (L0,L1,L2,...,Ln)要求将其变化为 L(L0,Ln,L1,Ln-1,L2,Ln-2,...),同时要求空间复杂度为O(1)并且只允许修改next域;
* 思路:这道题本质上就是将一个链表的后半部分的每一个节点依次按倒序插入到链表的前半部分相邻两元素之间,因此可以将过程分解为如下几个步骤:
* 1.确定需要移动的链表段的起始节点
* 1.1 扫描链表,得到所有的节点数目length;O(N)
* 1.2 用length/2得到链表的中间节点,则中间节点的下一个节点即为需要移动部分的起始节点;
* 1.3 再次遍历链表,分别用指针指向这些关键节点;O(N/2)
* 2. 逆序链表的后半部分。并将逆序后的部分拼接至原链表上。O(N/2);
* 3. 从需要移动的起始节点开始遍历,将后半部分的节点一个个的插入前半部分的制定位置。O(N/2)
* @author wangwei;
* @since 2014/09/29
*/
public static class Node{
public int data;
public Node next;
public Node(int data){
this.data=data;
this.next=null;
}
}
public Node head;
public LinkModify(int[] list){
head=new Node(list[0]);
Node now=head;
for(int i=1;i<list.length;i++){
Node one=new Node(list[i]);
now.next=one;
now=one;
}
}
public void Modify(){
//count the number of all nodes;
Node now=head;
int length=0;
while(now!=null){
length++;
now=now.next;
}
now=head;
//find the mid point;
int mid=length/2;
Node nd_end;
int i=0;
while(i<mid){
now=now.next;
i++;
}
nd_end=now;
//reverse the part behind mid point
Node parent=null;
Node start=nd_end.next;
Node after;
while(start!=null){
after=start.next;
start.next=parent;
parent=start;
start=after;
};
nd_end.next=parent;
//insert each node after mid point into front part;
Node before=head;
Node runner=nd_end.next;
while(runner!=null){
nd_end.next=runner.next;
runner.next=before.next;
before.next=runner;
before=runner.next;
runner=nd_end.next;
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] list={1,2,3,4,5,6,7,8,9,0};
LinkModify lm=new LinkModify(list);
lm.Modify();
Node head=lm.head;
while(head!=null){
System.out.println(head.data);
head=head.next;
}
}
}
链表之调整顺序
最新推荐文章于 2024-12-30 20:28:19 发布