微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

链接列表按K个节点的组反向

如何解决链接列表按K个节点的组反向

最初,面试官问这个问题,以扭转我很容易解决的链表。
现在他说要按K个节点的组来反转列表。

例如,如果列表为[1,2,3,4,5,6]K=4,则为o/p = [4,1,6].。因此,我已经修改了现有解决方案以实现此目的,但是仍然可以使整个列表的输出颠倒(i.e [6,1])。参见下面的程序。可能需要进行一些细微的更改,但我无法弄清楚。有人可以帮忙解决问题吗?

ListNode *reverseKGroup(ListNode *head,int k) 
{
    if (k == 0 || k == 1)
        return head;

    if (head == NULL)
        return NULL;

    int counter = 0;
    ListNode *fastPtr = head;
    ListNode *currentPtr = head;
    ListNode *nextPtr = NULL;
    ListNode *prevPtr = NULL;
        
    while (fastPtr)
    {
        counter++;

        //one chain formed from list,reverse it
        if (counter == k)
        {
            fastPtr = fastPtr->next;
            
            while (counter)
            {
                nextPtr = currentPtr->next;
                currentPtr->next = prevPtr;
                prevPtr = currentPtr;
                currentPtr = nextPtr;
                counter--;
            }

            //last node
            if (currentPtr->next == NULL)
            {
                currentPtr->next = prevPtr;
                prevPtr = currentPtr;
                break;
            }
        }
        else
        {
            fastPtr = fastPtr->next;
        }
    }
    
    return prevPtr;
}

解决方法

>它给出了整个列表的输出反转....

这是因为下次控件进入此if

if(counter == k)

在操作列表时,指针prevPtr仍指向列表中与上一次迭代所指向的节点相同的节点。反转一组prevPtr节点时,需要将NULL设置为k。与此同时,您需要明确地处理列表的headtail。列表的head将是颠倒的k节点的第一组的k th 节点,列表的tail将是第一个节点当列表中的节点是k的倍数时,最后一组k节点的;如果列表中的节点不在{{1}的倍数中,它将指向其余列表的第一个节点}。反转每个k节点组时,需要注意列表中的tail

在处理上述细节的同时粗略地修改了代码:

k

