滑动窗口最大值

2024-01-29

239. 滑动窗口最大值 - 力扣(LeetCode)

题目

给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。

返回 滑动窗口中的最大值

示例 1:

输入:nums = [1,3,-1,-3,5,3,6,7], k = 3
输出:[3,3,5,5,6,7]
解释:
滑动窗口的位置                最大值
---------------               -----
[1  3  -1] -3  5  3  6  7       3
 1 [3  -1  -3] 5  3  6  7       3
 1  3 [-1  -3  5] 3  6  7       5
 1  3  -1 [-3  5  3] 6  7       5
 1  3  -1  -3 [5  3  6] 7       6
 1  3  -1  -3  5 [3  6  7]      7

示例 2:

输入:nums = [1], k = 1
输出:[1]

提示:

  • 1 <= nums.length <= 10^5s
  • -10^4 <= nums[i] <= 10^4
  • 1 <= k <= nums.length

解决方案1

思路

结构、方法选择

要求得每k个的最大值,那么我就可以使用一个单调递减队列。 可以看出这个题是滑动窗口思想,所以我需要两个变量记录窗口的左边界和右边边界。

首先考虑前k个元素

  1. 从队尾和当前元素比较,小于当前元素则删除队尾,直到队尾大于新元素或者队空。新元素入队。
  2. 输出当前最大值。

窗口开始移动。

  1. 看窗口左边界,如果左边界是当前最大值,因为左边界即将不在考虑范围,所以删去队首。 如果左边界不是最大值,什么也不做。
  2. 窗口移动,左边界++,右边界++。
  3. 这时右侧有一个新值进入考虑范围。 从队尾和当前元素比较,小于当前元素则删除队尾,直到队尾大于新元素或者队空。新元素入队。

代码

class Solution {
public:
    vector maxSlidingWindow(vector& nums, int k) {
        if(nums.size() == 0 || k == 0) return {};
        deque deque;
        vector res(nums.size() - k + 1);

        // 形成k长的窗口前
        for(int i = 0; i < k; i++) {
            while(!deque.empty() && deque.back() < nums[i])
                deque.pop_back();
            deque.push_back(nums[i]);
        }
        res[0] = deque.front();

        // 形成窗口后,窗口移动
        for(int i = k; i < nums.size(); i++) {
            if(deque.front() == nums[i - k])
                deque.pop_front();
            while(!deque.empty() && deque.back() < nums[i])
                deque.pop_back();
            deque.push_back(nums[i]);
            res[i - k + 1] = deque.front();
        }
        return res;
    }
};

114. 二叉树展开为链表

题目

给你二叉树的根结点 root ,请你将它展开为一个单链表:

  • 展开后的单链表应该同样使用 TreeNode ,其中 right 子指针指向链表中下一个结点,而左子指针始终为 null

  • 展开后的单链表应该与二叉树 先序遍历 顺序相同。

  • 示例 1:

    滑动窗口最大值_第1张图片

    输入:root = [1,2,5,3,4,null,6]
    输出:[1,null,2,null,3,null,4,null,5,null,6]
    

    示例 2:

    输入:root = []
    输出:[]
    

    示例 3:

    输入:root = [0]
    输出:[0]
    

    提示:

    • 树中结点数在范围 [0, 2000]
    • -100 <= Node.val <= 100

解决方案1

思路

结构、方法选择

先序遍历,使用队列存储元素。之后依次出队,修改指针。

代码

class Solution {
public:
    queueq;
    void traverse(TreeNode* root)
    {
        if(root==nullptr)return;
        q.push(root);
        traverse(root->left);
        traverse(root->right);
    }
    void flatten(TreeNode* root) {
        traverse(root);
        TreeNode* pre = nullptr;
        while(!q.empty())
        {
            TreeNode* tmp = q.front();
            q.pop();
            if(pre!=nullptr)
            {
                pre->right = tmp;
                pre->left = nullptr;
            }
            pre  = tmp;
        }
    }
};

解决方案2

思路

要求最后连接的顺序是先序遍历(根左右)的顺序,那么去按照完全相反(右左根)的顺序遍历。并且记录每一步的节点。

每次遍历的当前节点的right指向的节点应该是上一个遍历到的节点,根据保存的节点就可以进行连接。

代码

class Solution {

public:
    TreeNode* preNode = nullptr;
    void flatten(TreeNode* root) {
        if (root == NULL) return;
        flatten(root->right);
        flatten(root->left);
        root->left = NULL;
        root->right = preNode;
        preNode = root;
    }
};

你可能感兴趣的:(算法,leetcode,数据结构)