[leetcode]剑指offer(C++版题解)

第一天

剑指 Offer 09. 用两个栈实现队列

->点这里进入leetcode
在这里插入图片描述
这道题的意思就是让我们使用两个栈实现一个队列,
简单复习一下:
栈:先进后出(栈顶进出元素)
队列:先进先出(队列头出元素,队列尾进元素)
我们会发现栈可以做到队列尾进元素,但是如何让栈底出元素是一个问题
我们会想到将一个栈的元素依次出栈放到另外一个栈中的时候,他的元素是不是会倒过来,例如:
在这里插入图片描述
这样我们是不是就可以在A栈进元素,B栈出元素构成了一个先进先出的队列。
代码:

class CQueue {
public:
    stack<int> a;
    stack<int> b;
    CQueue() {

    }
    //添加元素
    void appendTail(int value) {
        a.push(value);          //元素进队列直接将元素放入a栈即可
    }
    //删除元素
    int deleteHead() {
        int e;
        if(a.empty())         //这个很重要,如果a栈空会出错
            return -1;
        while(!a.empty())     //将a栈元素->b栈
         {
             e = a.top();
             a.pop();
             b.push(e);
         }
        int res = b.top();   //提取并删除b栈栈顶元素
        b.pop();
        while(!b.empty())    //将b栈元素->a栈
        {
             e = b.top();
             b.pop();
             a.push(e);
        }
        return res;
    }
    
};

/**
 * Your CQueue object will be instantiated and called as such:
 * CQueue* obj = new CQueue();
 * obj->appendTail(value);
 * int param_2 = obj->deleteHead();
 */

剑指 Offer 30. 包含min函数的栈

->点击这里进入leetcode
在这里插入图片描述
本题难点:
我们第一时间想到的肯定是将整个栈遍历一遍,找最小的元素,但是它会调用多次,每一次的时间复杂度都是O(n),这样肯定会超时。
解题思路:
建立两个栈:
数据栈A:存放栈的数据,入栈、出栈、获取栈顶元素都是正常的逻辑
辅助栈B:实现栈A中的最小元素始终对应着栈B的栈顶元素。
这样和普通的栈有什么不一样呢?
其中
pop() 时两栈栈顶元素同时出栈
push():时A栈正常,B栈则需要对比B栈栈顶元素和进栈元素,谁小,让谁进栈,这样就达成了栈A中的最小元素始终对应着栈B的栈顶元素(注意:当B栈为空的时候元素直接进栈即可)
**min()😗*取B栈栈顶元素即可。
举例:
在这里插入图片描述
代码:

class MinStack {
public:
    stack<int> s;//栈A
    stack<int> ad;//辅助栈
    /** initialize your data structure here. */
    MinStack() {

    }
    
    void push(int x) {
        s.push(x);
        if(ad.empty())        ad.push(x);//栈B为空,直接进栈
        else 
        {
            if(x < ad.top()) ad.push(x);
            else             ad.push(ad.top()); 
        }
    }
    
    void pop() {
        s.pop();
        ad.pop();
    }
    
    int top() {
        return s.top();
    }
    
    int min() {
        return ad.top();
    }
};

/**
 * Your MinStack object will be instantiated and called as such:
 * MinStack* obj = new MinStack();
 * obj->push(x);
 * obj->pop();
 * int param_3 = obj->top();
 * int param_4 = obj->min();
 */

当然,它还可以优化,可以将栈B重复元素去掉,减少空间复杂度,这样只用在pop()和min()的时候判断一下就可以了。

第二天

剑指 Offer 06. 从尾到头打印链表

在这里插入图片描述

这道题比较简单直接上代码:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    vector<int> reversePrint(ListNode* head) {
        vector<int> res;
        ListNode* p;
        p = head;
        while(p)
        {
            res.insert(res.begin(),p->val);
            p = p->next;
        }
        return res;
    }
};

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

在这里插入图片描述
这道题也比较简单:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        if(!head) return head;
        //ListNode* head2 = (ListNode*)malloc(sizeof(ListNode));
        ListNode* head2 = new ListNode;
        ListNode* p = head;
        ListNode* q = p->next;
        head2->next = NULL;
        while(q)
        {
            p->next = head2->next;
            head2->next = p;
            p=q;
            q = q->next;
        }
        head2->val = p->val;
        return head2;
    }
};

其实以上两道题我都使用了头插法的思想,你可以把输入的链表想象成一个序列,而用头插法就可以把他们反过来

剑指 Offer 35. 复杂链表的复制

在这里插入图片描述
本题难点:
加入了random指针,我们按照正常的思路复制的话,random指针难以处理;
解题方案:
使用哈希表映射,我们将每一个节点都复制一遍,也就是哈希表每个元素对应的映射,在复制random指针的时候,就可以在新建立的链表中根据映射找到对应的节点:
代码:

/*
// Definition for a Node.
class Node {
public:
    int val;
    Node* next;
    Node* random;
    
    Node(int _val) {
        val = _val;
        next = NULL;
        random = NULL;
    }
};
*/
class Solution {
public:
    Node* copyRandomList(Node* head) {
        map<Node*,Node*> m;
        Node* p = head;
        while(p)
        {
            m[p] = new Node(p->val);
            p = p->next;
        }
        p = head;
        while(p)
        {
            m[p]->next = m[p->next];
            m[p]->random = m[p->random];
            p = p->next;
        }
        return m[head];
    }
};

有待更新。。。。

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小光学嵌入式

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值