算法训练营day13

news2024/11/13 9:17:29

一、SlidingWindowMaximum(滑动窗口最大值)

前置题,155.最小栈

参考K神155. 最小栈 - 力扣(LeetCode)

做完最小栈的题能更好的理解这道题

鄙人想到了开辟空间来保存最小值,使用的HashMap;K神用的是栈+逻辑优化

class MinStack {
    private Stack<Integer> stack;
    private Stack<Integer> min_stack;

    public MinStack() {
        stack = new Stack<>();
        min_stack = new Stack<>();
    }
    
    public void push(int val) {
        stack.push(val);
        if (min_stack.isEmpty() || val <= min_stack.peek())
            min_stack.push(val);
    }
    
    public void pop() {
        if (stack.pop().equals(min_stack.peek()))
            min_stack.pop();
    }
    
    public int top() {
        return stack.peek();
    }
    
    public int getMin() {
        return min_stack.peek();
    }
}

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

  1. 使用双端队列保存每个窗口的最大值
  2. 左指针 > 0,也就是左指针 "存在"的时候,每次滑动窗口都要将队列第一个元素删除,保持和窗口一致
  3. 右指针在添加新元素的时候会判断队列中所有元素是否小于该元素,小于的部分将被删除
    1. 如果队列中所有元素都小于该新增元素,那么新增元素就是最大的元素
    2. 如果队列中存在元素 >= 该新增元素,停止移除元素,push该元素,我们会发现这个队列是 非严格递减(单调不增),与最小栈压辅助栈是相同的原理
      • 单调不增,不递增 -> 有两种可能,递减或相等
滑动窗口不分阶段
class Solution {
    public int[] maxSlidingWindow(int[] nums, int k) {
        if(nums.length == 0 || k == 0) return new int[0];
        Deque<Integer> deque = new LinkedList<>();
        int[] res = new int[nums.length - k + 1];
        //左指针i,右指针j,为了保证每次循环的条件相同(即Carl哥讲的循环不变量),这里我们发现K写的代码右指针是从0开始遍历的,而左指针则是 0 - (k - 1) = 1 - k开始遍历的
        for(int j = 0, i = 1 - k; j < nums.length; i++, j++) {
            // 删除 deque 中对应的 nums[i-1]
            if(i > 0 && deque.peekFirst() == nums[i - 1])
                deque.removeFirst();
            // 保持 deque 递减,
            // 循环停止 1.deque为空,表示nums[j]是当前最大的值,deque最后剩一个值
            // 2.deque.peekLast() >= nums[j],表示小于等于deque中的剩余元素
            while(!deque.isEmpty() && deque.peekLast() < nums[j])
                deque.removeLast();
            deque.addLast(nums[j]);
            // 记录窗口最大值
            if(i >= 0)
                res[i] = deque.peekFirst();
        }
        return res;
    }
} 
滑动窗口分阶段
  1. 因为不分阶段时左指针的起始索引为 1-K < 0 ,没在数组区间内,因此没形成窗口
  2. 当左指针 >= 0 时,窗口就在数组中了,即已经形成窗口
class Solution {
    public int[] maxSlidingWindow(int[] nums, int k) {
        if(nums.length == 0 || k == 0) return new int[0];
        Deque<Integer> deque = new LinkedList<>();
        int[] res = new int[nums.length - k + 1];
        // 未形成窗口
        for(int i = 0; i < k; i++) {
            while(!deque.isEmpty() && deque.peekLast() < nums[i])
                deque.removeLast();
            deque.addLast(nums[i]);
        }
        res[0] = deque.peekFirst();
        // 形成窗口后
        for(int i = k; i < nums.length; i++) {
            // i = k,i此时是右指针,左指针为0,右指针为 k - 1
            //i = k 为新的右指针,原左指针为 i - k(多减了一个1),如果原左指针等于队列中最大值,则将队列中最大值删除(这步是判断被移除的元素是否是原来的窗口的最大值)
            if(deque.peekFirst() == nums[i - k])
                deque.removeFirst();
            //保持 deque 递减
            while(!deque.isEmpty() && deque.peekLast() < nums[i])
                deque.removeLast();
            deque.addLast(nums[i]);
            // i - (k - 1) 是当前的左指针
            res[i - k + 1] = deque.peekFirst();
        }
        return res;
    }
}

二、前K个高频元素

前置知识:

简单写一下堆的知识,便于理解优先队列,已经了解的朋友转到逻辑部分

