当前位置: 首页 > news >正文

Java,八股,cv,算法——双非研0四修之路day24

目录

 昨日总结

今日计划

算法——前k个高频元素

算法——滑动窗口最大值(单调队列解法另一种实现法)

JVM

Redis分片集群的散列插槽结构

Redis分片集群的伸缩

Redis分片集群的故障转移

RedisTemplate分片集群的访问

昨日八股答案 

今日八股

总结


 昨日总结

  • redis高级篇(分布式缓存完结),JVM底层原理
  • cv(停滞中)
  • 背诵小林coding--Java并发面试篇(1/5)
  • 代码随想录——前k个高频元素,滑动窗口最大值(单调队列解法另一种实现法)

今日计划

  • redis高级篇(多级缓存),JVM底层原理
  • cv(停滞中)
  • 背诵小林coding--Java并发面试篇(2/5)
  • 代码随想录——二叉树的递归遍历,非递归遍历,广度优先搜索

算法——前k个高频元素

给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。

示例 1:

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

示例 2:

输入: nums = [1], k = 1
输出: [1]
//在此基础上的优化,可以用小顶堆来实现对hashmap的排序。小顶堆中剩余的元素,即是前k个频率最高的元素
class Solution {public int[] topKFrequent(int[] nums, int k) {//用hashmap存储元素和元素出现的次数HashMap<Integer, Integer> map = new HashMap<>();for(int num : nums) {//可以用一段代码实现,如下// map.put(num, map.getOrDefault(num, 0) + 1);if(map.containsKey(num)) {map.put(num,map.get(num) + 1);}else{map.put(num,1);}}// 将 HashMap 的键值对转换为 ListList<Map.Entry<Integer, Integer>> list = new ArrayList<>(map.entrySet());//可以用stream流实现排序// 使用 Stream 流实现排序// List<Map.Entry<Integer, Integer>> sortedList = list.stream()//         // 按照 Map.Entry 的值进行降序排序//        .sorted(Map.Entry.<Integer, Integer>comparingByValue().reversed())//         // 将排序后的元素收集到一个新的列表中//        .collect(Collectors.toList());// 使用 Collections.sort() 方法对值进行排序// Collections.sort(list, new Comparator<Map.Entry<Integer, Integer>>() {//     @Override//     public int compare(Map.Entry<Integer, Integer> o1, Map.Entry<Integer, Integer> o2) {//         return o2.getValue().compareTo(o1.getValue());//     }// });//最简洁的是使用Lambda表达式实现Collections.sort(list, (o1, o2) -> o2.getValue().compareTo(o1.getValue()));List<Integer> resp = new ArrayList<>();int num = 0;for (Map.Entry<Integer, Integer> entry : list) {if(num == k)break;resp.add(entry.getKey());num++;}return resp.stream().mapToInt(Integer::intValue).toArray();}
}

算法——滑动窗口最大值(单调队列解法另一种实现法)

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

返回 滑动窗口中的最大值 

示例 :

输入:nums = [1,3,-1,-3,5,3,6,7], k = 3
输出:[3,3,5,5,6,7]
class Solution {public int[] maxSlidingWindow(int[] nums, int k) {int len = nums.length;int[] res = new int[len - k + 1];Deque<Integer> queue = new ArrayDeque<Integer>();//先将队列填满,将数组里面的前k个元素入队,同是保证他是一个单调队列for (int i = 0; i < k; i++) {//移除最大元素之前的元素,保证队头是最大元素while (!queue.isEmpty() && nums[i] > queue.peekLast()) {queue.pollLast();}queue.offerLast(nums[i]);}//记录目前最大元素res[0] = queue.peekFirst();for (int i = k, j = 1; i < len; i++, j++) {//移除队列最大的元素if (!queue.isEmpty() && nums[i - k] == queue.peekFirst()) {queue.pollFirst();}//移除最大元素之前的元素,保证队头是最大元素while (!queue.isEmpty() && nums[i] > queue.peekLast()) {queue.pollLast();}queue.offerLast(nums[i]);//记录数组中最大元素res[j] = queue.peekFirst();}return res;}
}

JVM

