【问题标题】:Reverse every k block of nodes in a link list反转链表中的每 k 个节点块
【发布时间】:2015-07-09 21:44:46
【问题描述】:

我试图解决这个问题,即反转链接列表中的每 k 个节点块。我在每个外部 while 循环中处理 2*k 个元素。是否可以通过只处理每个外部 while 循环中的 k 个元素或不使用 hasknodes() 函数来完成?

样本输入:1->2->3->4->5 和 k = 3

样本输出:3->2->1->4->5

 struct node *rev(struct node *head,int k)
    {
        if(k == 0 || k == 1) {
            return head;
        }
        int i;
        struct node *prev,*temp,*curr,*newhead,*p,*thead;
        p = head;
        thead = head;
        newhead = NULL;
        while(p && hasknodes(p,k)) {
            prev = NULL;
            curr = p;
            i = 0;
            while(curr && i < k) {
                temp = curr->next;
                curr->next = prev;
                prev = curr;
                curr= temp;
                i++;
            }
            if(newhead == NULL) {
                newhead = prev;
            }
            else {
                thead->next = prev;
            }
            p->next = curr;
            head = p;
            if(p) {
                p = p->next;
            }
        }
        if(newhead == NULL) {
            return head;
        }
        return newhead;
    }
//The function hasknodes(p,k) checks if there are k elements present from the current position p.

【问题讨论】:

  • 如果可以撤消最后一段的反转,则不必知道剩余长度。
  • 样本输出不应该是2-&gt;1-&gt;4-&gt;3-&gt;5吗?
  • 其他限制?你能用一个向量作为临时的吗?
  • @AlexandruBarbarosie 那错了。查看编辑。
  • @DOUGLASO.MOEN 我们不能使用向量

标签: c++ algorithm data-structures linked-list


【解决方案1】:

其实你不需要调用函数hasknodes;而是开始拾取节点并以相反的顺序链接它们(就像您在内部 while 循环中所做的那样),如果您过早到达列表的末尾,则重新附加反向列表的元素。然而,这种方法的缺点是代码变得有点复杂。

正如第一个评论者所写:O(2*n) 实际上与 O(n) 相同,因为 O(n) 意味着您的问题可以在时间 与 n 成比例 的时间内解决。所以,你基本上已经完成了:-)

【讨论】:

  • 我看到你提到了第一条评论,但没有提到你在回答中基本上重复的第二条评论
  • 我猜重新添加会消耗额外的内存。
  • @shivam mitra:不,重新附加不会消耗额外的内存。这只是调整节点链接的问题。
【解决方案2】:

将反转视为从一个列表弹出并推入另一个列表会很有帮助。您还需要知道 k 的前一个块的尾部,以便附加下一个。所以在伪代码中:

// let list be the head of the input list
prev_tail = sentinel; // fake previous tail node to append the first block
while list is not NULL 
  tail = list
  block = NULL
  for k times and while list isn't NULL
    push(block, pop(list))
  prev_tail->next = block
  prev_tail = tail;
return sentinel->next;

现在在 C 中,push 和 pop 以通常的方式实现:

typedef struct node_s { 
  struct node_s *next;
  ...
} Node;

Node *reverse_blocks(Node *list, int k) {
  Node sentinel[1] = {{NULL}};
  Node *prev_tail = sentinel;
  while (list) {
    Node *block = NULL;
    Node *tail = list;
    for (int i = 0; list && i < k; i++) {
      Node *pop = list;
      list = list->next;
      pop->next = block; // push(block, pop)
      block = pop;
    }
    prev_tail->next = block;
    prev_tail = tail;
  }
  return sentinel->next;
}

【讨论】:

    【解决方案3】:

    您可以为此编写一个简单的递归解决方案:

    struct node *reverse (struct node *head, int k)
    {
       struct node* current = head;
       struct node* next = NULL;
       struct node* prev = NULL;
       int count = 0;   
    
         /*reverse first k nodes of the linked list */
         while (current != NULL && count < k)
        {
           next  = current->next;
           current->next = prev;
           prev = current;
           current = next;
           count++;
        }
    
       /* next is now a pointer to (k+1)th node,Recursively call for the   
          list starting from current.And make rest of the list as next of first node */
       if(next !=  NULL)
       { 
           head->next = reverse(next, k); 
       }
    
       /* prev is new head of the input list */
       return prev;
    }
    

    【讨论】:

      猜你喜欢
      • 2011-10-31
      • 1970-01-01
      • 1970-01-01
      • 2020-12-25
      • 2016-07-09
      • 2018-07-28
      • 1970-01-01
      • 2023-03-08
      相关资源
      最近更新 更多