IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 双端队列(Deque) -> 正文阅读

[数据结构与算法]双端队列(Deque)

71. 简化路径

知识点: 用队列实现栈 Deque, ArrayDeque, pollLast, offer, equals, split, join.

class Solution {
    public String simplifyPath(String path) {
        Deque<String> stack = new ArrayDeque<String>();
        for (String p : path.split("/")) {
            if ("..".equals(p)) {
                if (!stack.isEmpty()) stack.pollLast();
            } 
            else if (p.length() > 0 && !".".equals(p)) {
                stack.offerLast(p);
            }
        }
        // StringBuilder ans = new StringBuilder();
        // if (stack.isEmpty()) ans.append('/');
        // else {
        //     while (!stack.isEmpty()) {
        //         ans.append('/');
        //         ans.append(stack.pollFirst());
        //     }
        // }
        // return ans.toString();

        return "/" + String.join("/", stack);
    }
}

239. 滑动窗口最大值

heapq 库中的堆默认是最小堆

class Solution:
    def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]: 
    	## 方法一:优先队列 最大堆
        q = [(-nums[i], i) for i in range(k)]
        heapq.heapify(q)
        res = [-q[0][0]]
        for i in range(k, len(nums)):
            heapq.heappush(q, (-nums[i], i))
            while q[0][1] <= i - k: heapq.heappop(q)           
            res.append(-q[0][0])
    
        return res

    	## 方法二:双向队列
        q = collections.deque()
        # for i in range(k):
        #     while q and nums[i] >= nums[q[-1]]:q.pop()
        #     q.append(i)
        for i in range(k - 1, -1, -1):
            if not q or nums[i] > nums[q[-1]]: q.append(i)
        q.reverse() # 对应值单调递减

        res = [nums[q[0]]]
        for i in range(k, len(nums)):
            while q and nums[i] >= nums[q[-1]]: q.pop()
            q.append(i) # 去掉小的后添加 维护对应值单调递减队列
            while q[0] <= i - k: q.popleft() # 移出窗口
            res.append(nums[q[0]])
        
        return res

862. 和至少为 K 的最短子数组

class Solution:
    def shortestSubarray(self, nums: List[int], k: int) -> int:
        n = len(nums)
        res = n + 1
        # acc = [0] + list(accumulate(nums)) 
        acc = [0]
        for x in nums: acc.append(acc[-1] + x)     
        q = collections.deque()
        for i, x in enumerate(acc):
            while q and x <= acc[q[-1]]:
                q.pop()
            while q and x - acc[q[0]] >= k:
                res = min(res, i - q.popleft())
            q.append(i)                
        return res if res <= n else -1
class Solution {
    public int shortestSubarray(int[] nums, int k) {
        int n = nums.length;
        int ans = n + 1;
        long[] acc = new long[n + 1];
        Deque<Integer> q = new LinkedList();
        for (int i = 0; i < n; i++) acc[i + 1] = acc[i] + (long) nums[i];
        for (int i = 0; i < acc.length; i++){
            while (!q.isEmpty() && acc[i] <= acc[q.getLast()]) q.removeLast();
            while (!q.isEmpty() && acc[i] >= acc[q.getFirst()] + k) ans = Math.min(ans, i - q.removeFirst());
            q.addLast(i);
        }
        return ans <= n ? ans : -1; 
    }
}

1823. 找出游戏的获胜者

class Solution:
    def findTheWinner(self, n: int, k: int) -> int:
        q = deque(range(1, n + 1))
        while len(q) > 1:
            for _ in range(k - 1):
                q.append(q.popleft())
            q.popleft()
        return q[0]
class Solution {
    public int findTheWinner(int n, int k) {
        Deque<Integer> q = new ArrayDeque<>();
        for (int i = 1; i < n + 1; i++) q.offer(i);
        while (q.size() > 1){
            for (int i = 1; i < k; i++){
                q.offer(q.poll());
            }
            q.poll();
        }
        return q.peek();
    }
}

约瑟夫环

第一轮会删掉第 k 个人,问题就变为对 n - 1 个人进行这个游戏。
假设我们知道 f(n?1, k) 最终剩下的人的编号,由于我们删了第 k 个人,n ? 1 个人的游戏是从原来第 k + 1 个人开始的,原来的编号和新的编号有一个偏差 k。
以坐标从 0 到 n - 1 来看的话(去掉 1 的偏差减少计算量,最终加一次 1 即可):
f(n, k) = (f(n - 1, k) + k) \ % n
当只剩一个人时,即 f(1, k) = 0
从 f(1, k) 推出 f(2, k) 一直到 f(n, k)即可。

class Solution:
    def findTheWinner(self, n: int, k: int) -> int:
        ans = 0
        for i in range(2, n + 1):
            ans = (ans + k) % i
        return ans + 1

每次往同一方向,以固定步长 k 进行消数。由于下一次操作的发起点为消除位置的下一个点(即前后两次操作发起点在原序列下标中相差 kk),同时问题规模会从 n 变为 n - 1,因此原问题答案等价于 findTheWinner(n - 1, k) + k。

一些细节,由于编号从 1 开始,在返回答案时我们需要将结果为 0 的值映射回编号 n。

class Solution {
    public int findTheWinner(int n, int k) {
        if (n <= 1) return n;
        int ans = (findTheWinner(n - 1, k) + k) % n;
        return ans == 0 ? n : ans;
    }
}
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-05-09 12:59:06  更:2022-05-09 13:00:59 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年1日历 -2025/1/10 2:21:13-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码