反转链接列表中的每k个节点块

时间:2015-07-09 21:44:47

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

我试图解决扭转链接列表中每个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.

3 个答案:

答案 0 :(得分:0)

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

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

答案 1 :(得分:0)

将反转视为从一个列表中弹出并推送到另一个列表是有帮助的。你还需要知道前一个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中,推送和弹出以通常的方式实现:

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;
}

答案 2 :(得分:0)

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

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;
}