您可以使用递归来反转列表中ListNode* reverseKGroup(ListNode* head,int k) { if(k==0 || k==1) return head; if(head == NULL) return NULL; int counter = 0; ListNode* fastPtr = head; ListNode* currentPtr = head; ListNode* nextPtr = NULL; ListNode* prevPtr = NULL; ListNode* tail = NULL; ListNode* currLast = NULL; int set_head = 0; int set_currLast = 0; while(fastPtr) { counter++; //one chain formed from list,reveser it if(counter == k) { fastPtr = fastPtr->next; prevPtr = NULL; set_currLast = 0; while(counter) { nextPtr = currentPtr->next; currentPtr->next = prevPtr; // when reversing group of k nodes,the first node will be // the last when whole group reversed if (!set_currLast) { currLast = currentPtr; set_currLast = 1; } prevPtr = currentPtr; currentPtr = nextPtr; counter--; } // Need to set head just once only if (!set_head) { tail = head; head = prevPtr; set_head = 1; } else { // the tail need to set after reversing every k nodes group tail->next = prevPtr; tail = currLast; } // For the last group which will be of size less than k tail->next = nextPtr; } else { fastPtr = fastPtr->next; } } return head; } 个节点组中的节点。该代码看起来很干净,更容易理解:

k
,

您的方法还可以,但是您没有正确链接反向列表片段:

  • 您可以将fastPtr = fastPtr->next;分解为if语句的两个分支。

  • 最后一个节点的测试是虚假的:如果列表长度是if (currentPtr->next == NULL)的倍数,k将取消引用空指针。

  • 您应该保留一个指向反向列表片段头部存储位置的指针。在循环开始时,该指针指向变量head,在每个片段反转之后,它应指向反转之前片段第一个节点的next成员,即CurrentNode在反转循环的开始。

通过这些小的修改,您的代码可以正常运行。

请注意,这个问题很棘手。如果面试官要求您以交互方式解决问题,则他们可能会对您解决问题的方法感兴趣。在不到半小时的时间内构造出有效而优雅的解决方案将是非常好的。

这是带有测试床的修改版:

#include <stdio.h>

typedef struct ListNode {
    struct ListNode *next;
    int data;
} ListNode;

ListNode *reverseKGroup(ListNode *head,int k) {
    if (k > 1) {                     // no need to test for `head != NULL`
        int counter = 0;
        ListNode **start = &head;    // place where to store the head of the reversed fragment
        ListNode *currentPtr = head; // pointer to the first node of the fragment
        ListNode *fastPtr = head;    // pointer to the node after the end of the fragment

        while (fastPtr) {
            fastPtr = fastPtr->next;
            counter++;
            if (counter == k) {
                // k nodes between CurrentPtr and fastPtr: reverse the fragment
                ListNode *lastPtr = currentPtr;
                ListNode *prevPtr = fastPtr;
                while (counter) {
                    ListNode *nextPtr = currentPtr->next;
                    currentPtr->next = prevPtr;
                    prevPtr = currentPtr;
                    currentPtr = nextPtr;
                    counter--;
                }
                *start = prevPtr;
                start = &lastPtr->next;
            }
        }
    }
    return head;
}

void printList(const char *prefix,const ListNode *p,const char *suffix) {
    while (p) {
        printf("%s%d",prefix,p->data);
        prefix = ",";
        p = p->next;
    }
    printf("%s",suffix);
}

ListNode *test(ListNode *list,int k) {
    printf("reverseKGroup(%d): ",k);
    list = reverseKGroup(list,k);
    printList("",list,"\n");
    return reverseKGroup(list,k); // undo k-reversal
}

int main() {
    ListNode a[10],*list = a;
    for (int i = 0; i < 10; i++) {
        a[i].next = i + 1 < 10 ? &a[i + 1] : NULL;
        a[i].data = i + 1;
    }
    for (int k = 0; k <= 11; k++) {
        list = test(list,k);
    }
    return 0;
}

输出:

reverseKGroup(0): 1,2,3,4,5,6,7,8,9,10
reverseKGroup(1): 1,10
reverseKGroup(2): 2,1,10,9
reverseKGroup(3): 3,10
reverseKGroup(4): 4,10
reverseKGroup(5): 5,6
reverseKGroup(6): 6,10
reverseKGroup(7): 7,10
reverseKGroup(8): 8,10
reverseKGroup(9): 9,10
reverseKGroup(10): 10,1
reverseKGroup(11): 1,10
,

最初,面试官问这个问题来扭转链接 清单,我很容易解决。现在他说要扭转小组名单 K个节点。

对于初学者,切勿在面试中做任何测试作业。禁止他人操纵您和您的时间。忽略提供测试任务的公司。

例如,对于任务而言,使用递归函数不是一个好主意,因为对于大列表,您可能会出现堆栈溢出。

另外,引入一种用于声明列表本身的结构会更好。

我可以提出以下解决方案。

#include <stdio.h>
#include <stdlib.h>

struct Node
{
    int data;
    struct Node *next;
};

struct List
{
    struct Node *head;
};

int push_front( struct List *list,int data )
{
    struct Node *new_node = malloc( sizeof( struct Node ) );
    int success = new_node != NULL;
    
    if ( success )
    {
        new_node->data = data;
        new_node->next = list->head;
        list->head = new_node;
    }
    
    return success;
}

void clear( struct List *list )
{
    while ( list->head != NULL )
    {
        struct Node *tmp = list->head;
        list->head = list->head->next;
        free( tmp );
    }
}

FILE * display( const struct List *list,FILE *fp )
{
    for ( const struct Node *current = list->head; current != NULL; current = current->next )
    {
        fprintf( fp,"%d -> ",current->data );
    }
    
    fputs( "null",fp );
    
    return fp;
}

void reverse_n( struct List *list,size_t n )
{
    if ( !( n < 2 ) )
    {
        for( struct Node **first = &list->head,*last = list->head; last != NULL; )
        {
            for ( size_t i = n; --i != 0 && last; )
            {
                last = last->next;
            }
            
            if ( last != NULL )
            {
                struct Node *next = ( *first )->next;
                ( *first )->next = last->next;
                last = *first;

                for ( size_t i = n; --i != 0; )
                {
                    struct Node *tmp = next;
                    next = next->next;
                    tmp->next = *first;
                    *first = tmp;
                }
                
                first = &last->next;
                last  = last->next;
            }
        }
    }
}

int main(void) 
{
    struct List list = { .head = NULL };
    const int N = 10;
    
    for ( size_t i = 2; i < N + 1; i++ )
    {
        for ( int j = N; j != 0; --j )
        {
            push_front( &list,j - 1 );
        }
    
        putc( '\n',display( &list,stdout ) );
    
        reverse_n( &list,i );
    
        putc( '\n',stdout ) );
        
        putc( '\n',stdout );
        
        clear( &list );
    }

    return 0;
}

程序输出为

0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> null
1 -> 0 -> 3 -> 2 -> 5 -> 4 -> 7 -> 6 -> 9 -> 8 -> null

0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> null
2 -> 1 -> 0 -> 5 -> 4 -> 3 -> 8 -> 7 -> 6 -> 9 -> null

0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> null
3 -> 2 -> 1 -> 0 -> 7 -> 6 -> 5 -> 4 -> 8 -> 9 -> null

0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> null
4 -> 3 -> 2 -> 1 -> 0 -> 9 -> 8 -> 7 -> 6 -> 5 -> null

0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> null
5 -> 4 -> 3 -> 2 -> 1 -> 0 -> 6 -> 7 -> 8 -> 9 -> null

0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> null
6 -> 5 -> 4 -> 3 -> 2 -> 1 -> 0 -> 7 -> 8 -> 9 -> null

0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> null
7 -> 6 -> 5 -> 4 -> 3 -> 2 -> 1 -> 0 -> 8 -> 9 -> null

0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> null
8 -> 7 -> 6 -> 5 -> 4 -> 3 -> 2 -> 1 -> 0 -> 9 -> null

0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> null
9 -> 8 -> 7 -> 6 -> 5 -> 4 -> 3 -> 2 -> 1 -> 0 -> null

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。