2017年亚马逊实习生招聘时的题目
问题描述:实现一个链表,反转后一半,如果链表长度是奇数,则从(N+1)/2开始反转;
想到的思路:
1、可以设置两个指示节点的标记,一个标记每次前进一个节点,一个每次前进两个节点,这样循环N/2次就可以找到中间节点,然后从这里开始链表反转;
2、直接设置一个数组,将链表拷贝入数组中,然后从头开始新建一个链表,将数组前半段按顺序拷贝到新链表,后半段反序拷贝。
java实现代码
链表结构
class Linked{
int node;
Linked next;
}
思路1代码
/**
* 将链表后一半反转
* @param head
* @return
*/
public static Linked halfReverse1(Linked head){
// 判断链表长度是否大于1
if(head.next!=null){
// 判断链表长度是否大于2
if(head.next.next!=null){
// step_1每次更新一步,step_1初始值为第一个节点
Linked step_1 = head.next;
// 初始值step_2指向step_1节点的后第2个节点
Linked step_2 = head.next.next.next;
while(step_2!=null){
// step_2每次向后更新两个节点
// step_2先向后跟新一个节点
step_2 = step_2.next;
// 判断是否为空
if(step_2!=null){
// 不为空step_2再向后更新一个节点
step_2 = step_2.next;
}else{
// 为空时跳出循环,此时step_1指的节点下一节点就是中间要开始反转的节点
break;
}
// step_1每次更新一步
step_1 = step_1.next;
}
// step_1后边节点实现反转
Linked l = step_1.next;
Linked previouseNode = null;
while(l!=null){
Linked nextNode = l.next;
l.next = previouseNode;
previouseNode = l;
l=nextNode;
}
step_1.next=previouseNode;
}
}
return head;
}
思路2代码
/**
* 实现链表后半段反转,借助数组,直接将链表所有内容拷贝到数组中,然后新建一个链表将数组前半段按顺序拷入链表,后半段反转拷入
*/
public static Linked halfReverse2(Linked head){
Linked l = head.next;
int[] a = new int[100];
int n = 0;
// 将链表所有数据按顺序拷贝入数组
while(l!=null){
a[n] = l.node;
l = l.next;
n++;
}
// 找到开始反转节点
int middle = n/2;
// 新建链表的表头
Linked h = new Linked();
Linked linked = null;
for(int i=0,k=1;i<n;i++){
if(i==0){
// 构建第一个节点
linked = new Linked();
linked.node = a[i];
h.next = linked;
}else if(i<middle){
// 构建不需要反转节点
Linked l1 = new Linked();
l1.node = a[i];
linked.next = l1;
linked = l1;
}else {
// 构建反转的节点
Linked l1 = new Linked();
l1.node = a[n-k];
k++;
linked.next = l1;
linked = l1;
}
}
return h;
}