Algorithm 在给定块大小时反转单链表

Algorithm 在给定块大小时反转单链表,algorithm,linked-list,space-complexity,Algorithm,Linked List,Space Complexity,有一个单独连接的链表,并且给出了一个块大小。例如,如果我的链表是1->2->3->4->5->6->7->8-NULL,并且我的块大小是4,那么将第一个4元素和第二个4元素颠倒过来。问题的输出应该是4->3->2->1->8->7->6->5-NULL 我正在考虑将链表分成大小为4的段,然后将其反转。 但是那样的话,我不得不使用很多额外的节点,这是完全不需要的。 空间复杂度应保持在最低限度 如果有人能提供一个更好的解决方案,将额外节点的使用量保持在最低限度,这将是非常值得赞赏的。您可以提前将当前

有一个单独连接的链表,并且给出了一个块大小。例如,如果我的链表是
1->2->3->4->5->6->7->8-NULL
,并且我的块大小是
4
,那么将第一个
4
元素和第二个4元素颠倒过来。问题的输出应该是
4->3->2->1->8->7->6->5-NULL

我正在考虑将链表分成大小为
4
的段,然后将其反转。 但是那样的话,我不得不使用很多额外的节点,这是完全不需要的。 空间复杂度应保持在最低限度


如果有人能提供一个更好的解决方案,将额外节点的使用量保持在最低限度,这将是非常值得赞赏的。

您可以提前将当前元素替换为接下来的3次:1234、2134、2314、2341。然后做两次,得到3421。然后一次拿到4321。然后前进4步,对下一个块重复这个过程。

我试过这个……似乎很好

node* reverse(node* head) // function to reverse a list
{
    node* new_head = NULL;
    while(head != NULL)
    {
        node* next = head->next;
        head->next = new_head;
        new_head = head;
        head = next;
    }
    return new_head;
}

node* reverse_by_block(node* head, int block)
{
    if(head == NULL)
            return head;

    node* tmp = head;
    node* new_head = head;
    node* new_tail = NULL;

    int count = block;
    while(tmp != NULL && count--)
    {
        new_tail = tmp;
        tmp = tmp->next;
    }

    new_tail->next = NULL;
    new_tail = new_head;
    new_head = reverse(new_head);
    new_tail->next = reverse_by_block(tmp,block);

    return new_head;
}

这可以在线性时间内完成,且空间恒定。 以下是简要说明:

  • 按块大小将链表拆分为两部分

    
    int split(node* head, node** listA, node** listB size_t block_size)
    {
    node* cur = head;
    
    while(block_size && cur)
    {
       cur = cur->next;
       --block_size;
    }
    if(!cur) { /* error : invalid block size */ return -1; }
    *listA = head;
    *listB = cur->next;
    cur->next = NULL; /* terminate list A */
    return 0;
    }
    
  • 反转两个子部分(使用非递归线性时间常数空间函数)

  • 链接它们以获得所需的链接列表

    
    cur = *listA;
    /* goto last but one element of listA */
    while(cur->next) cur = cur->next; 
    cur->next = *listB;
    

  • 我必须反转节点,而不仅仅是数据元素。是的。要交换A和B,P是A之前的节点(扫描时跟踪此节点),请执行P.next=B,A.next=B.next,B.next=A。明白了。您的prg正在使用5个额外的节点,需要处理该节点。节点只是指针…重点是没有使用xtra内存。
    
    cur = *listA;
    /* goto last but one element of listA */
    while(cur->next) cur = cur->next; 
    cur->next = *listB;