链表的一些小知识

24两两交换链表中的节点

19删除链表中倒数第N个节点

对于24题从这三张图就可以完美写出来了,一种迭代的思想,链表中迭代思想,很大程度需要建立一个虚拟的头节点。

 

 

 迭代的重复的以上的三个步骤,就可以完成这个题目

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        //我先设置一个判断就是如果他是空链表或者链表中只有一个元素,我就不需要交换了
        if(head == NULL || head->next == NULL)
        {
            return head;
        }
        ListNode *dummyHead = new ListNode(0); //设置虚拟的头节点
        dummyHead->next = head;
        ListNode *cur = dummyHead; 
        ListNode *tmp;
        //我刚开始写的while语句的时候判断语句只写了cur->next != NULL 但是leetcode的实例中链表中的节点个数会出现奇数个,例如出现3个前面两个交换后面那个不动,所以要判断他是否有右相邻的节点。
        while(cur->next != NULL && cur->next->next != NULL)  
        {
            ListNode *tmp2 = cur->next->next->next;
            tmp = cur->next;
            cur->next = tmp->next; // 步骤一
            cur->next->next = tmp;//步骤二
            cur->next->next->next = tmp2;//步骤三
            cur = cur->next->next;
        }
        head = dummyHead->next;
        delete dummyHead;
        return head;
    }
};

对于19题我的思想就是先遍历一遍链表长度,然后再遍历链表找到我们要删除节点的前一个位置,删除节点,使用虚拟头节点,这样方便对于头节点的删除,让删除操作都统一不用单独再分类。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode *dummyHead = new ListNode(0);
        dummyHead->next = head;
        ListNode *cur = dummyHead;
        int size = 0;//记录链表中有几个节点
        while(cur != nullptr)
        {
            size++;
            cur = cur->next;
        }
        if(size == 1)
        {
            return nullptr;
        }
        cur = dummyHead;
        size = size-n-1;
        while(size--)
        {
            cur = cur->next;
        }
        ListNode *tmp = cur->next;
        cur->next = cur->next->next;
        delete tmp;
        return dummyHead->next;
    }
};

题目中说可以尝试一下用一趟扫描实现,实现这样需要用到是双指针的思想一个快指针一个是慢指针。

1.初始化两个指针,都指向虚拟头节点位置

        ListNode *dummyHead = new ListNode(0);
        dummyHead->next = head;
        ListNode *fast = dummyHead;
        ListNode *slow = dummyHead;

2.fast首先走n+1步,为什么是n+1呢,因为只有这样同时移动的时候slow才能指向删除节点的上一个节点(方便操作) 

 while(n-- && fast != NULL) {
            fast = fast->next;
        }
        fast = fast->next; // fast再提前走一步,因为需要让slow指向删除节点的上一个节点

 3.fast和slow同时移动,直到fast指向末尾

        while (fast != NULL) {
            fast = fast->next;
            slow = slow->next;
        }

 我的代码思路和上面2和3有点出处,但是大概思想也是一样,我是让fast指针指到最后一个节点而不是指向NULL,然后我就不需要让fast指针提前移动n+1下,只需要移动n下就行,然后在slow和fast指针同时移动的时候,多加一个判断就是fast->next != NULL,这个判断出来fast指针是否到达最后一个节点了。

        while(n-- && fast != nullptr)
        {
            fast = fast->next;
        }
        while(fast!=nullptr && fast->next != nullptr)
        {
            fast = fast->next;
            slow =slow->next;
        }

4.删除slow指向的下一个节点

        ListNode *tmp = slow->next;
        slow->next = tmp->next;
        delete tmp;
        head = dummyHead->next;
        delete dummyHead;
        return head;

 这点需要注意的是,leetcode中不删除节点也能通过编译,但是在实际开发中,C++不像python,java有自动回收机制,C++需要手动释放,所以我们当开辟了一个新的区域的时候,需要手动删除,例如我们创建了一个虚拟节点,是在堆区开辟的内存,所以我们需要delete删除。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值