算法题-按照左右半区的方式重新组合单链表

40 篇文章 0 订阅
38 篇文章 0 订阅

[编程题]按照左右半区的方式重新组合单链表

时间限制:1秒 空间限制:32768K

给定一个单链表的头部节点head,链表长度为N。 如果N为偶数,那么前N/2个节点算作左半区,后N/2个节点算作右半区; 如果N为奇数,那么前N/2个节点算作左半区,后N/2+1个节点算作右半区; 左半区从左到右依次记为L1->L2->…,右半区从左到右依次记为R1->R2->…。请将单链表调整成L1->R1->L2->R2->…的样子。 例如: 1->2->3->4 调整后:1->3->2->4 1->2->3->4->5 调整后:1->3->2->4->5 要求:如果链表长度为N,时间复杂度请达到O(N),额外空间复杂度请达到O(1)

思路:
创建一个新Vector,先将整个链表push_back如心得Vector中,同时将其按下标分成左右两个链表,从前到后逐个判断”链表”(实则已是在Vector中操作)从头到尾的第奇数还是偶数位,Vector的奇数位插入原链表右侧元素,偶数为插入原链表左侧元素,直到链表(Vector)结束;

    /*
     *  按照左右半区的方式重新组合单链表
     *  输入:一个单链表的头节点head
     *  将链表调整成题目要求的样子
     */

class Solution {
public:

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

    void relocateList(struct ListNode* pHead) {
        ListNode* Pointer = pHead;
        vector<int> Vector;
        while (Pointer != NULL) {
            Vector.push_back(Pointer->val);
            Pointer = Pointer->next;
        }
        Pointer = pHead;
        int IndexOfVector = 0;
        int IndexOfLeft = 0;
        int IndexOfRight = Vector.size() / 2;
        while (IndexOfVector<Vector.size()-1 && Pointer != NULL) {
            if (IndexOfVector % 2 == 0) {//链表偶数位(包括0)
                Pointer->val = Vector[IndexOfLeft++];
                Pointer = Pointer->next;
            }
            else if (IndexOfVector % 2 != 0) {//链表奇数位
                Pointer->val = Vector[IndexOfRight++];
                Pointer = Pointer->next;
            }
            ++IndexOfVector;
        }
    }
};

解法2

class Solution {
public:
    void relocateList(struct ListNode* head) {
        ListNode* p = head ;
        int length = 0 ;
        while ( p != NULL ) {
            ++ length ;
            p = p -> next ;
        }

        vector<int> vec ;
        p = head ;
        for ( int i = 0; i < length; ++ i ) {
            vec.push_back( p->val ) ;
            p = p->next ;
        }

        p = head ;
        int left_cur = 0 ;
        int right_cur = length / 2 ;
        int index = 0 ;
        while( index < vec.size() - 1 && p != NULL ) {
            if ( index % 2 == 0 ) {
                p->val = vec[left_cur] ;
                ++ left_cur ;
            }
            else {
                p->val = vec[right_cur] ;
                ++ right_cur ;
            }
            p = p->next ;
            ++ index ;
        }
    }
};

【基本思路】

  先遍历一遍找到左半区的最后一个节点,然后将链表分成左右两部分,在按照题目要求重新合并即可。

  如何找到左半区的最后一个节点?
  
  例如:1 -> 2,mid为1;
  1 -> 2 -> 3,mid为2;
  1 -> 2 -> 3 -> 4,mid为2;
  1 -> 2 -> 3 -> 4 -> 5,mid为3;
  1 -> 2 -> 3 -> 4 -> 5 -> 6,mid为3;

  也就是说,从长度为2开始,长度每增加2,mid就往后移动一个节点。

Python实现

#python3.5
def reCombination(head):
    if head == None or head.next == None:
        return head
    mid = head
    right = head.next
    while right.next != None and right.next.next != None:
        mid = mid.next
        right = right.next.next
    right = mid.next
    mid.next = None
    cur = head
    while cur.next != None:
        rightNext = right.next
        right.next = cur.next
        cur.next = right
        cur = right.next
        right = rightNext
    cur.next = right
    return head

Python解法参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值