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