leetcode 剑指offer1-20

文章目录[剑指 Offer 03. 数组中重复的数字](https://leetcode-cn.com/problems/shu-zu-zhong-zhong-fu-de-shu-zi-lcof/)哈希表原地交换[剑指 Offer 04. 二维数组中的查找](https://leetcode-cn.com/problems/er-wei-shu-zu-zhong-de-cha-zhao-lcof/)模拟[剑指 Offer 05. 替换空格](https://leetcode-cn.com/problems/
摘要由CSDN通过智能技术生成

文章目录



剑指 Offer 03. 数组中重复的数字

找出数组中重复的数字。

在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。

示例 1:

输入:
[2, 3, 1, 0, 2, 5, 3]
输出:2 或 3 

哈希表

class Solution {
public:
    int findRepeatNumber(vector<int>& nums) {
        unordered_map<int,int> mp;
        for(auto& num:nums)
        {
            mp[num]++;
            if(mp[num]>1) return num;
        }
        return 0;
    }
};

原地交换

  • 通过原地交换,降低空间复杂度

https://leetcode-cn.com/problems/shu-zu-zhong-zhong-fu-de-shu-zi-lcof/solution/mian-shi-ti-03-shu-zu-zhong-zhong-fu-de-shu-zi-yua/

原地交换

class Solution {
public:
    int findRepeatNumber(vector<int>& nums) {
        int i = 0;//初始序号
        while(i < nums.size()) {//在范围内就不断循环
            if(nums[i] == i) {//加一个判断,当索引等于对应值,索引值自加才会触发
                i++;
                continue;
            }
            if(nums[nums[i]] == nums[i])//根据索引值来找值,发生重复
                return nums[i];
            swap(nums[i],nums[nums[i]]);
        }
        return -1;
    }
};
// 作者:jyd
// 链接:https://leetcode-cn.com/problems/shu-zu-zhong-zhong-fu-de-shu-zi-lcof/solution/mian-shi-ti-03-shu-zu-zhong-zhong-fu-de-shu-zi-yua/
// 来源:力扣(LeetCode)
// 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

剑指 Offer 04. 二维数组中的查找

在一个 n * m 的二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个高效的函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。

示例:

现有矩阵 matrix 如下:

[
  [1,   4,  7, 11, 15],
  [2,   5,  8, 12, 19],
  [3,   6,  9, 16, 22],
  [10, 13, 14, 17, 24],
  [18, 21, 23, 26, 30]
]

给定 target = 5,返回 true

给定 target = 20,返回 false

限制:

0 <= n <= 1000
0 <= m <= 1000

模拟

  • 从左下角一直往右上角走,一重循环解决问题
class Solution {
public:
    bool findNumberIn2DArray(vector<vector<int>>& matrix, int target) {
        int row = matrix.size();
        if(row==0) return false;
        int col = matrix[0].size();
        for(int i=row-1,j=0;i>=0&&j<col;)
        {
            if(matrix[i][j]==target) return true;
            else if(matrix[i][j]>target) i--;
            else j++;
        }
        return false;
    }
};

剑指 Offer 05. 替换空格

难度简单165

请实现一个函数,把字符串 s 中的每个空格替换成"%20"。

示例 1:

输入:s = "We are happy."
输出:"We%20are%20happy."

限制:

0 <= s 的长度 <= 10000

字符串

  • 遍历模拟一遍
class Solution {
public:
    string replaceSpace(string s) {
        string res;
        for(char& ch:s)
        {
            if(ch==' ')
            {
                res+="%20";
            }
            else
                res+=ch;
        }
        return res;
    }
};

原地修改

  • 增加一点时间开销,减小空间开销,第一遍遍历统计空格数量,第二遍遍历倒序修改。
class Solution {
public:
    string replaceSpace(string s) {
        int cnt = 0;
        int size = s.size();
        //统计空格数量
        for(char ch:s)
        {
            if(ch==' ') cnt++;
        }
        s.resize(size+cnt*2);
        int nsize = s.size();
        //更改原字符串
        for(int i=size-1,j=nsize-1;i<j;i--)
        {
            if(s[i]!=' ')
            {
                s[j--] = s[i];
            }
            else
            {
                s[j--] = '0';
                s[j--] = '2';
                s[j--] = '%';
            }
        }
        return s;
    }
};

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

难度简单195

输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)。

示例 1:

输入:head = [1,3,2]
输出:[2,3,1]

递归

  • 利用递归的性质,从后往前放入值,因为枚举结束后相当于返回上一层,但是枚举多了,会消耗额外的栈空间,增加空间消耗
class Solution {
private:
    vector<int> vct;//定义向量
    void recur(ListNode* head)//递归函数
    {
        if(head==NULL) return;//边界条件,节点为空
        recur(head->next);//递归下一节点
        vct.emplace_back(head->val);//往向量中放入对应值
    }
public:
    vector<int> reversePrint(ListNode* head) {
        recur(head);//递归,寻找头节点
        return vct;//返回向量
    }
};

辅助栈

  • 利用栈先进后出的性质,存储这些值,然后后面利用一层遍历循环,导出栈中的元素
class Solution {
public:
    vector<int> reversePrint(ListNode* head) {
        // recur(head);
        vector<int> vct;
        stack<int> st;
        while(head!=NULL)//终止条件
        {
            st.push(head->val);
            head= head->next;//不断枚举
        }
        while(!st.empty())
        {
            vct.emplace_back(st.top());//取栈顶元素
            st.pop();//弹出栈顶元素
        }
        return vct;
    }   
};

剑指 Offer 07. 重建二叉树

输入某二叉树的前序遍历和中序遍历的结果,请构建该二叉树并返回其根节点。

假设输入的前序遍历和中序遍历的结果中都不含重复的数字。

示例 1:

img

Input: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]
Output: [3,9,20,null,null,15,7]

示例 2:

Input: preorder = [-1], inorder = [-1]
Output: [-1]

限制:

0 <= 节点个数 <= 5000

递归+哈希表

class Solution {
public:
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        this->preorder = preorder;
        for(int i = 0; i < inorder.size(); i++)
            dic[inorder[i]] = i;
        return recur(0, 0, inorder.size() - 1);
    }
private:
    vector<int> preorder;
    unordered_map<int, int> dic;
    TreeNode* recur(int root, int left, int right) { 
        if(left > right) return nullptr;                        // 递归终止
        TreeNode* node = new TreeNode(preorder[root]);          // 建立根节点
        int i = dic[preorder[root]];                            // 划分根节点、左子树、右子树
        node->left = recur(root + 1, left, i - 1);              // 开启左子树递归
        node->right = recur(root + i - left + 1, i + 1, right); // 开启右子树递归
        return node;                                            // 回溯返回根节点
    }
};

// 作者:Krahets
// 链接:https://leetcode-cn.com/leetbook/read/illustration-of-algorithm/99ljye/
// 来源:力扣(LeetCode)
// 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

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

用两个栈实现一个队列。队列的声明如下,请实现它的两个函数 appendTail 和 deleteHead ,分别完成在队列尾部插入整数和在队列头部删除整数的功能。(若队列中没有元素,deleteHead 操作返回 -1 )

示例 1:

输入:
["CQueue","appendTail","deleteHead","deleteHead"]
[[],[3],[],[]]
输出:[null,null,3,-1]

提示:

  • 1 <= values <= 10000
  • 最多会对 appendTail、deleteHead 进行 10000 次调用

双辅助栈

  • 一个栈模拟入队列,另一个栈模拟出队列

栈st1模拟入队列࿰

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值