每日一题(4)

给定一个链表,把最后一个结点插入到第1个结点后,倒数第二个结点插入到第2个结点后,倒数第三个结点插入到第3个结点后,以此类推……

【必须在不改变节点值的情况下就位】


思路:
先用快慢指针找到链表的中点,然后翻转链表后半部分,再和前半部分组合。
注意:
把链表分成两半时,前半段的尾节点要置为NULL,翻转链表时也要把尾节点置为NULL。

/**
 * 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)
            return;
        ListNode *fast=head;
        ListNode *slow=head;
        while(fast->next && fast->next->next){
            fast=fast->next->next;
            slow=slow->next;
        }
        //此时的slow即为中间节点

        //将中间节点前后拆成两条链
        ListNode *list=slow->next;
        slow->next=NULL;

        //逆置中间节点后的节点
        ListNode *node=NULL;
        ListNode *cur=list;
        while(cur){
            ListNode *tmp=cur;
            cur=cur->next;

            //头插头插法
            tmp->next=node;
            node=tmp;
        }
        list=node;

        //将两个链表合并
        ListNode *node1=head,*node2=list;
        while(node2){
            ListNode *tmp1=node1->next;
            ListNode *tmp2=node2->next;
            node1->next=node2;
            node2->next=tmp1;
            node1=tmp1;
            node2=tmp2;
        } 
    }
};

因为题目要求复杂度为O(nlogn),故可以考虑归并排序的思想。
时间复杂度O(nlogn)空间复杂度 O(1)
这里写图片描述
归并排序的一般步骤为:

  1. 将待排序数组(链表)取中点并一分为二;
  2. 递归地对左半部分进行归并排序;
  3. 递归地对右半部分进行归并排序;

根据题目要求,可以划分为三个小问题:

  1. 找到链表中点
  2. 写出MergeTwoList函数,即如何合并链表。
  3. 写出sortlist函数,通过递归实现
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *FindMiddleNode(ListNode *head){
        ListNode *fast=head,*slow=head;
        while(fast->next && fast->next->next){
            fast=fast->next->next;
            slow=slow->next;
        }
        return slow;       
    }

    ListNode *MergeTwoList(ListNode *list1,ListNode *list2){
        if(list1==NULL)
            return list2;
        if(list2==NULL)
            return list1;
        ListNode *list=new ListNode(NULL),*node=list;
        while(list1 && list2){
            if(list1->val>list2->val){
                node->next=list2;
                list2=list2->next;
            }else{
                node->next=list1;
                list1=list1->next;
            }
            node=node->next;
        }
        if(list1)
            node->next=list1;
        if(list2)
            node->next=list2;
        return list->next;
    }

    ListNode *sortList(ListNode *head) {
        if(head==NULL || head->next==NULL)
            return head;
        ListNode *middle=FindMiddleNode(head);
        ListNode *right=sortList(middle->next);
        middle->next=NULL;
        ListNode *left=sortList(head);
        return MergeTwoList(left,right);
    }
};

给出一个所有元素以升序排序的单链表,将它转换成一棵高度平衡的二分查找树


用快慢指针找出中点,作为根,中点左右两边分别递归的构建二叉树。

最初使用跟Sort List一般的方法:一个链分裂成两个链,发现有错误。原因是有中点需要去掉,跟划分链不完全一致了。

最好是使用一个begin指针指示第一个元素,end指针指示最后一个元素的下一个位置(即左闭右开空间),很方便的就构建起平衡二叉树。

元素个数为奇数的构建平衡二叉查找树:

元素个数为偶数的构建平衡二叉查找树:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
/**
 * Definition for binary tree
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode *BuildBSTree(ListNode *begin,ListNode *end){
        if(begin==end)
            return NULL;
        ListNode *fast=begin,*slow=begin;
        while(fast->next!=end && fast->next->next!=end){
            fast=fast->next->next;
            slow=slow->next;
        }
        fast=slow->next;
        TreeNode *root=new TreeNode(slow->val);

        root->left=BuildBSTree(begin,slow);
        root->right=BuildBSTree(fast,end);
        return root;
    }
    TreeNode *sortedListToBST(ListNode *head) {
        if(head==NULL)
            return NULL;
        if(head->next==NULL)
            return new TreeNode(head->val);
        return BuildBSTree(head,NULL);
    }
};

猜你喜欢

转载自blog.csdn.net/sifanchao/article/details/81389541