力扣刷题笔记-栈和链表

刷题笔记

001.定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的 min 函数在该栈中,调用 min、push 及 pop 的时间复杂度都是 O(1)。

class MinStack {
public:
    /** initialize your data structure here. */
    long long num_min;
    stack<long long> stack_diff;
    MinStack() {
    }
    
    void push(int x) {
        if(stack_diff.empty())
        {
            num_min = x;
            stack_diff.push(0);
            return;
        }
        stack_diff.push((long long)x-num_min);
        if(x < num_min)
        {
            num_min = x;
        }
    }
    
    void pop() {
        if(stack_diff.top() < 0)
        {
            num_min -= stack_diff.top();
        }
        stack_diff.pop();
    }
    
    int top() {
        if(stack_diff.top() >= 0)
        {
            return stack_diff.top()+num_min;
        }
        else
        {
            return num_min;
        }
    }
    
    int min() {
        return num_min;
    }
};

这种方法是不使用备用栈的方法,总体的思路是栈中存储的是与当前最小值的差值,即:x-min。
在进行出栈行为时,再把当前的值对应的最小值加上就是初始值。
注意处理好第一个进栈的元素,放0.

002.定义一个函数,输入一个链表的头节点,反转该链表并输出反转后链表的头节点。

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        if (!head || !head->next) {
            return head;
        }
        ListNode* newHead = reverseList(head->next);
        head->next->next = head;
        head->next = nullptr;
        return newHead;
    }
};

假设链表从节点Nk+1~Nm都已经转换过来,此时我们正处在Nk。
我们希望Nk+1的下个结点指向Nk,所以Nk.next=nk。
需要注意的是N1的下一个节点必须指向∅。如果忽略了这一点,链表中可能会产生环

003.请实现 copyRandomList 函数,复制一个复杂链表。在复杂链表中,每个节点除了有一个 next 指针指向下一个节点,还有一个 random 指针指向链表中的任意节点或者 null。

class Solution {
public:
    unordered_map<Node*, Node*> cachedNode;

    Node* copyRandomList(Node* head) {
        if (head == nullptr) {
            return nullptr;
        }
        if (!cachedNode.count(head)) {
            Node* headNew = new Node(head->val);
            cachedNode[head] = headNew;
            headNew->next = copyRandomList(head->next);
            headNew->random = copyRandomList(head->random);
        }
        return cachedNode[head];
    }
};

本题要求我们对一个特殊的链表进行深拷贝。如果是普通链表,我们可以直接按照遍历的顺序创建链表节点。而本题中因为随机指针的存在,当我们拷贝节点时,「当前节点的随机指针指向的节点」可能还没创建,因此我们需要变换思路。一个可行方案是,我们利用回溯的方式,让每个节点的拷贝操作相互独立。对于当前节点,我们首先要进行拷贝,然后我们进行「当前节点的后继节点」和「当前节点的随机指针指向的节点」拷贝,拷贝完成后将创建的新节点的指针返回,即可完成当前节点的两指针的赋值。
具体地,我们用哈希表记录每一个节点对应新节点的创建情况。遍历该链表的过程中,我们检查「当前节点的后继节点」和「当前节点的随机指针指向的节点」的创建情况。如果这两个节点中的任何一个节点的新节点没有被创建,我们都立刻递归地进行创建。当我们拷贝完成,回溯到当前层时,我们即可完成当前节点的指针赋值。注意一个节点可能被多个其他节点指向,因此我们可能递归地多次尝试拷贝某个节点,为了防止重复拷贝,我们需要首先检查当前节点是否被拷贝过,如果已经拷贝过,我们可以直接从哈希表中取出拷贝后的节点的指针并返回即可。
在实际代码中,我们需要特别判断给定节点为空节点的情况。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值