1.重排链表(LeetCode:143)

问题描述 :

给定一个单链表 L:L0→L1→…→Ln-1→Ln ,

将其重新排列后变为: L0→Ln→L1→Ln-1→L2→Ln-2→…

你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。

示例 1:

给定链表 1->2->3->4, 重新排列为 1->4->2->3.

示例 2:

给定链表 1->2->3->4->5, 重新排列为 1->5->2->4->3.

可使用以下代码,完成其中的reorderList函数,其中形参head指向无头结点单链表。

#include

using namespace std;

struct ListNode

{

int val;

ListNode *next;

ListNode() : val(0), next(NULL) {}

ListNode(int x) : val(x), next(NULL) {}

ListNode(int x, ListNode *next) : val(x), next(next) {}

};

class Solution

{

public:

void reorderList(ListNode* head)

{

         //填充本函数完成功能

}

};

ListNode *createByTail()

{

ListNode *head;

ListNode *p1,*p2;

int n=0,num;

int len;

cin>>len;

head=NULL;

while(n>num)

{

    p1=new ListNode(num);

    n=n+1;

    if(n==1)

        head=p1;

    else

        p2->next=p1;

    p2=p1;

}

return head;

}

void displayLink(ListNode *head)

{

ListNode *p;

p=head;

cout<<"head-->";

while(p!= NULL)

{

    cout<val<<"-->";

    p=p->next;

}

cout<<"tail\n";

}

int main()

{

ListNode* head = createByTail();

Solution().reorderList(head);

displayLink(head);

return 0;

}

输入说明 :

首先输入链表长度len,然后输入len个整数,以空格分隔。

输出说明 :

输出格式见范例

输入范例 :

5
1 2 3 4 5

输出范例 :

head–>1–>5–>2–>4–>3–>tail

/*
给定一个单链表 L:L0→L1→…→Ln-1→Ln ,
将其重新排列后变为: L0→Ln→L1→Ln-1→L2→Ln-2→…
你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
示例 1:
给定链表 1->2->3->4, 重新排列为 1->4->2->3.
示例 2:
给定链表 1->2->3->4->5, 重新排列为 1->5->2->4->3.


算法思想:
法一:遍历链表节点,将节点加入vector,通过索引完成重新排序,时间复杂度O(n) 

法二:
	1.快慢指针找到中点
	2.将后半段逆置
	3.将后半段插入前半段 
*/

#include
#include
using namespace std;

struct ListNode
{
    int val;
    ListNode *next;
    ListNode() : val(0), next(NULL) {}
    ListNode(int x) : val(x), next(NULL) {}
    ListNode(int x, ListNode *next) : val(x), next(next) {}
};

class Solution
{
public:
    void reorderList(ListNode* head)
    {
    	if(head == NULL)
    	{
    		return;
    	}
    	vector<ListNode *> node_vec;
    	ListNode *p = head;
    	//将链表节点的指针加入vector中
    	while(p)
    	{
    		node_vec.push_back(p);
    		p = p->next;
    	}
    	int i = 0,j = node_vec.size()-1;
    	//通过索引重新完成排序
    	for(;i != j; i++,j--)  //当链表有奇数个节点时会从i!=j处退出循环
    	{
    		node_vec[i]->next = node_vec[j];
    		if(j == i+1)
    		{
    			break;		//当链表有偶数个节点时会从 这里退出循环
			}
			node_vec[j]->next = node_vec[i+1]
		}
		node_vec[j]->next = NULL;	//表尾结点后继为NULL
    	
    }
    
    void  reorderList2(ListNode* head){
    	if(head == NULL){
    		return ;
		}
		//1.快慢找到需要重排的后半部分
		ListNode *slow = head;
		ListNode *fast = head;
		while(fast && fast->next)
		{
			slow = slow->next;
			fast = fast->next->next;
		}
		//2.逆置后半部分链表
		ListNode *p = slow->next;  //后半部分的开始
		ListNode *pre_node = NULL;
		while(p)
		{
			ListNode *next = p->next;  //保存p的后继
			p->next = pre_node;  //p指向其前驱节点
			pre_node = p;		//更新pre
			p = next;			//更新p;
		}
		//3.将逆置后的后半部分插入前半部分
		ListNode *left = head;
		ListNode *right = pre_node;
		while(right)
		{
			ListNode *next = right->next;
			right->next = left->next;
			left->next = right;
			right = next;
			left = left->next->next;
		}
	}
};

ListNode *createByTail()
{
    ListNode *head;
    ListNode *p1,*p2;
    int n=0,num;
    int len;
    cin>>len;
    head=NULL;
    while(n<len && cin>>num)
    {
        p1=new ListNode(num);
        n=n+1;
        if(n==1)
            head=p1;
        else
            p2->next=p1;
        p2=p1;
    }
    return head;
}

void displayLink(ListNode *head)
{
    ListNode *p;
    p=head;
    cout<<"head-->";
    while(p!= NULL)
    {
        cout<<p->val<<"-->";
        p=p->next;
    }
    cout<<"tail\n";
}

int main()
{
    ListNode* head = createByTail();
    Solution().reorderList2(head);
    displayLink(head);
    return 0;
}

你可能感兴趣的:(链表)