链表的刷题心得

1.两两交换链表中的节点

leetcode 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) {

        int i=1;

        int k=0;

        ListNode* a=new ListNode(0);

        a->next=head;

        ListNode* swa=head;

        ListNode* swa1=nullptr;

        while(swa){

            if(i%2==0){

                k=swa->val;

                swa->val=swa1->val;

                swa1->val=k;

                swa1=swa;

                swa=head->next;

                head=head->next;

            }

            else{

                swa1=swa;

                swa=head->next;

                head=head->next;    

            }

            i++;

        }

        a = a->next;

        return a;

    }

};

思想是双指针,一前一后,偶数就交换,否则就先前走的简单思想。

2.反转链表

代表为leetcode的206题目

也是参考双指针的做法,改变了链表的next的走向就可以了。

这个画个图就很好理解了,注意temp = cur->next;,是让temp指向cur下一个目标,而cur->next = pre才是把链表翻转,注意next这个,这个才是连接链表的关键

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        ListNode* temp; // 保存cur的下一个节点
        ListNode* cur = head;
        ListNode* pre = NULL;
        while(cur) {
            temp = cur->next;  // 保存一下 cur的下一个节点,因为接下来要改变cur->next
            cur->next = pre; // 翻转操作
            // 更新pre 和 cur指针
            pre = cur;
            cur = temp;
        }
        return pre;
    }
};

3.删除链表的倒数N个节点

该题为leetcode 19

给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。

示例 1:

输入:head = [1,2,3,4,5], n = 2
输出:[1,2,3,5]

示例 2:

输入:head = [1], n = 1
输出:[]

示例 3:

输入:head = [1,2], n = 1
输出:[1]

提示:

  • 链表中结点的数目为 sz
  • 1 <= sz <= 30
  • 0 <= Node.val <= 100
  • 1 <= n <= sz

刷题心得:对于链表,使用虚拟头节点+类似于双指针法进行操作容易解决很多问题。

第一:先用ListNode* new_head =new ListNode(0),连接head,此时就有了一条虚拟头接点的链表。然后,旧的head为新链表的下一个节点,就很轻而易举的操作整条链表。其中begin =new_head操作,可以想象为这个begin也是一个虚拟头节点。

第二:操作begin比end多n+1个位置,因为要删除倒数第n个节点,那么end应该是它的上一个节点,则直接使用end->next=end->next->next;跳过第N个节点就可以了。

最重要的是链表的移动这个问题,begin = begin->next;这样就进行了链表的点的移动,因为begin也是新的链表的一个虚拟头节点,所以可以这样操作

/**

 * 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* begin ;

        ListNode* new_head =new ListNode(0);

        new_head->next=head;

        ListNode* end=new_head;

        begin =new_head;

        while(n--&&begin!=NULL){

            begin = begin->next;  

        }

        begin =begin->next;

        while(begin != nullptr){

            begin =begin->next;

            end =end->next;

        }

        end->next=end->next->next;

        return new_head->next;

    }

};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值