c语言重排链表,重排链表

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)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值