代码随想录算法训练营第三天 | 203.移除链表元素 707.设计链表 206.反转链表

Leetcode 203.移除链表元素

class Solution {
public:
    ListNode* removeElements(ListNode* head, int val) {
        
        ListNode* dummyhead = new ListNode (0, head);
        ListNode* temp = dummyhead;

        while (temp->next != nullptr)
        {
            if (temp->next->val == val) 
            {
                temp->next = temp->next->next;
                
                // 上一步操作之后,temp->next就是新的了,并没有判断过,所以不要这一步
                // temp = temp->next;
            }
            else
            {
                temp = temp->next;
            }
        }

        return dummyhead->next;
    }
};
  1. dummyhead的作用为保存头节点的位置,因为头节点可能会被删除

  1. 创建一个临时节点temp, 当temp的next为空时即停止遍历,不用考虑temp现在是否等于val,因为在上一级已经考虑过temp会等于val的情况了

Leetcode 707.设计链表

class MyLinkedList {
public:

    typedef struct _node {
        int val;
        _node* next;
        _node(int val):val(val), next(nullptr) {}
    } Node;

    Node* dummyhead;   
    int size;

    // 这不是一个节点,这是一个类的构造函数
    MyLinkedList() {
        dummyhead = new Node(0); // 虚拟头节点, 不是真正的头节点
        size = 0;

        //printLinedList();
        //cout << size << endl;
    }
    
    int get(int index) {
        if (index < 0 || index > (size-1)) return -1;
        Node* curr = dummyhead->next;
        // cout << curr->val << endl;
        for (int i = 0; i < index; i++) curr = curr->next;
        return curr->val;
    }
    
    void addAtHead(int val) {
        Node* newNode = new Node(val);
        newNode->next = dummyhead->next;
        dummyhead->next = newNode;
        size++;

        //printLinedList();
        //cout << size << endl;
    }
    
    void addAtTail(int val) {
        Node* curr = dummyhead;
        Node* newtail = new Node(val);
        while (curr->next != nullptr) curr = curr->next;
        curr->next = newtail;
        size++;

        //printLinedList();
        //cout << size << endl;
    }
    
    void addAtIndex(int index, int val) {
        if (index > size) return;
        if (index < 0) index = 0;
        // 使用dummyhead 这样遍历的时候能够找到前一个node
        // 不用考虑dummyhead会不会溢出,因为有size能够得到链表的大小

        Node* temp = dummyhead;
        for (int i = 0; i < index; i++) temp = temp->next;

        // 如果index = size,那么此时temp是最后一个节点,temp的下一个节点为空节点
        // 先记录temp的下一个节点,无论这个节点是不是空节点, temp的下一个节点就是第index个节点
        Node* curr = temp->next;
        Node* newnode = new Node(val);
        newnode->next = curr;
        temp->next = newnode;

        size++;

        //printLinedList();
        //cout << size << endl;
    }
    
    void deleteAtIndex(int index) {
        if (index < 0 || index >= size) return;

        // 使用dummyhead 找到第index-1个node
        Node* temp = dummyhead;
        for (int i = 0; i < index; i++) temp = temp->next;
        Node* curr = temp->next;
        temp->next = curr->next;
        delete curr;

        size--;

    }

    void printLinedList()
    {
        Node* curr = dummyhead->next;
        while (curr != nullptr)
        {
            cout << curr->val << " ";
            curr = curr->next;
        }

        cout << endl;
    }
};
  1. 使用dummyhead可以找到curr的前一个node

  1. 在使用循环遍历寻找第index个node时,使用dummyhead找到了第index-1个node

  1. 当index < 0时,直接index = 0, 初始想法为用if判断,逻辑全部展开,不用如此复杂,可以简化

  1. 找到第index个node,同时涉及到需要操作第index-1个node时, 可以直接找第index-1个node, 简化操作,第index个就是第index-1个的下一个

  1. 写for循环里的判断条件要注意每个值意义

Leetcode 206.反转链表

初见想法:递归或者迭代

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        ListNode* pre = nullptr;
        ListNode* cur = head;

        // 链表可以先画个图
        while (cur != nullptr)
        {
            ListNode* temp = cur->next;
            cur->next = pre;
            pre = cur;
            cur = temp;
        }

        return pre;
    }
};
  1. 遍历链表,curr不断的指向pre,当cur为空时就结束

  1. 链表题可以画一个图

class Solution {
public:
    ListNode* reverseList(ListNode* head) {

        return traversal(nullptr, head);
    }

    // 根据遍历法,推算得出
    ListNode* traversal(ListNode* pre, ListNode* curr)
    {
        if (curr == nullptr) return pre;

        ListNode* temp = curr->next;
        curr->next = pre;
        return traversal(curr, temp);
    }
};
// 递归操作

traversal(....)
{    
    // 终止条件
    // 操作
    // traversal(....) 下一层
}
// 这种写法先操作,在往下一层去,有点类似遍历,直到终止条件停止

traversal(....)
{
    // 终止条件
    // traversal(......) 下一层
    // 操作 
}
// 这种写法为先到最底层再操作
  1. 递归函数先递归到最底层,然后最底层的最先返回

  1. 利用 return 来进入下一层, 无法确定 traversal的返回值时, 直接return, 只会返回一个值

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值