  • 栈的存取速度大于堆
  • 栈中存取是的对象的引用。例如MyObject obj = new MyObejct(),这里的obj实际上是一个存储在栈上的引用,指向堆中世纪的对象的实例

Redis分片集群的散列插槽结构

Redis会把每一个master节点映射到0~16383共16384个插槽(hashslot)上,查看集群信息时就能看到。
为什么要引入插槽,用它来绑定数据的key?
当节点的master宕机时,引入插槽的集群信息就可以直接转移到别的master上,不会因此丢失信息。
redis如何判断某个key在哪个master节点中?
首先将16384个插槽分配给不同的maser节点,根据key的有效部分计算哈希值,对16384取余,余数作为插槽值。

Redis分片集群的伸缩

新建节点操作,同时分配插槽(用的时候直接查命令,知道有这个方法就行)

Redis分片集群的故障转移

Reids集群不需要哨兵,他可以自动实现主从集群的切换
也可以手动实现数据迁移,实现主从集群的切换(用的时候直接查命令,知道有这个方法就行)

RedisTemplate分片集群的访问

redistemplate底层基于lettuce实现了分片集群的支持,使用步骤与哨兵模式基本一致:
  • 引入redis的starter依赖
  • 配置分片集群地址(与哨兵模式略有差异)
  • 配置读写分离

昨日八股答案 

  • JVM的内存模型架构

一张图可以清晰的展示出整体架构,大概的流程就是:

  1. 当java程序启动时,字节码文件被加载到类加载器中
  2. 经过类加载器的链接和初始化操作,将加载的信息传到运行时数据区
  3. 加载的类信息被传送到方法区,JVM会创建线程分配其空间来执行main方法,过程中需要用到java栈,程序计数器等帮助,同时,类创建的对象分配在堆中
  4. 程序结束后,JVM会销毁线程,同时释放资源。

  • JVM中堆栈的区别

  1. 栈用于存储局部变量,方法调用的参数,方法返回地址等一些临时的数据,每一个方法被调用,一个栈帧就会在栈中创建;堆用于存储对象的实例。
  2. 生命周期不同。当一个方法调用结束时,其对应的栈帧就会销毁;堆中的对象生命周期不确定,需要在检测对象不再被引用时才能被回收。
  3. 栈基于先进后出原则,操作简单,运行速度快;堆需要对象的分配和回收,这些机制导致其速度较慢
  4. 栈的空间大小较小;堆的大
  5. 栈中的数据对线程是私有的;堆中的数据对线程是共享的。
  • JVM方法区中方法的执行过程

  1. JVM会根据方法的符号引用(逻辑)找到方法的物理地址
  2. 在执行方法前,需要分配一个新的栈帧,用于存储局部变、操作数栈、方法出口等信息
  3. 之后开始执行方法
  4. 执行完毕后,返回结果给调用者,清理栈帧。
  • 程序计数器的作用,为什么是私有的

记录程序运行到的位置,方便回调后找到执行的位置。

每个线程都有自己的程序计数器。每个线程执行的程序指令不一样,所以记录的位置也不同,需要自己维护一个程序计数器。

今日八股

  • 引用类型有哪些?有什么区别?

  • 内存泄漏和内存溢出的理解

  • JVM内存结构溢出的情况

总结

写代码题耗了好长的时间,还是要多练习,不过收获很大。

http://www.lryc.cn/news/609358.html

相关文章:

  • 2025年测绘程序设计比赛--基于统计滤波的点云去噪(已获国特)
  • 【AI】文档理解
  • 旧笔记本电脑如何安装飞牛OS
  • 嵌入式学习日志——数据结构(一)
  • 渗透高级-----应急响应
  • LLM调研
  • nestjs @Param 从入门到精通
  • 大模型能力测评(提示词请帮我把这个项目改写成为python项目)
  • 数据结构基础 - 平衡二叉树
  • 关于 xrdp远程桌面报错“Error connecting to sesman on 127.0.0.1:3350“的解决方法
  • lua table常用函数汇总
  • 6. 平台总线
  • 模型学习系列之参数
  • 秋招笔记-8.3
  • 关于记录一下“bug”,在做图片上传的时候出现的小问题
  • 验房收房怎么避免被坑?
  • 我的世界进阶模组开发教程——伤害(2)
  • 自己实现一个freertos(2)任务调度 1——最基本的TCB
  • 深入解析HashMap:原理与性能优化
  • Redis实战(7)-- 高级特性 Redis Stream数据结构与基础命令
  • spring batch处理数据模板(Reader-Processor-Writer模式)
  • Timer实现定时调度的原理是什么?
  • PPT 转高精度 PDF API 接口
  • 使用DrissionPage实现xhs笔记自动翻页并爬取笔记视频、图片
  • Coin Combinations I(Dynamic Programming)
  • Docker环境离线安装指南
  • 解剖 .NET 经典:从 Component 到 BackgroundWorker
  • node.js常用函数
  • GaussDB case when的用法
  • SpringBoot AI自动化测试实战案例