参考8.1 堆 - Hello 算法 (hello-algo.com)

  1. 堆:是一种满足特定条件的完全二叉树,主要可分为两种类型

    • 小顶堆(min heap):任意节点的值 ≤ 其子节点的值。
    • 大顶堆(max heap):任意节点的值 ≥ 其子节点的值。
  2. 堆作为完全二叉树的一个特例,具有以下特性。

    • 最底层节点靠左填充,其他层的节点都被填满。
    • 我们将二叉树的根节点称为“堆顶”,将底层最靠右的节点称为“堆底”。
    • 对于大顶堆(小顶堆),堆顶元素(根节点)的值是最大(最小)的。

    实际上,通常用于实现优先队列,大顶堆相当于元素按从大到小的顺序出队的优先队列。从使用角度来看,我们可以将“优先队列”和“堆”看作等价的数据结构。

  3. 堆的存储与表示

    1. “二叉树”章节讲过,完全二叉树非常适合用数组来表示。由于堆正是一种完全二叉树,因此我们将采用数组来存储堆
    2. 当使用数组表示二叉树时,元素代表节点值,索引代表节点在二叉树中的位置。节点指针通过索引映射公式来实现
    3. 给定索引 i ,其左子节点的索引为 2i+1 ,右子节点的索引为 2i+2 ,父节点的索引为 (i−1)/2(向下整除)。当索引越界时,表示空节点或节点不存在。如图在这里插入图片描述
  4. 建堆操作

    1. 借助入堆操作实现,设元素数量为 n ,每个元素的入堆操作使用 n(logn) 时间,因此该建堆方法的时间复杂度为时间复杂度O(nlogn)
    2. 通过遍历堆化实现
      1. 将列表原封不动添加到堆当中,此时还没有满足堆的性质
      2. 倒序遍历堆(层序遍历的倒序),依次对每个非叶节点执行“从顶至底堆化”。
      3. 复杂度
        1. 假设完全二叉树的节点数量为 n ,则叶节点数量为 (n+1)/2 ,其中 / 为向下整除。因此需要堆化的节点数量为 (n−1)/2 。
        2. 在从顶至底堆化的过程中,每个节点最多堆化到叶节点,因此最大迭代次数为二叉树高度 log⁡n。
        3. 将上述两者相乘,可得到建堆过程的时间复杂度为O(nlogn) 。但这个估算结果并不准确,因为我们没有考虑到二叉树底层节点数量远多于顶层节点的性质
        4. 作者进行更精确的数学计算之后,时间复杂度为O(n)
逻辑部分
一、堆解法

代码中见注解

class Solution {
    public int[] topKFrequent(int[] nums, int k) {
        //key为num,value为出现的次数
        Map<Integer, Integer> occurrences = new HashMap<Integer, Integer>();
        for (int num : nums) {
            occurrences.put(num, occurrences.getOrDefault(num, 0) + 1);
        }

        // int[] 的第一个元素代表数组的值,第二个元素代表了该值出现的次数
//PriorityQueue是优先队列,按照比较器(Comparator)的逻辑来比较元素
//若要实现升序排序,当第一个参数 < 第二个参数时返回负数,相等时返回 0;
//若要实现降序排序,当第一个参数 > 第二个参数时返回负数,相等时返回 0。
//也可以简单理解成 return出的参数和compare中参数相对位置一致是升序,相反是降序
//这里是 第一种情况升序
        PriorityQueue<int[]> queue = new PriorityQueue<int[]>(new Comparator<int[]>() {
            public int compare(int[] m, int[] n) {
                return m[1] - n[1];
            }
        });
        //entrySet()放回map中的每个键值对组成的集合
        for (Map.Entry<Integer, Integer> entry : occurrences.entrySet()) {
            int num = entry.getKey(), count = entry.getValue();
            //如果queue大小已经等于k,判断队列第一个元素的[1]也就是最小出现频率是否大于当前count
            if (queue.size() == k) {
                //当前count > peek()[1],弹出队首元素,将当前数字及频率创建数组添加到queue中
                if (queue.peek()[1] < count) {
                    queue.poll();
                    queue.offer(new int[]{num, count});
                }
            } else {
                queue.offer(new int[]{num, count});
            }
        }
        //创建大小为k的数组,保存最后结果
        int[] ret = new int[k];
        for (int i = 0; i < k; ++i) {
            ret[i] = queue.poll()[0];
        }
        return ret;
    }
}
索引排序
  1. 适用于map和value都是Integer类型
  2. 在1的前提下巧妙之处是将map的key和value调换
  3. 那么索引在
