力扣OJ 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.

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/reorder-list
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路:

分为三步:

(1)算出链表长度,从中间断开,变成2个链表

(2)后半段链表反转,输出新的head即原来的tail

(3)把2个链表交叉串起来。

代码:

int GetLength(ListNode *p)//获取链表长度
{
    int ans=0;
    while(p)
    {
        ans++;
        p=p->next;
    }
    return ans;
}

ListNode * Reverse(ListNode *p)//链表反转,返回新的head
{
    if(p==NULL)return p;
    ListNode * q1;
    ListNode * q2;
    q1=p->next, p->next=NULL;
    while(q1)
    {
        q2=q1->next, q1->next=p, p=q1, q1=q2;
    }
    return p;
}

class Solution {
public:
    void reorderList(ListNode* head) {
        if(head==NULL)return;
        int length=GetLength(head);
        length=(length-1)/2;
        ListNode* p=head;
        while(length--)p=p->next;
        ListNode*q=p->next;
        p->next=NULL; //链表割开
        q=Reverse(q);//后半段反转
        p=head;
        ListNode* pnext,*qnext;
        while(q)
        {
            pnext=p->next, qnext=q->next;
            p->next=q, q->next=pnext;
            p=pnext, q=qnext;
        }
    }
};

做题时候调试用的测试代码:

int main()
{
    ListNode *p1=new ListNode(1);
    ListNode *p2=new ListNode(2);
    ListNode *p3=new ListNode(3);
    ListNode *p4=new ListNode(4);
    p1->next=p2,p2->next=p3,p3->next=p4,p4->next=NULL;
    Solution s;
    s.reorderList(p1);
    cout<<p1->val<<p2->val<<p3->val<<p4->val<<endl;
    while(p1)
    {
        cout<<p1->val;
        p1=p1->next;
    }
    return 0;
}

输出:

1234
1423

PS:可以看出修改链表的节点存储的数值,和修改链表的链接,是不一样的。这也是题目要求的做法。

发布了1185 篇原创文章 · 获赞 679 · 访问量 171万+

猜你喜欢

转载自blog.csdn.net/nameofcsdn/article/details/103969203