算法训练营第三天 | LeetCode 203 移除链表元素 LeetCode 707设计链表 LeetCode 206反转链表 LeetCode

链表理论基础

struct LisiNode {
    int val;
    ListNode* next;
    ListNode() {
        val = 0;
        next = nullptr;
    }
    ListNode(int v) {
        val = val;
        next = nullptr;
    }
    ListNode(int v, ListNode* n) {
        val = v;
        next = n;
    }
};

链表节点是一个结构体,内部有一个指针,保存它逻辑结构上的下一个节点的位置。内部构造函数有如上三种写法,根据需要取其中两种即可。定义时采用对应的构造函数用new来实现或者直接定义对应的指针即可。

今天的链表专题主要是关于头结点的。实际上我之前在面试时候遇到链表题目的时候,就下意识3定义了之前一刷时候用过的虚拟头节点,但是我直接把头节点的值赋给它并且还没怎么实际用到。那是一道移除链表中重复元素的题目。面试官还说了我定义了一个虚拟头节点啊,但是后面就没说了因为我没咋用。最后花的时间也挺多还没调出来。今天重点用虚拟头节点实现一下几道题目。

LeetCode 203 移除链表元素

这种类型题目我之前一般都要花蛮多时间才能解出来,这次只花了几分钟。都是虚拟头节点的功劳了。它让我避免了很多复杂的情况,只需要花费O(1)的时间代价,就能够达到将prev节点用作i,cur节点用作j的情况来像对数组进行操作那样对链表进行同样的操作。就如同数据结构中链表结构中使用的for循环+下标对链表元素进行遍历一般方便了。

代码如下:

class Solution {
public:
    ListNode* removeElements(ListNode* head, int val) {
        ListNode* virtualHead = new ListNode(0, head);
        ListNode* cur = head;
        ListNode* prev = virtualHead;
        while (prev && prev->next) {
            if (prev->next->val == val) {
                cur = prev->next;
                while (cur && cur->val == val) {
                    if (cur->next) cur = cur->next;
                    else cur = nullptr; 
                }
                prev->next = cur;
                prev = prev->next;
            } else {
                prev = prev->next;
            }
        }
        head = virtualHead->next;
        delete virtualHead;
        return head;
    }
};

LeetCode 707 设计链表

这题一刷时候就遇到了两个bug,修改之后过了。二刷还是遇到了。通过修改两个bug,得出了最后结果。主要是在deleteAtIndex和addAtIndex时cnt和index比较条件的不同。前者是cnt和index + 1比较,后者是cnt和index比较。这次在理解了new和delete(通过内存池去理解的)的前提之上,自己还加了一个deleteAll作为防止内存泄漏的析构函数

代码如下:

/*struct ListNode {
    int val;
    ListNode* next;
    ListNode() {
        val = 0; next = nullptr;
    }
    ListNode(int v) {
        val = v; next = nullptr;
    }
    ListNode(int v, ListNode* n) {
        val = v; next = n;
    }
};*/

class MyLinkedList {
private:
    ListNode* virtualHead;
    ListNode* prev;
    ListNode* cur;
    ListNode* newNode;
    int cnt;
public:
    MyLinkedList() {
        virtualHead = new ListNode(0, nullptr);
        prev = cur = virtualHead;
        cnt = 0;
    }
    
    int get(int index) {
        if (index + 1 > cnt) return -1;
        prev = virtualHead;
        for (int i = 0; i <= index; i++) {
            prev = prev->next;
        }
        return prev->val;
    }
    
    void addAtHead(int val) {
        ListNode* newNode = new ListNode(val, virtualHead->next);
        virtualHead->next = newNode;
        cnt++;
    }
    
    void addAtTail(int val) {
        cur = virtualHead;
        while (cur && cur->next) {
            cur = cur->next;
        }
        cur->next = new ListNode(val);
        cnt++;
    }
    
    void addAtIndex(int index, int val) {
        if (index > cnt) return;
        prev = virtualHead;
        for (int i = 0; i < index; i++) {
            prev = prev->next;
        }
        newNode = new ListNode(val, prev->next);
        prev->next = newNode;
        cnt++;
    }
    
    void deleteAtIndex(int index) {
        if (index + 1 > cnt) return;
        prev = virtualHead;
        for (int i = 0; i < index; i++) {
            prev = prev->next;
        }
        cur = prev->next;
        if (cur->next) {
            prev->next = cur->next;
        } else {
            prev->next = nullptr;
        }
        cnt--;
    }
    void deleteAll() {
        ListNode* temp = virtualHead;
        cur = virtualHead;
        while (cur && cur->next) {
            temp = cur;
            cur = cur->next;
            delete temp;
        }
        temp = cur;
        delete temp;
    }
};

/**
 * Your MyLinkedList object will be instantiated and called as such:
 * MyLinkedList* obj = new MyLinkedList();
 * int param_1 = obj->get(index);
 * obj->addAtHead(val);
 * obj->addAtTail(val);
 * obj->addAtIndex(index,val);
 * obj->deleteAtIndex(index);
 */

LeetCode 206 反转链表

我人都啥掉了,一直超时,也看不出来原因是什么,先放代码,之后再看看吧。

/**
 * 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* reverseList(ListNode* head) {
        if (!head) return head;
        ListNode* virtualHead = new ListNode(0, head);
        ListNode* prev = virtualHead;
        ListNode* cur = head;
        while (cur && cur->next) {
            ListNode* temp = cur->next;
            cur->next = prev;
            prev = cur;
            cur = temp;
        }
        cur->next = prev;
        head = cur;
        while (cur && cur->next) {
            prev = cur;
            cur = cur->next;
        }
        prev->next = nullptr;
        delete virtualHead;
        return head;
    }
};

晚上结合打印输出发现是第二个循环进入死循环了。原因是我把virtualHead初始化时候next指针指向head节点了,这样后面想去尾的时候就会从尾再到头再循环下去,改成如下的形式就能解决了。记得腾讯客户端一次面试也是这种类型题目挂的,哎。说多了都是泪。

  • 9
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值