public List<Integer> topKFrequent(int[] nums, int k) {

	List<Integer>[] bucket = new List[nums.length + 1];
	Map<Integer, Integer> frequencyMap = new HashMap<Integer, Integer>();

	for (int n : nums) {
		frequencyMap.put(n, frequencyMap.getOrDefault(n, 0) + 1);
	}

	for (int key : frequencyMap.keySet()) {
		int frequency = frequencyMap.get(key);
		if (bucket[frequency] == null) {
			bucket[frequency] = new ArrayList<>();
		}
		bucket[frequency].add(key);
	}

	List<Integer> res = new ArrayList<>();
	//出现频次高的在列表后面,使用倒序遍历,
    //停止条件为 pos >= 0,有可能数组里面数字的种类凑不齐k个数
    //res.size() < k表示res已经记录了出现频次最高的k个数字
	for (int pos = bucket.length - 1; pos >= 0 && res.size() < k; pos--) {		//不为空的添加到列表中
		if (bucket[pos] != null) {
			res.addAll(bucket[pos]);
		}
	}
	return res;
}
相似习题

692. 前K个高频单词 - 力扣(LeetCode)

451. 根据字符出现频率排序 - 力扣(LeetCode)

(bucket[pos]);
}
}
return res;
}




#### 相似习题

