非科班选手的刷题学习记录Day4

本文解析了五个编程题目,涉及计算幂、最小值栈、验证栈序列、二叉树层序打印和字符串排列。通过递归和栈的操作,讲解了如何在O(logn)时间内完成幂运算,并演示了如何设计高效的栈和队列数据结构。适合提升算法和数据结构能力。
摘要由CSDN通过智能技术生成

目录

1. ​​​​​​剑指 Offer 16. 数值的整数次方

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

3. 946. 验证栈序列

4. 剑指 Offer 32 - I. 从上到下打印二叉树

5. 剑指 Offer 38. 字符串的排列


还在剑指扫盲中...


难度中等292

实现 pow(x, n) ,即计算 x 的 n 次幂函数(即,xn)。不得使用库函数,同时不需要考虑大数问题。

示例 1:

输入:x = 2.00000, n = 10
输出:1024.00000

示例 2:

输入:x = 2.10000, n = 3
输出:9.26100

示例 3:

输入:x = 2.00000, n = -2
输出:0.25000
解释:2-2 = 1/22 = 1/4 = 0.25

提示:

  • -100.0 < x < 100.0
  • -231 <= n <= 231-1
  • -104 <= xn <= 104

这道题可以用递归实现求幂,把对x求n次方化为求n/2、n/4次方...直到n=0时x的0次方为1,这样时间复杂度就是O(logn),空间复杂度也是O(logn)。(递归函数调用会使用栈空间)递归过程中注意当n为奇数时要多乘一个x。

class Solution {

public:

    double traversal(double x, int n){

        if(n == 0){

            return 1.0;

        }

        double temp = traversal(x,n / 2);

        return n % 2 ? x * temp * temp : temp * temp;//直接用traversal(...)超时

    }

    double myPow(double x, int n) {

        return n >= 0 ? traversal(x,n) : traversal(1.0 / x,n);

    }

};

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

难度简单331

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

示例:

MinStack minStack = new MinStack();
minStack.push(-2);
minStack.push(0);
minStack.push(-3);
minStack.min();   --> 返回 -3.
minStack.pop();
minStack.top();      --> 返回 0.
minStack.min();   --> 返回 -2.

提示:

  1. 各函数的调用总次数不超过 20000 次

定义一个栈用来正常的出入栈,另一个栈用于存放当前的最小值以便用O(1)复杂度获取,每次入栈元素小于最小栈栈顶才压入最小栈,每次出栈时如果是最小值要弹出最小栈。

class MinStack {

private:

    stack<int> stk;//用来正常出入

    stack<int> minStk;//存放最小值 

public:

    /** initialize your data structure here. */

    MinStack() {

    }

    void push(int x) {

        stk.push(x);

        if(minStk.empty()){

            minStk.push(x);

        }

        else if(x <= minStk.top()){

            minStk.push(x);

        }

    }   

    void pop() {

        if(!stk.empty() && !minStk.empty()){

            if(minStk.top() == stk.top()){

                minStk.pop();

            }

            stk.pop();

        }

    }    

    int top() {

        return stk.top();

    }   

    int min() {

        return minStk.top();

    }

};

3. 946. 验证栈序列

难度中等238

给定 pushed 和 popped 两个序列,每个序列中的 值都不重复,只有当它们可能是在最初空栈上进行的推入 push 和弹出 pop 操作序列的结果时,返回 true;否则,返回 false 。

示例 1:

输入:pushed = [1,2,3,4,5], popped = [4,5,3,2,1]
输出:true
解释:我们可以按以下顺序执行:
push(1), push(2), push(3), push(4), pop() -> 4,
push(5), pop() -> 5, pop() -> 3, pop() -> 2, pop() -> 1

示例 2:

输入:pushed = [1,2,3,4,5], popped = [4,3,5,1,2]
输出:false
解释:1 不能在 2 之前弹出。

提示:

  • 1 <= pushed.length <= 1000
  • 0 <= pushed[i] <= 1000
  • pushed 的所有元素 互不相同
  • popped.length == pushed.length
  • popped 是 pushed 的一个排列

题意相当于pushed经过一系列出入栈操作能否变成popped。因此定义一个栈来模拟pushed的出入,从pushed第一个元素开始入栈,如果栈顶元素等于popped当前的元素则出栈,再比较新的栈顶元素和popped的下一个元素【注意不是if】,直到栈顶和popped当前的元素不相等,此时再把pushed的下一个元素压入栈。当pushed所有元素都已经入栈后,如果栈为空,说明pushed可以经过出入栈变成popped。

class Solution {

public:

    bool validateStackSequences(vector<int>& pushed, vector<int>& popped) {

        stack<int> stk;

        int pushedId = 0, popedId = 0;

        for(;pushedId < pushed.size();pushedId++){

            stk.push(pushed[pushedId]);

            while(!stk.empty() && popped[popedId] == stk.top()){

                stk.pop();

                popedId++;

            }

        }

        if(stk.empty()){

            return true;

        }

        return false;

    }

};

4. 剑指 Offer 32 - I. 从上到下打印二叉树

难度中等191

从上到下打印出二叉树的每个节点,同一层的节点按照从左到右的顺序打印。

例如:
给定二叉树: [3,9,20,null,null,15,7],

    3
   / \
  9  20
    /  \
   15   7

返回:

[3,9,20,15,7]

提示:

  1. 节点总数 <= 1000

用队列实现层序遍历,重拳出击吧:

class Solution {

public:

    vector<int> levelOrder(TreeNode* root) {

        queue<TreeNode*> que;

        vector<int> ret;

        if(root == nullptr){

            return {};

        }

        que.push(root);

        while(!que.empty()){

            int len = que.size();

            for(int i = 0; i < len; i++){

                TreeNode* cur = que.front();

                ret.push_back(cur -> val);

                que.pop();

                if(cur -> left){

                    que.push(cur -> left);

                }

                if(cur -> right){

                    que.push(cur -> right);

                }

            }

        }

        return ret;

    }

};

5. 剑指 Offer 38. 字符串的排列

难度中等544

输入一个字符串,打印出该字符串中字符的所有排列。

你可以以任意顺序返回这个字符串数组,但里面不能有重复元素。

示例:

输入:s = "abc"
输出:["abc","acb","bac","bca","cab","cba"]

限制:

1 <= s 的长度 <= 8

典型的回溯题目,注意s包含重复字符,要在树层进行去重:

class Solution {

public:

    string temp;

    vector<string> ret;

    void backTrack(string& s,vector<bool>& used){

        if(temp.size() == s.size()){

            ret.push_back(temp);

            return;

        }

        for(int i = 0; i < s.size(); i++){

            if(i > 0 && s[i] == s[i - 1] && used[i - 1] == true){

                continue;

            }

            if(used[i] == false){//某个字符被重复使用

                used[i] = true;

                temp.push_back(s[i]);

                backTrack(s,used);

                temp.pop_back();

                used[i] = false;

            }

        }

    }

    vector<string> permutation(string s) {

        vector<bool> used(s.size(),false);

        sort(s.begin(),s.end());

        backTrack(s,used);

        return ret;

    }

};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值