删除链表的倒数第K个节点

看到这个题我先想到的是之前做过链表面试题中的:查找链表的倒数第K个节点(要求只遍历一次链表),而删除的话就是另外一个面试题:删除链表的pos节点;另外一种就是在OJ下实现的方法。

相关的链表面试题:
C语言实现单链表面试题—基础篇
https://blog.csdn.net/qq_37941471/article/details/78033970
C语言实现单链表面试题—进阶
https://blog.csdn.net/qq_37941471/article/details/80437143


代码实现:

#pragma once

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <windows.h>
#include <assert.h>

typedef int DataType;
typedef struct ListNode
{
    DataType data;//节点存放的数据
    struct ListNode* next;//下一个节点
}ListNode;

ListNode* BuyNode(DataType x)//创建节点
{
    ListNode* Node = (ListNode*)malloc(sizeof(ListNode));//开辟空间
    Node->data = x;
    Node->next = NULL;
    return Node;
}

void PrintList(ListNode *plist)//打印链表
{
    ListNode* cur = plist;
    while (cur)
    {
        printf("%d->",cur->data);
        cur = cur->next ;
    }
    printf("NULL\n");
}
void PushFront(ListNode **pplist,DataType x)//头插
{
    assert(pplist);
    //1. 链表为空
    //2. 非空
    if( *pplist == NULL )
    {
        *pplist = BuyNode(x);
    }
    else //非空 
    {
        ListNode* Node = BuyNode(x);
        Node->next = *pplist;
        *pplist = Node;
    }
}
void PopFront(ListNode **pplist)//头删
{
    assert(pplist);
    //1. 链表为空
    //2. 一个节点
    //3. 多节点
    if( *pplist == NULL )
        return;
    else if ( (*pplist)->next == NULL )
    {
        free(*pplist);
        *pplist = NULL;
    }
    else//多节点
    {
        ListNode* tmp  = *pplist;
        ListNode* Next = (*pplist)->next ;
        *pplist = Next;
        free(tmp);
    }
}
void PopBack(ListNode **pplist)//尾删
{
    assert(pplist);
    //1. 链表为空
    //2. 一个节点
    //3. 多个节点
    if( *pplist == NULL )
        return;
    else if( (*pplist)->next == NULL )
    {
        free(*pplist);//malloc free()
        *pplist = NULL;
    }
    else//多节点
    {
        ListNode* prev = *pplist;
        ListNode* cur = *pplist;
        while( cur->next )
        {
            prev = cur;
            cur = cur->next ;
        }
        free(cur);
        cur = NULL;
        prev->next = NULL;
    }
}
void Erase(ListNode **pplist,ListNode *pos)//删除pos节点
{
    assert(pplist&&pos);
    //1. 头删
    //2. 尾删
    //3. 中间删
    if( *pplist == pos )//头删
    {
        PopFront(pplist);
    }
    else if( pos->next == NULL ) //尾删
    {
        PopBack(pplist);
    }
    else //中间删
    {
        ListNode* prev = *pplist;
        while( prev->next != pos )
        {
            prev = prev->next ;
        }
        prev->next = pos->next ;
        free(pos);
        pos = NULL;
    }
}
ListNode* FindKNode(ListNode* plist,int k)
{
    ListNode* slow = plist;
    ListNode* fast = plist;
    int count = k;
    assert(plist);
    if( plist == NULL || k <=0 )
        return NULL;
 //快指针先走n步,然后快慢指针一起走,等快指针走完,慢指针就是要找的节点
    while( --count > 0){//n--走n步,--n走n-1步,而这走n-1步才是第n个节点
        fast = fast->next;
    }
    while( fast->next ){
        fast = fast->next;
        slow = slow->next;
    }
    return slow;
}
void test()//删除链表倒数第K个节点
{
    ListNode* list = NULL;

    PushFront(&list,4);
    PushFront(&list,3);
    PushFront(&list,2);
    PushFront(&list,1);
    PrintList(list);

    Erase(&list,FindKNode(list,2));//删除倒数第2个节点
    PrintList(list);
}
int main()
{
    test();
    return 0;
}

OJ下实现:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *removeNthFromEnd(ListNode *head, int n) {
        //相当于查找链表的倒数第n个节点,然后删掉pos位
        //1. 查找链表的倒数第n个节点   用快慢指针
        if( head == NULL || n <= 0 )
            return NULL;
        ListNode* slow = head;
        ListNode* fast = head;
        //快指针先走n步,然后快慢指针一起走,等快指针走完,慢指针就是要找的节点
        while( --n > 0){//n--走n步,--n走n-1步,而这走n-1步才是第n个节点
            fast = fast->next;
        }
        ListNode* prev = NULL;
        while( fast->next ){
            prev = slow;
            fast = fast->next;
            slow = slow->next;
        }
        //2. 删掉pos位,slow就是要删除的节点
        if( slow == head ){//头删
            head = head->next;
        }
        else{
            prev->next = slow->next;
        }
        return head;
    }
};

在VS下测试代码:

#pragma once

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <windows.h>
#include <assert.h>

typedef int DataType;
typedef struct ListNode
{
    DataType data;//节点存放的数据
    struct ListNode* next;//下一个节点
}ListNode;

ListNode* BuyNode(DataType x)//创建节点
{
    ListNode* Node = (ListNode*)malloc(sizeof(ListNode));//开辟空间
    Node->data = x;
    Node->next = NULL;
    return Node;
}

void PrintList(ListNode *plist)//打印链表
{
    ListNode* cur = plist;
    while (cur)
    {
        printf("%d->",cur->data);
        cur = cur->next ;
    }
    printf("NULL\n");
}
void PushFront(ListNode **pplist,DataType x)//头插
{
    assert(pplist);
    //1. 链表为空
    //2. 非空
    if( *pplist == NULL )
    {
        *pplist = BuyNode(x);
    }
    else //非空 
    {
        ListNode* Node = BuyNode(x);
        Node->next = *pplist;
        *pplist = Node;
    }
}
ListNode* removeNthFromEnd(ListNode *head, int n) {
        //相当于查找链表的倒数第n个节点,然后删掉pos位
        //1. 查找链表的倒数第n个节点   用快慢指针
        ListNode* prev = NULL;
        ListNode* slow = head;
        ListNode* fast = head;
        if( head == NULL || n <= 0 )
            return NULL;
        //快指针先走n步,然后快慢指针一起走,等快指针走完,慢指针就是要找的节点
        while( --n > 0){//n--走n步,--n走n-1步,而这走n-1步才是第n个节点
            fast = fast->next;
        }
        while( fast->next ){
            prev = slow;
            fast = fast->next;
            slow = slow->next;
        }
        //2. 删掉pos位,slow就是要删除的节点
        if( slow == head ){//头删
            head = head->next;
        }
        else{
            prev->next = slow->next;
        }
        return head;
    }
void test()//删除链表倒数第K个节点
{
    ListNode* list = NULL;

    PushFront(&list,4);
    PushFront(&list,3);
    PushFront(&list,2);
    PushFront(&list,1);
    PrintList(list);

    list = removeNthFromEnd(list,2);
    PrintList(list);//删除倒数第2个节点
}
int main()
{
    test();
    return 0;
}

“`

猜你喜欢

转载自blog.csdn.net/qq_37941471/article/details/80657210
今日推荐