[692. 前K个高频单词 - 力扣(LeetCode)](https://leetcode.cn/problems/top-k-frequent-words/description/)

[451. 根据字符出现频率排序 - 力扣(LeetCode)](https://leetcode.cn/problems/sort-characters-by-frequency/)

显然这两道题,区别在于存储出现频率时,key为String/Character,value为Integer,其他的逻辑部分大差不差,具体实现不同需要自己补充了解

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1612938.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

网盘_游戏_博客自动化部署(Nginx多项目部署)

目录 一.前提介绍 二.环境介绍 三.自述&#xff08;脚本&#xff09; 四.关于Nginx多项目部署 一.前提介绍 在我之前的博客里详细介绍了上述项目的部署&#xff0c;那么如何使用简单脚本自动部署和使用Nginx多项目部署是本文来介绍的基础篇章。 二.环境介绍 CentOS Linux…

吴恩达深度学习 (week5,6)

文章目录 一、训练开发测试集二、机器学习基础三、 正则化初步介绍四、Dropout 正则化五、其他正则化方法六、归一化输入介绍七、梯度消失与梯度爆炸八、神经网络的权重初始化九、梯度数值逼近和检验十、上述学习总结第一题 划分训练/开发/测试集第二题 开发和测试集分布第三题…

gradle安装和部署

准备工作 下载地址&#xff1a;https://gradle.org/releases/ 安装和配置环境变量 将压缩包解压到/usr/local/目录下 unzip gradle-8.7-bin.zip -d /usr/local/找到gradle的安装目录/usr/local/gradle-8.7 编辑/etc/vi /etc/profileprofile配置环境变量&#xff08;这是ce…

duke liver datasets数据处理

Duke liver datasets 如果大家是做医学图像处理的&#xff0c;刚好又是做肝脏那边的&#xff0c;对这个数据集应该不会陌生 我发现网上现有的资料很少有说怎么读取这个数据集的&#xff0c;由于我之前一直都是做的nii格式的数据集&#xff0c;现在碰到了dicom格式的数据集页研…

SQLite导出数据库至sql文件

SQLite是一款实现了自包含、无服务器、零配置、事务性SQL数据库引擎的软件库。SQLite是世界上部署最广泛的SQL数据库引擎。 SQLite 是非常小的&#xff0c;是轻量级的&#xff0c;完全配置时小于 400KiB&#xff0c;省略可选功能配置时小于250KiB。 SQLite 源代码不受版权限制。…

分类神经网络3:DenseNet模型复现

目录 DenseNet网络架构 DenseNet部分实现代码 DenseNet网络架构 论文原址&#xff1a;https://arxiv.org/pdf/1608.06993.pdf 稠密连接神经网络&#xff08;DenseNet&#xff09;实质上是ResNet的进阶模型&#xff08;了解ResNet模型请点击&#xff09;&#xff0c;二者均是…

数字阅览室解决方案

一、方案概述 “数字阅览室”概念一经提出&#xff0c;就得到了广泛的关注&#xff0c;纷纷组织力量进行探讨、研究和开发&#xff0c;进行各种模型的试验。随着数字地球概念、技术、应用领域的发展&#xff0c;数字阅览室已成为数字地球家庭的成员&#xff0c;为信息高速公路…

Flowable 基本用法

一. 什么是Flowable Flowable 是一个基于 Java 的开源工作流引擎&#xff0c;用于实现和管理业务流程。它提供了强大的工作流引擎和一套丰富的工具&#xff0c;使开发人员能够轻松地建模、部署、执行和监控各种类型的业务流程。Flowable 是 Activiti 工作流引擎的一个分支&am…

LeetCode-电话号码的字母组合(回溯)

每日一题 今天刷到的是一道利用回溯来解决的题&#xff0c;不过稍微有点复杂&#xff0c;并且我也有一段时间没有做回溯了&#xff0c;所有在解题时也是思考了一段时间。 题目要求 给定一个仅包含数字 2-9 的字符串&#xff0c;返回所有它能表示的字母组合。答案可以按 任意…

常见现代卷积神经网络(ResNet, DenseNet)(Pytorch 11)

一 批量规范化&#xff08;batch normalization&#xff09; 训练深层神经网络是十分困难的&#xff0c;特别是在较短的时间内使他们收敛更加棘手。批量规范化&#xff08;batch normalization&#xff09;是一种流行且有效的技术&#xff0c;可持续加速深层网络的收敛速度。 …

网络原理-UDP和TCP

在传输层中有两个非常重要的协议&#xff0c;UDP和TCP&#xff0c;现在就来研究一下这两个协议。 UDP 报文格式 我们观察可以发现&#xff0c;里面UDP报文长度为2个字节&#xff0c;那么是多少呢&#xff1f;我们需要快速反应如下固定字节数据类型的取值范围&#xff1a; 字…

【融合ChatGPT等AI模型】Python-GEE遥感云大数据分析、管理与可视化及多领域应用

随着航空、航天、近地空间遥感平台的持续发展&#xff0c;遥感技术近年来取得显著进步。遥感数据的空间、时间、光谱分辨率及数据量均大幅提升&#xff0c;呈现出大数据特征。这为相关研究带来了新机遇&#xff0c;但同时也带来巨大挑战。传统的工作站和服务器已无法满足大区域…

anaconda配置的环境对应的地址查看,环境安装位置

打开conda指令窗口 这个和上面的都一样&#xff0c;哪个都行 点开后&#xff0c;输入 conda env list 这里显示的就是自己的每个环境对应的地址了

python_4

def reverse(number):a str(number) # 将输入的数字转成字符串print(f"反向输出:{a[::-1]}") # 将字符串通过切片反向输出number int(input("输入整数:")) reverse(number)import mathdef isValid(side1, side2, side3):# 根据"两边之和大于第三边…

安装mmsegmentation默认主分支main

安装时间2024.4.21 mmsegmentation新版本main分支&#xff08;v1.2.2&#xff09; 安装过程 conda create --name openmmlab python3.8 -y conda activate openmmlab// 很关键&#xff0c;可以避免mmcv版本问题 pip install torch1.10.1cu113 torchvision0.11.2cu113 torcha…

明日周刊-第7期

转眼间就又快到了五一假期&#xff0c;小长假有什么计划吗。封面配图是杭州高架上的月季花&#xff0c;非常好看。 文章目录 一周热点资源分享言论歌曲推荐 一周热点 鸿蒙系统持续扩大影响力&#xff1a;近期&#xff0c;华为官方宣布广东省已有超过600款应用加入鸿蒙系统&…

文献速递:深度学习胶质瘤诊断---使用深度学习在 MRI 图像中进行低级别胶质瘤的脑肿瘤分割和分级

Title 题目 Brain tumor segmentation and grading of lower-grade glioma using deeplearning in MRI images 使用深度学习在 MRI 图像中进行低级别胶质瘤的脑肿瘤分割和分级 01文献速递介绍 胶质瘤是最常见的脑肿瘤&#xff0c;根据肿瘤的恶性程度和生长速率具有不同的分级…

如何在PostgreSQL中使用pg_stat_statements插件进行SQL性能统计和分析?

文章目录 一、启用pg_stat_statements插件二、查看统计信息三、定期重置统计信息四、注意事项 PostgreSQL中的pg_stat_statements是一个强大的插件&#xff0c;用于追踪执行时间最长的SQL语句。通过它&#xff0c;我们可以获取有关SQL语句执行频率、总执行时间、平均执行时间等…

2024团体程序设计天梯赛L1-104 九宫格

题目链接L1-104 九宫格 #include<iostream> #include<stdio.h> #include<string.h> #include<algorithm> using namespace std; int n, mapp[10][10], a[10]; int dx[10]{0, 1, 1, 1, 4, 4, 4, 7, 7, 7}; int dy[10]{0, 1, 4, 7, 1, 4, 7, 1, 4, 7}; b…

HTML:Form表单控件主要标签及属性。name属性,value属性,id属性详解。表单内容的传递流程,get和post数据传递样式。表单数据传递实例

form表单 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title> </head> &…