0
class Solution {
public:
void reorderList(ListNode *head) {
ListNode *tail=head;
ListNode *p=head;
ListNode *uptail;
if(head==NULL)
return;
else
{
while(p->next!=NULL)
{
uptail=p;
p=p->next;
}
tail=p;
}
if(tail!=head&&tail!=(head->next))
{
tail->next=head->next;
head->next=tail;
uptail->next=NULL;
if(head->next->next->next!=NULL)
reorderList(head->next->next);
}
// else return;
}
};
发表于 2016-08-28 18:52:13
回复(0)
更多回答
41
public class Solution {
public void reorderList(ListNode head) {
if(head == null || head.next == null)
return;
// 快满指针找到中间节点
ListNode fast = head;
ListNode slow = head;
while(fast.next != null && fast.next.next != null){
fast = fast.next.next;
slow = slow.next;
}
// 拆分链表,并反转中间节点之后的链表
ListNode after = slow.next;
slow.next = null;
ListNode pre = null;
while(after != null){
ListNode temp = after.next;
after.next = pre;
pre = after;
after = temp;
}
// 合并两个链表
ListNode first = head;
after = pre;
while(first != null && after != null){
ListNode ftemp = first.next;
ListNode aftemp = after.next;
first.next = after;
first = ftemp;
after.next = first;
after = aftemp;
}
}
}
发表于 2017-05-23 22:23:33
回复(21)
32
//快慢指针找到中间节点,将后面的链表反转(前插法),合并链表
//另:题目要求是就地解决,应该是不能用辅助栈之类的吧
public class Solution {
public void reorderList(ListNode head) {
if(head==null)
return;
ListNode slow=head;
ListNode fast=head;
while(fast.next!=null&&fast.next.next!=null){
fast=fast.next.next;
slow=slow.next;
}
ListNode pre=slow.next;
if(pre!=null&&pre.next!=null){
ListNode nex=pre.next;
while(nex!=null){
pre.next=nex.next;
nex.next=slow.next;
slow.next=nex;
nex=pre.next;
}
}
merge(head,slow);
}
public void merge(ListNode head,ListNode slow){
ListNode p=head;
ListNode q=slow.next;
while(q!=null&&p!=null){
slow.next=q.next;
q.next=p.next;
p.next=q;
q=slow.next;
p=p.next.next;
}
}
}
发表于 2016-06-16 10:42:19
回复(21)
11
public class Solution {
public void reorderList(ListNode head) {
ListNode rear=head;
ListNode tmp;
while(head!=null&&head.next!=null){
while(rear.next.next!=null){
rear=rear.next;
}
tmp=rear.next;
rear.next=null;
tmp.next=head.next;
head.next=tmp;
head=rear=tmp.next;
}
}
}
编辑于 2017-03-26 00:31:17
回复(7)
6
看大家思路都不错。。
我这个思路很朴素
复制一个链表然后逆序
在正序链表和逆序链表中按顺序各挑选一个 直到够数为止 class Solution {
public:
static ListNode* reverse(ListNode* pHead){//链表逆序
if(!pHead) return pHead;
ListNode* last = pHead, *nex = pHead->next, *cur = nex;
last->next = NULL;
while(cur){
nex = cur->next;
cur->next = last;
last = cur;
cur = nex;
}
return last;
}
static ListNode* copy(ListNode* pHead) {//复制链表
ListNode* copylist = new ListNode(0);
ListNode* p = pHead;
ListNode* copyhead = copylist;
while(p) {
ListNode* s = new ListNode(p->val);
copyhead->next=s;
copyhead=s;
p=p->next;
}
copyhead->next = NULL; //链表结尾必须置为NULL
return copylist->next;
}
void reorderList(ListNode *head) {
if(!head || !head->next) return;
ListNode* copylist = copy(head);
ListNode* rev = reverse(copylist);
ListNode* cnt_p = head;
int cnt = 0;
while(cnt_p){cnt++;cnt_p = cnt_p->next;}
ListNode* cur = new ListNode(-1);
cur->next = head;
ListNode* seq = head;
while(1){
ListNode* tmp1 = seq; seq = seq->next;
ListNode* tmp2 = rev; rev = rev->next;
cur->next = tmp1;
cur = cur->next;
cnt--; if(cnt==0) {cur->next=NULL;break;}
cur->next = tmp2;
cur = cur->next;
cnt--; if(cnt==0) {cur->next=NULL;break;}
}
}
};
编辑于 2019-04-09 16:05:02
回复(1)
3
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
用双端队列就行了。。头拿一个,尾拿一个。O(N)时间,O(1)空间
*/
class Solution {
public:
void reorderList(ListNode *head) {
deque ques;
auto tmp = head;
while(tmp != nullptr){
ques.push_back(tmp);
tmp = tmp->next;
}
ListNode nhead(0);
ListNode * ntail = &nhead;
while(!ques.empty()){
auto h = ques.front();
auto t = ques.back();
if(h == t){//只有一个元素了。
ques.pop_front();
h->next = nullptr;
ntail->next = h;
}else{
ques.pop_front();
ques.pop_back();
h->next = t;
t->next = nullptr;
ntail->next = h;
ntail = t;
}
}
head = nhead.next;
}
};
发表于 2019-08-06 23:25:09
回复(0)
3
/**
* 通过快慢指针找到中间节点,拆分链表为两部分,将后半部分链表翻转,然后合并两部分
*
* @param head
*/
public void reorderList(ListNode head) {
if (head == null || head.next == null) {
return;
}
//快慢指针找到中间节点
ListNode slow = head, fast = head, temp = null;
while (fast.next != null && fast.next.next != null) {
slow = slow.next;
fast = fast.next.next;
}
//拆分链表为两部分
temp = slow.next;
slow.next = null;
slow = temp;
//后半边进行头插法,翻转链表
ListNode node = slow.next;
slow.next = null;
while (node != null) {
temp = node.next;
node.next = slow;
slow = node;
node = temp;
}
//合并链表
merge(head, slow);
}
public void merge(ListNode head1, ListNode head2) {
ListNode p = head1, q = head2, temp;
while (p != null && q != null) {
temp = p.next;
p.next = q;
p = temp;
temp = q.next;
q.next = p;
q = temp;
}
}
编辑于 2018-03-18 01:25:06
回复(0)
5
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
void reorderList(ListNode *head) {
if(head == NULL || head->next == NULL || head->next->next == NULL)
return;
//快慢指针找中点
ListNode* fast = head;
ListNode* low = head;
while(fast->next != NULL && fast->next->next != NULL){
fast = fast->next->next;
low = low->next;
}
//对low后面的部分逆序
fast = low->next;
low->next = NULL;
while(fast != NULL){
ListNode* temp = fast->next;
fast->next = low->next;
low->next = fast;
fast = temp;
}
//合并low前面和后面两部分
ListNode* p = head;
ListNode* q = low->next;
while(p != NULL && q != NULL){
low->next = q->next;
q->next = p->next;
p->next = q;
p = q->next;
q = low->next;
}
}
/*
//方法一:暴力法
void reorderList(ListNode *head) {
ListNode *p = head;
ListNode *rear = head;
while(p != NULL && p->next != NULL){
while(rear->next->next != NULL){
rear = rear->next;
}
ListNode *temp = rear->next;
rear->next = NULL;
temp->next = p->next;
p->next = temp;
rear = temp->next;
p = temp->next;
}
}
*/
};
发表于 2017-04-28 09:52:43
回复(3)
2
void reorderList(ListNode *head) {
if(!head || !head->next ||!head->next->next)return;
ListNode *mid=new ListNode(0);
ListNode *end=new ListNode(0);
mid->next=head;
end->next=head;
int n=0;
while(end->next && end->next->next){
mid=mid->next;
end=end->next->next;
n++;
}
stackst;
mid=mid->next;
while(mid){
st.push(mid);
mid=mid->next;
}
ListNode *h=head;
while(n--){
ListNode *tmp=st.top();
tmp->next=h->next;
st.pop();
h->next=tmp;
h=tmp->next;
}
h->next=NULL;
}
编辑于 2018-03-02 22:32:26
回复(0)
2
// 用到了辅助栈
import java.util.Stack;
public class Solution {
public void reorderList(ListNode head) {
if(head == null)
return;
ListNode node = getMiddle(head);
ListNode middle = node.next;
// 把链表切成两段
node.next = null;
ListNode overMiddle = overturn(middle);
ListNode node2 = head;
ListNode result = head;
while(overMiddle != null){
ListNode newNode = new ListNode(overMiddle.val);
newNode.next = node2.next;
node2.next = newNode;
node2 = newNode.next;
overMiddle = overMiddle.next;
}
}
// 取得中间点
private ListNode getMiddle(ListNode head){
if(head == null || head.next == null){
return head;
}
ListNode fast = head, slow = head;
while(fast.next != null && fast.next.next != null){
fast = fast.next.next;
slow = slow.next;
}
return slow;
}
// 将链表翻转
private ListNode overturn(ListNode head){
if(head == null || head.next == null){
return head;
}
Stack stack = new Stack();
while(head != null){
stack.push(head);
head = head.next;
}
ListNode result = new ListNode(stack.peek().val);
ListNode node = result;
stack.pop();
while(stack != null && stack.size() != 0){
node.next = new ListNode(stack.peek().val);
node = node.next;
stack.pop();
}
return result;
}
}
发表于 2017-06-06 16:51:17
回复(0)
1
思路跟大家一样:1.用快慢指针找到链表中点,2.反转链表后半部门,3合并两个链表
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
void reorderList(ListNode *head) {
ListNode *slow = head, *fast = head;
while(fast->next != nullptr && fast->next->next != nullptr){
slow = slow->next;
fast = fast->next->next;
}
ListNode *mid = slow->next;
slow->next = nullptr;
ListNode *prev = nullptr, *cur = mid;
while(cur != NULL){
ListNode *tmp = cur->next;
cur->next = prev;
prev = cur;
cur = tmp;
}
ListNode *l1 = head, *l2 = prev;
while(l1 != NULL && l2 != NULL){
ListNode *l1_tmp = l1->next;
ListNode* l2_tmp = l2->next;
l1->next = l2;
l1->next->next = l1_tmp;
l1 = l1_tmp;
l2 = l2_tmp;
}
}
};
编辑于 2021-05-20 16:25:39
回复(0)
1
采用双端队列:
void reorderList(ListNode *head) {
if (head == NULL) return;
deque que;
ListNode* p = head->next;
while (p) {
que.push_back(p);
p = p->next;
}
ListNode* tmp = head;
tmp->next = NULL;
head = tmp;
while (que.size()>1) {
ListNode* f = que.front();
ListNode* r = que.back();
f->next = NULL;
r->next = NULL;
tmp->next = r;
tmp = tmp->next;
tmp->next = f;
tmp = tmp->next;
que.pop_front();
que.pop_back();
}
if (que.size()==1) {
ListNode* f = que.front();
f->next = NULL;
tmp->next = f;
que.pop_front();
}
}
发表于 2021-05-12 11:20:36
回复(0)
1
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
void reorderList(ListNode *head) {
if(head == nullptr) return;
ListNode *f = head->next, *s = head;
while(f && f->next){ //split link
s = s->next;
f = f->next->next;
}
f = s->next;
s->next = nullptr;
ListNode *pre = nullptr, *cur = f;
while(cur){ // reverse 2nd part
ListNode *next = cur->next;
cur->next = pre;
pre = cur;
cur = next;
}
cur = head;
while(pre && cur){ // merge
ListNode *tmp = pre->next;
pre->next = cur->next;
cur->next = pre;
cur = pre->next;
pre = tmp;
}
}
};
发表于 2020-07-07 21:14:39
回复(0)
1
一种很菜的思路:先将尾节点保存,然后删除,最后将尾节点插入到第二个位置,并将第二个位置的下一个节点当成下次执行时的头节点。
不知道是不是原地算法。 /**
* Definition for singly-linked list.
* class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public void reorderList(ListNode head) {
while(head != null && head.next != null && head.next.next != null){
//获取尾节点last
ListNode last = head;
while(last.next != null){
last = last.next;
}
//获取倒数第二个节点secondLast
ListNode secondLast = head;
while(secondLast.next.next != null){
secondLast = secondLast.next;
}
//删除尾节点
secondLast.next = null;
//将原尾节点插入第二个节点
ListNode preNode = head;
ListNode nextNode = head.next;
preNode.next = last;
last.next = nextNode;
//递归继续执行,此时的head为插入节点的下一个节点
head = last.next;
}
}
}
发表于 2020-06-12 18:21:10
回复(0)
1
class Solution {
ListNode* Rerverse(ListNode*pHead){
ListNode*tail=pHead;
while(tail->next)tail=tail->next;
while(pHead!=tail){
ListNode*temp=pHead->next;
pHead->next=tail->next;
tail->next=pHead;
pHead=temp;
}
return tail;
}
public:
void reorderList(ListNode *head) {
if(!head||!head->next)return ; //必须考虑到只有一个节点和空节点的情况
ListNode*fast=head,*slow=head;
while(fast->next&&fast->next->next){ //快慢指针求中间节点
slow=slow->next;
fast=fast->next->next;
}
ListNode*pHead=slow->next;
slow->next=nullptr;
ListNode*p2=Rerverse(pHead); //翻转列表 尾插法
ListNode*p1=head;
while(p2){
ListNode*p=p1->next;
p1->next=p2;
ListNode*pp=p2->next;
p2->next=p;
p1=p;
p2=pp;
}
}
};
发表于 2020-03-11 11:58:02
回复(0)
1
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
void reorderList(ListNode *head) {
if(!head) return;
// 快慢指针找到中间节点
ListNode* fast = head;
ListNode* slow = head;
while(fast->next != NULL && fast->next->next != NULL){
fast = fast->next->next;
slow = slow->next;
}
// 拆分链表,并反转中间节点之后的链表
ListNode* after = slow->next;
slow->next = NULL;
ListNode* pre = NULL;
while(after != NULL){
ListNode* temp = after->next;
after->next = pre;
pre = after;
after = temp;
}
// 合并两个链表
ListNode* first = head;
after = pre;
while(first != NULL && after != NULL){
ListNode* ftemp = first->next;
ListNode* aftemp = after->next;
first->next = after;
first = ftemp;
after->next = first;
after = aftemp;
}
}
};
编辑于 2020-03-08 19:33:28
回复(0)
1
解题思路
①找到中间节点 ②将链表拆分并逆序后半部分
③重新间隔拼接在一起
public class Solution {
public void reorderList(ListNode head) {
//链表长度小于2时直接返回
if(head == null || head.next == null) {
return;
}
//设置两个快慢指针
ListNode slow = head;
ListNode fast = head;
//fast走两步同时slow只走一步,从而找到中间节点
while (fast.next != null && fast.next.next != null){
fast = fast.next.next;
slow = slow.next;
}
//将链表从slow处拆开
ListNode after = slow.next;
slow.next = null;
//将后半部分链表逆序
ListNode pre = null;
while (after != null){
ListNode temp = after.next;
after.next = pre;
pre = after;
after = temp;
}
//将pre链表间隔插入head链表
ListNode first = head;
ListNode second = pre;
while (first != null && second != null){
ListNode firstTemp = first.next;
ListNode secondTemp = second.next;
first.next = second;
first = firstTemp;
second.next = first;
second = secondTemp;
}
}
}
编辑于 2020-02-28 01:56:17
回复(0)
1
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
找到链表中间的节点,利用for循环定位计数,创建一个虚拟节点连接新的链表,空间复杂度O(1),并且不改变原节点数据 class Solution {
public:
void reorderList(ListNode *head) {
if(head==NULL||head->next==NULL||head->next->next==NULL)
return ;
ListNode g=ListNode(0);
ListNode *h=&g;
ListNode *hh=h;
int num=0;
ListNode *temp=head;
while(temp!=NULL){
num++;
temp=temp->next;
}
int n=num/2;
temp=head;
ListNode * other=NULL;
for(int i=0;i
temp=temp->next;
}
other=temp;
int t=0;
if(num%2!=0)t=1;
for(int i=0;i
ListNode * curl=head;
head=head->next;
h->next=curl;
curl->next=NULL;
h=h->next;
temp=other;
int o=n+t-1-i;
while(o--){
temp=temp->next;
}
h->next=temp;
h=h->next;
temp->next=NULL;
}
if(t){
temp->next=other;
other->next=NULL;
}
head=hh->next;
return ;
}
};
发表于 2020-02-05 18:47:47
回复(0)
1
public void Solution(ListNode head){
if(head == null) return;
ListNode lowNode = head;
ListNode fastNode = head;
while(fastNode.next != null && fastNode.next.next != null){
lowNode = lowNode.next;
fastNode = fastNode.next.next;
}
ListNode leftNode = head;
ListNode rightNode = lowNode.next;
// 切断中间链
lowNode.next = null;
ListNode p = new ListNode(-1);
ListNode returnNode = p;
// head是左链头 rightNode是右链头
while(leftNode != null){
p.next = leftNode;
leftNode = leftNode.next;
ListNode tempR = rightNode;
while (tempR != null && tempR.next!= null && tempR.next.next!=null){
tempR = tempR.next;
}
if(tempR == null || tempR.next == null){
p.next.next = tempR;
rightNode = null;
}else{
p.next.next = tempR.next;
tempR.next = null;
}
if(p.next != null){
p = p.next.next;
}
}
head = returnNode;
}
思路和归并排序类似:
观察发现该结果是类似二路归并(L0->Ln/2 与 Ln/2+1 -> Ln)
故原地排序方法为:
1.找到中间节点 左链表 leftNode 右链表 rightNode(Ln/2+1)
2.每次取一个左链表头,取一个右链表尾
3.取完右链表值后,将其父节点的next索引置空
发表于 2020-01-08 20:18:59
回复(0)
1
主要知识点:快慢指针寻找链表中点,链表反转,链表合并
import java.util.List;
import java.util.Stack;
/*
将给定的单链表L: L 0→L 1→…→L n-1→L n,
重新排序为: L 0→L n →L 1→L n-1→L 2→L n-2→…
要求使用原地算法,并且不改变节点的值
例如:
对于给定的单链表{1,2,3,4},将其重新排序为{1,4,2,3}.
*/
public class Solution {
public void reorderList(ListNode head) {
if (head == null || head.next == null)
return;
// 快慢指针找到中间节点
ListNode fast = head;
ListNode slow = head;
while (fast.next != null && fast.next.next != null) {
fast = fast.next.next;
slow = slow.next;
}
//拆分链表,并反转中间节点之后的链表
ListNode curNode = slow.next; //定义一个辅助curNode
slow.next = null; //将原来的链表拆分,拆分后的最后一个非空节点为slow
ListNode preNode = null; //定义一个空的preNode,表示curNode之前的节点
while (curNode != null) {
ListNode nextNode = curNode.next; //
curNode.next = preNode; //当前节点的下一个节点指向前面的节点,即指针反转
preNode = curNode; //preNode后移到curNode上
curNode = nextNode; //curNode后移
}
//执行完反转操作之后,反转链表的第一个节点为preNode
//合并两个链表
ListNode first = head; //first指向第一个链表的头结点
ListNode after = preNode; //after指向第二个反转后的链表的头结点
while (first != null && after != null) {
ListNode firstTemp = first.next;
ListNode afterTemp = after.next;
first.next = after; //将after的第一个数放在first后面
first = firstTemp; //first后移到firstTemp
after.next = first; //after指向新的first
after = afterTemp; //after后移到afterTemp
}
}
}
发表于 2020-01-06 14:45:39
回复(0)
1
public class Solution {
// 快慢指针寻找链表中点
private static ListNode findMid(ListNode head){
ListNode quick = head;
ListNode slow = head;
while(quick.next!=null && quick.next.next!=null){
quick = quick.next.next;
slow = slow.next;
}
return slow;
}
// 链表反转
private static ListNode reverse(ListNode head){
ListNode rhead = null;
ListNode cur = head;
while(cur!=null){
ListNode tmp = cur;
cur = cur.next;
tmp.next = rhead;
rhead = tmp;
}
return rhead;
}
public void reorderList(ListNode head) {
if(head==null||head.next==null) return;
// 找到中点后将链表分为两部分,后面一部分反转
ListNode mid = findMid(head);
ListNode rhead = reverse(mid.next);
mid.next = null;
ListNode p = head;
ListNode q = rhead;
// 将两截链表按照p0->q0->p1->q1...重新连接
while(p!=null&&q!=null){
ListNode a = p.next;
ListNode b = q.next;
p.next = q;
q.next = a;
p = a;
q = b;
}
}
}
发表于 2019-12-30 16:25:31
回复(0)