秋招突击——8/6——万得数据面试总结

文章目录

引言

  • 今天要面试万得数据,上午在整理项目相关的问题,看相关的代码,现在整理一下面经,毕竟下午两点钟就要开始的!

正文

面经整理一

作者:网抑云八级选手

链接:https://www.nowcoder.com/feed/main/detail/a44af7a275754bc0a200fcc9778d64c0?sourceSSR=search

来源:牛客网

1、讲一下java的多态,重载,重写的概念,区别

多态

  • 同一个接口或者基类可以指向不同的实现或子类对象 ,编写更加通用和灵活的代码
    • 编译时多态(静态多态):通过方法重载实现。
    • 运行时多态(动态多态):通过方法重写和接口实现。

重载

  • 重载是指在同一个类中,可以有多个同名的方法但它们的参数列表不同(参数的数量或类型不同) 。重载是编译时多态的一种形式
  • 主要特点
    • 方法名相同
    • 参数列表不同(参数的数量或类型不同)。
    • 可以有不同的返回类型
    • 可以有不同的访问修饰符

重写

  • 重写是指子类提供了与父类中同名方法的实现
  • 重写是运行时多态的一种形式 。通过重写,子类可以提供特定的实现,而不是使用父类的实现
  • 主要特点
    • 方法名、参数列表、返回类型必须相同。
    • 访问修饰符不能比父类的更严格(可以更宽松)。
    • 子类方法不能比父类方法抛出更多或更广泛的异常。

区别

  • 多态:同一个接口或者基类可以多种实现
  • 重载:在同一个类中,同名方法有不同的参数列表,是编译时多态
  • 重写:子类提供与父类同名方法的实现,运行时多态
2、说一下Java的数组,链表的结构,优缺点

数组

  • 一种线性数据结构,用于存储相同类型元素的集合
  • 数组在内存中是连续分配的,所有元素的大小相同,可以通过索引快速访问。
  • 优点
    • 快速访问:由于数组元素在内存中是连续存储的,可以通过索引在O(1)时间复杂度内直接访问任意元素。
    • 节省内存:没有额外的存储开销(如指针)。
    • 缓存友好:由于数组元素连续存储,使用缓存时效率更高。
  • 缺点
    • 固定大小:数组的大小在创建时必须确定,之后不能改变。这可能导致内存浪费或不够用。
    • 插入和删除效率低:在数组中插入或删除元素需要移动大量元素,时间复杂度为O(n)。
    • 不适合频繁插入和删除操作:由于上述原因,数组不适合在中间频繁进行插入和删除操作。

链表

  • 一种线性数据结构,由一系列节点(Node)组成每个节点包含数据和指向下一个节点的引用(或指针)

  • 根据节点之间的连接方式,链表可以分为单向链表(Singly Linked List)和双向链表(Doubly Linked List)

  • 优点

    • 动态大小:链表可以根据需要动态增长或缩小,不需要预先分配固定大小。
    • 插入和删除操作高效:在链表中插入或删除元素不需要移动其他元素,只需修改指针即可,时间复杂度为O(1)(在已知位置的情况下)。
    • 适用于频繁插入和删除操作:尤其是在中间插入或删除时,链表比数组更高效。
  • 缺点

    • 访问速度慢:由于无法通过索引直接访问元素,必须从头节点开始逐个遍历,时间复杂度为O(n)。
    • 额外的内存开销:每个节点除了存储数据,还需要存储指针,这会占用额外的内存。
    • 缓存不友好:由于链表元素在内存中不是连续存储的,使用缓存时效率较低。
3、创建java线程的方式有哪些,具体说说

继承Thread类

  • 结构
    • 通过继承Thread类并重写run方法来创建线程
  • 步骤
    • 创建一个继承自Thread类的子类。
    • 在子类中重写run方法,将线程的执行逻辑写在run方法中。
    • 创建该子类的实例,并调用start方法启动线程。

实现Runnable接口

  • 结构

    • 通过实现Runnable接口并将其传递给Thread类来创建线程。
  • 步骤

    • 创建一个实现Runnable接口的类。
    • 在类中实现run方法,将线程的执行逻辑写在run方法中。
    • 创建该类的实例,并将其作为参数传递给Thread对象。
    • 调用Thread对象的start方法启动线程。

。。。

总结

  • 继承Thread类:简单直接,但不支持多继承。
  • 实现Runnable接口:推荐使用,符合Java单继承多实现的特性。
  • 使用Callable和Future:适用于需要返回结果或抛出异常的任务。
  • 使用ExecutorService框架:适用于需要高效管理线程池的场景。
4、创建线程池呢、每个参数的意义
5、通过那几种方式保证线程安全
6、jvm加载
7、了解数据库事物?特性?
8、怎么提高sql查询性能 (只说了添加索引,分库分表)
  • 优化查询语句

    • 避免SELECT *,尽量只查询需要的列
    • 使用WHERE条件筛选数据,减少返回的数据量
    • 避免在WHERE子句中使用函数,使用函数会导致无法使用索引,从而降低查询性能。
  • 索引优化

    • 创建合适的索引
    • 使用覆盖索引
  • 数据库分区

    • 使用分区表 :将大表按照某个字段(如日期、ID范围)进行分区,减少单个分区的数据量,提高查询性能。
  • 数据库配置优化

    • 调整数据库配置:根据实际需求调整数据库的内存分配、缓存大小、连接数等配置参数,提高整体性能。
9、String特性是什么

不可变性(Immutability)

  • 在Java中,String对象是不可变的。一旦创建,字符串的值就不能更改。如果需要修改字符串,则会创建一个新的字符串对象。

字符串池(String Pool)

  • Java使用字符串池来优化字符串的存储和管理 。当你创建一个字符串字面量时,JVM会先检查字符串池中是否存在相同的字符串如果存在,则返回对该字符串的引用;如果不存在,则在池中创建新的字符串

字符串连接(Concatenation):

  • Java支持使用+操作符进行字符串连接,也可以使用StringBuilder或StringBuffer来提高性能。StringBuilder和StringBuffer是可变的,并且提供了对字符串的高效修改操作。
10、redis数据类型
11、redis持久化 答了(AOF,RDB)接着问了他们之间的区别

面经整理二

作者:MO小天才

链接:https://www.nowcoder.com/feed/main/detail/363997511497459ea21b12aa686439d7?sourceSSR=search

来源:牛客网

1、spring是怎么实现aop的
  • 一种用于分离关注点的技术 ,特别是在横切关注点(如日志记录、事务管理、权限控制等)方面。Spring AOP的实现主要基于代理模式。

  • 切面(Aspect)

    • 面是横切关注点的模块化表现,是通知(advice)和切入点(pointcut)的结合
  • 通知(Advice)

    • 通知是在切入点上执行的操作常见的通知类型包括前置通知(before)、后置通知(after)、返回通知(after returning)、异常通知(after throwing)和环绕通知(around)。
  • 切入点(Pointcut)

    • 切入点定义了通知应当应用到哪些连接点(Join Points)。通常使用AspectJ表达式语言来定义切入点。
  • 目标对象(Target Object)

    • 目标对象是被通知的对象,即那些包含核心业务逻辑的方法被AOP框架拦截的对象
  • 代理(Proxy)

    • 代理是AOP框架创建的对象,它被用来代替目标对象代理对象负责拦截方法调用,并在适当的时间执行通知
  • 织入(Weaving)

    • 织入是将切面应用到目标对象并创建代理对象的过程。Spring AOP在运行时通过动态代理或CGLIB代理进行织入。
2、aop的原理
  • Spring AOP通过动态代理(JDK动态代理和CGLIB代理)实现了AOP的功能使得我们可以在不修改业务代码的情况下将横切关注点(如日志记录、事务管理等)应用到目标对象的方法上
3、用户通过客户端或者浏览器发送请求,在springboot框架下是如何接收这个请求、解析并向下透传到control层的

1、接收请求

  • 当用户发送HTTP请求时,嵌入式服务器会受到请求

2、请求解析

  • 将请求传递给Servlet容器进行解析,变成HttpServletRequest和HttpServletResponse对象

3、拦截请求

  • DispatcherServlet ,它是Spring MVC的前端控制器,负责处理所有进来的HTTP请求。
  • 映射到所有路径(/) ,因此它会拦截所有请求

4、映射控制器

  • 会根据请求的URL和HTTP方法(GET、POST等) ,通过HandlerMapping找到相应的处理器
  • HandlerMapping的工作是将请求映射到具体的控制器类和方法上。

5、调用控制器方法

  • DispatcherServlet会使用HandlerAdapter调用控制器方法
    • 控制器方法通常使用@RequestMapping或其他映射注解(如@GetMapping、@PostMapping等)来指定URL路径和请求方法

6、处理请求并返回响应对象

  • 控制器方法处理请求,并返回一个响应对象,一般是调用service层的处理业务逻辑,并将结果返回

7、返回给客户端

  • 响应返回给Servlet容器,Servlet容器将响应发送回客户端
4、mysql的底层结构
5、索引分为哪几个类型
6、以非聚簇索引作为一个查询条件,去获取到整条记录的中间过程是什么

1. 在非聚簇索引中查找键值

  • 查找索引键 :、
    • 数据库引擎在非聚簇索引的 B+ 树中查找符合查询条件的索引键
  • 获取聚簇索引键
    • 找到匹配的索引键后,获取指向实际数据记录的指针或聚簇索引键值

2. 在聚簇索引中查找完整记录

  • 查找数据记录
    • 使用从非聚簇索引中获取的聚簇索引键值 ,在聚簇索引的 B+ 树中查找完整的数据记录。
  • 返回完整记录
    • 找到对应的叶节点后,提取并返回完整的数据记录
7、建索引要满足哪些原则
8、hashmap扩容的过程

触发条件

  • 容量(capacity):HashMap桶(bucket)数组的当前大小。
  • 负载因子(load factor):当HashMap的元素数量超过capacity * load factor时触发扩容。默认负载因子为0.75。

扩容过程

  • a. 计算新容量

    • HashMap扩容时,新容量通常是旧容量的两倍 。扩容后,新容量和新阈值会重新计算。
  • b. 创建新桶数组

    • 创建一个大小为新容量的新的桶数组
  • c.重新分配元素

    • 将旧桶数组中的所有元素重新计算哈希并分配到新桶数组中。由于容量的变化,元素的位置可能会发生变化。
    • 链表节点重新分配旧桶数组中存在链表时,需要对链表节点重新分配 。根据节点的哈希值决定其在新桶数组中的位置。如果节点的哈希值与旧容量进行按位与运算结果为0,则其放置在新桶中的原位置,否则放置在原位置加上旧容量的位置。
  • 更新HashMap的引用和阈值

    • 将HashMap的桶数组引用更新为新的桶数组,并更新阈值。
9、synchronized和可重入锁有哪些区别
10、线程安全的集合concurrenthashmap是如何保证线程安全的
  • 分段锁
    • 减少锁争用,提高并发性能。
  • CAS 操作和自旋锁
    • 保证原子性和线程安全。
  • 细粒度锁
    • 对每个桶进行锁定,允许更多并发操作。
  • 树化和链化
    • 提高哈希冲突处理效率,每一个桶的链表长度超过阈值,转为红黑树,提高查找和出入效率
  • 无锁读操作
    • 提高并发读性能。
  • 高效扩容
    • 分批次进行扩容,减少性能影响。
11、java的内存分布
  • 堆(Heap) :存储所有对象实例和数组,分为年轻代和老年代。
  • 栈(Stack) :每个线程都有自己的栈,存储局部变量、方法调用等信息
  • 方法区(Method Area) :存储类的元数据、静态变量、常量池等。在Java 8之后称为元空间(Metaspace)。
  • 程序计数器(PC Register):指示当前线程执行的字节码位置。
  • 本地方法栈(Native Method Stack):为虚拟机执行本地方法服务。
12、1.8的jvm默认的两个垃圾回收器是哪两个,区别是什么
  • 1. Parallel GC(并行垃圾回收器)

    • 特点
      • 年轻代收集 :使用多线程的复制算法(copying)
      • 老年代收集 :使用多线程的标记-压缩算法(mark-compact)
      • 多线程 :使用多个线程同时进行垃圾回收操作,适用于多核 CPU,提高垃圾回收效率
      • 吞吐量优先 :Parallel GC 设计的目标是最大化吞吐量,最小化垃圾回收对应用程序的影响时间
  • 2. G1 GC(Garbage-First Garbage Collector)

    • 特点
      • 分区 :将整个堆内存划分为多个相等大小的独立区域(Region) ,每个区域可以充当 Eden、Survivor 或 Old 区
      • 混合收集年轻代和老年代一起进行收集(mixed collection),在一次垃圾回收过程中,既回收年轻代,又回收部分老年代
      • 并发标记G1 GC 使用并发标记阶段来标记存活对象,从而减少应用程序暂停时间。
      • 停顿时间目标:允许用户指定期望的停顿时间,通过调优停顿时间目标来满足应用程序的低延迟要求。
13、有一个web服务的接口,刚上线的时候没有什么问题,突然一段时间后客户端调用该接口,该接口的反馈都是超时,如何定位这个服务的问题
  • 1. 检查服务器资源
  • 2. 检查应用日志
  • 3. 检查数据库性能
    • 慢查询
    • 连接池耗尽
    • 锁争用
  • 4、检查外部依赖是否正常
    • 缓存服务器
    • 消息队列
  • 5、分析网络问题
    • 网络延迟
    • 防火墙和负载均衡器
  • 6、重现问题
    • 尝试在本地或者测试环境中,重现则个问题,以便更容易调试和分析

正式面试

第一面
A面
  • 1、重点介绍一下个人项目

    • 说的过于琐碎,没有必要,需要概括一下,重点说出你的要点,而不是很细致地完全讲出来,没有必要!
    • 重点介绍Java相关的项目
  • 2、浮点数了解吗?怎么实现的

    • 浮点数的实现主要是基于科学计数法,有以下四部分构成,分别是
      • 符号位:0正数,1负数
      • 基数:使用二进制表示
      • 指数:表示基数应该乘以多少次幂,可以是正数或者负数
      • 尾数:有效位数
    • 特殊
      • 不能表示所有数字,涉及小数比较时,需要处理小数误差
      • 正零和负零
      • 无穷大:超出表示范围的数字
      • NaN:未定义或者不确定地结果
  • 3、给你一个数组,数组里面全部是数字,然后再给你一个s表示窗口的大小,从最左侧滑动,然后滑动到最右侧,求取每一次移动的滑动窗口平均值,你计算一下滑动窗口的最小值?并计算一下的时间复杂度和空间复杂度

    • 想不出更好的做法,只能使用模拟的方式实现,维护滑动窗口的sum,然后每一次计算一次平均值,比较平均值的最最优值。
    • 时间复杂度是O(n),空间复杂度是O(1).
B面
  • 1、简单的自我介绍

    • 项目介绍太过繁琐,很多细节不需要,只需要说你做了什么项目,大概概括一下!项目就说做了什么,然后你有哪些工作,然后总结一下,没有必要面面俱到,什么都说。
  • 项目上线了吗?

    • 并没有上线,在等进一步审核。
  • 系统的准确率是多少

    • 分情况说,比较真实。
  • 针对这种情况有什么其他的优化方案吗?

    • 拓宽信息模态
    • 更换信息收集场景
  • 这个项目是基于大语言模型的,谁在维护和训练?

    • 使用开源大语言模型的API直接调用的,并没有的自己训练一个大语言模型
  • 说一下ThreadLocal的使用?怎么防止内存泄露

    • ThreadLocal是的key是弱引用,但是他的value会强引用,通过调用对应的set等方法会自动回收不再使用value,但是线程不再被使用,不再调用对应方法就不会进行内存回收,导致内存泄漏
    • 如何避免内存泄漏
      • 先获取到 ThreadLocalMap 这个引用的,并且调用了它的 remove 方法,手动调用remove方法,防止内存泄漏
  • MySQL中聚簇索引和非聚簇索引有什么区别

    • 聚簇索引

      • 聚簇索引决定了磁盘上的存储顺序,同时聚簇索引的叶子节点包含了完整的数据行,查询聚簇索引无需额外查询数据
      • 主键默认创建为聚簇索引,如果没有指定主键,会选择一个唯一非空索引作为聚簇缩影。
    • 非聚簇索引

      • 非聚簇索引是单独的索引结构,叶子节点不包含数据行,而是包含了指向数据行的指针
      • 非聚簇索引和数据的存储顺序无关,非聚簇索引的叶子节存储的是数据行的位置或者主键位置,通常需要二次查找。
  • 建表的时候,没有指定任何列作为他的主键,会创建的主键索引吗?

    • 首先,检查表中是否存在唯一非空的索引,有就将其作为主键索引
    • 然后,如果表中没有主键,没有唯一索引,自动生成一个6字节长的隐藏主键列,不可见无法访问
  • InnoDB引擎默认的隔离级别是什么?这个隔离级别会带来问题?做了哪些操作来尽量缓解这个问题?

    • 可重复读,解决了脏读和不可重读,但是还是存在部分幻读
    • 如何解决幻读的问题
      • 提供了两种查询方式的,分别是快照读和当前读,都会产生幻读
      • 针对快照读,使用MVCC来解决幻读问题,第一次查询生成一个readview,然后在当前事务中都使用相同的readview,保证结果相同。
      • 针对当前读,依靠行级锁中的间隙锁来实现
      • 但并不能完全避免,一般是没有加上对应的for update
  • SpringAOP的实现过程

    • 用于在不修改代码的情况下,动态地将某些行为应用到特定的方法或者类上。主要是基于动态代理和字节码操作实现。
    • 定义一个切面类,这个切面类中要指明增强的方式是@Before还是@AfterReturning等,同时指定对应地切点,然后定义具体的需要额外执行的逻辑和行为。
    • 主要是定义通知类和配置类,具体编程实现如下
  • 第二阶段会有一个算法题,HR会通知你的。
ThreadLocal了解吗?如何防止内存泄漏?

资料来源
ThreadLocal介绍

  • 应用场景
    • ThreadLocal用作保存每一个线程独享的对象 ,每一个线程都创建一个副本,这样每一个线程都可以修改自己所拥有的副本 ,不会影响其他线程的副本,确保线程安全
      • 保存线程不安全的工具类,典型需要使用的类是SimpleDataFormat
    • ThreadLocal 用作每一个线程内需要独立保存信息,以便供线程内其他方法更方便地获取该信息场景。线程内每个方法获取到的信息是不一样的,前面执行的方法保存了信息后,后续方法可以通过ThreadLocal获取,避免传参,类似线程内的全局变量。
    • 保存业务的一些内容,比如说在拦截器中获取用户的信息,可以让不同方法直接使用,避免了传递参数麻烦

ThreadLocal可以用来解决共享资源的多线程访问的问题吗?

  • 不是,ThreadLocal 并不是用来解决共享资源问题的 。虽然 ThreadLocal 确实可以用于解决多线程情况下的线程安全问题,但其资源并不是共享的,而是每个线程独享的

ThreadLocal和Synchronized关系?

  • ThreadLocal 是通过让每个线程独享自己的副本,避免了资源的竞争。
  • synchronized 主要用于临界资源的分配,在同一时刻限制最多只有一个线程能访问该资源。

ThreadLocal、Thread和ThreadLocalMap的关系

  • 一个Thread有一个ThreadLocalMap,而ThreadLocalMap的key就是一个一个ThreadLocal

防止内存泄漏

  • 内存泄漏
    • 当某一个对象不在有用时,占用的内存却不能被回收,是内存泄漏
  • 引用分析
    • ThreadLocal中的key是弱引用,如果不在引用了,垃圾回收机制能够成功收回
    • ThreadLocal中value是强引用,如果某一个Thread长时间运行,并且某一个Thread不再被使用,那么这个value就会内存泄漏,没法被垃圾回收
      • set、remove和rehash都会刷新key-value,如果key为null,会自动回收对应的value,但是如果不调用就没有办法刷新了
  • 如何避免内存泄漏
    • 先获取到 ThreadLocalMap 这个引用的,并且调用了它的 remove 方法,手动调用remove方法,防止内存泄漏
如何对复杂对象进行深拷贝?
  • 实现 Cloneable 接口并重写 clone() 方法
    • 通过实现 Cloneable 接口并重写 clone() 方法,可以对对象进行深拷贝
  • 使用序列化进行深拷贝
    • 通过将对象序列化为字节流然后反序列化,可以实现深拷贝。
  • 递归实现深拷贝
    • 通过自定义的递归方法,我们可以实现对复杂对象的深拷贝。此方法适用于对象嵌套结构较为复杂的情况。
SpringAOP的实现过程
  • 一种用于分离关注点的技术 ,特别是在横切关注点(如日志记录、事务管理、权限控制等)方面。Spring AOP的实现主要基于代理模式。

  • 切面(Aspect)

    • 面是横切关注点的模块化表现,是通知(advice)和切入点(pointcut)的结合
  • 通知(Advice)

    • 通知是在切入点上执行的操作常见的通知类型包括前置通知(before)、后置通知(after)、返回通知(after returning)、异常通知(after throwing)和环绕通知(around)。
  • 切入点(Pointcut)

    • 切入点定义了通知应当应用到哪些连接点(Join Points)。通常使用AspectJ表达式语言来定义切入点。
  • 目标对象(Target Object)

    • 目标对象是被通知的对象,即那些包含核心业务逻辑的方法被AOP框架拦截的对象
  • 代理(Proxy)

    • 代理是AOP框架创建的对象,它被用来代替目标对象代理对象负责拦截方法调用,并在适当的时间执行通知
  • 织入(Weaving)

    • 织入是将切面应用到目标对象并创建代理对象的过程。Spring AOP在运行时通过动态代理或CGLIB代理进行织入。
  • Spring AOP通过动态代理(JDK动态代理和CGLIB代理)实现了AOP的功能使得我们可以在不修改业务代码的情况下将横切关注点(如日志记录、事务管理等)应用到目标对象的方法上

笔试

对于必胜的理解

  • 对于序列a而言,其中的元素[a1,a2,a3,a4,a5]等,要是必赢的情况下,随便取出来一个数字ax,使得剩下元素的最大值amax和amin的累加和 大于等于 target,但是最大值不能大于等于target,只要能够是这种情况,那么先手肯定是必胜的。
  • 如果是这种只能够报数三次的情况,肯定能够判定出来的。当前方选什么才能让后方必输
  • 但是如果当前报数并不能立刻判定出能否获胜的话,就不好判定了!

A和B都会按照最优的方式报数

  • 如果轮到A,只要A能够赢,或者说存在必赢的方案,一定会选择必赢的方案
  • 如果轮到B,只要B能够赢,或者说存在必赢的方案,一定会选择必赢的方案
  • 言外之意,就是A每一次做出决定之前,都要判定会不会给B带来必赢的局面,如果能够给B带来必赢的局面,就不选当前方案

能否通过动态规划实现

  • 如果使用动态规划实现,必须能够使用集合的语言进行表达,但是这个题目不知道怎么用集合的语言表达。
  • 我应该还是会使用回溯实现!

回溯条件

  • 如果无论A选什么,B都存在必胜的条件,那么就返回false
  • 如果无论A选了某个分支,B无论选了什么,那么就返回true

具体实现代码

java 复制代码
import java.io.FilterOutputStream;
import java.util.*;

/**
 * @author Long Guo
 * @create 2024-08-10-14:32
 *///TIP To <b>Run</b> code, press <shortcut actionId="Run"/> or
// click the <icon src="AllIcons.Actions.Execute"/> icon in the gutter.
public class Main {
    // 定义不同的状态表示当前是谁在报数
    static boolean A = true;
    static boolean B = false;
    static List<Integer> list;   // 能够报的数字的列表
    static Map<Integer, Boolean> cached;

    static boolean dfs(int target, boolean AorB, int cacheNum) {
        /*
         * 具体含义:当前做选择的游戏玩家是否存在胜利的情况,存在返回true,不存在返回false
         * list表示剩余列表中所有能够选择的数字
         * target表示目标数值
         * AorB表示对应的角色,true表示为A先手,false表示B,后手
         * 基本思路:
         *    在所有搜索树中,总共有两种选择关系,分别是的由A到B和由B到A
         *        A选B:一旦所有B的情况中,有一种是B必胜的情况,那么就不能选,因为B一定会选必胜的情况,所以这里需要的将所有B可选的情况通过与&进行连接
         *        B选A:一旦所有的A的情况中,有一种的A必胜的情况,B就不会选,所以这里要选择全部是false的情况,也就是通过或进行连接,全部为false的情况
         *    最终通过回溯,判定当前节点下是否存在A必胜的情况
         */

        // 临界条件,必赢状况,这里需要特殊处理,如果是B的回合,那就是A必输的情况
        int m = list.size();
        if (list.get(m - 1) >= target) return true;

        // 分情况遍历所有可能地选择
        boolean flag;
        for (int i = 0; i < m; i++) {
            int curNum = cacheNum | (1 << list.get(i));
            if (cached.containsKey(curNum)) flag = cached.get(curNum);
            else {
                int tempNum = list.get(i);
                int tempTar = target - tempNum;
                list.remove(i);
                flag = dfs(tempTar, !AorB, curNum);
                cached.put(curNum, flag);
                list.add(i, tempNum);
            }
            if (!flag) return true;
        }
        return false;
    }

    static boolean isAlwaysWin(int N, int Target) {
        for (int i = 0; i < N; i++) {
            int cacheNum = 0 | (1 << i + 1);
            int tempNum = list.get(i);
            int tempTar = Target - tempNum;
            list.remove(i);
            if (!dfs(tempTar, B, cacheNum)) return true;
            list.add(i, tempNum);
            cached.put(cacheNum, false);
        }
        return false;
    }
//

    public static void main(String[] args) {

        // 处理输入输出
//        Scanner in = new Scanner(System.in);
//        String nInput = in.nextLine();
//        String targetInput = in.nextLine();
//        int n = Integer.parseInt(nInput.replaceAll("[^0-9]]",""));
//        int target = Integer.parseInt(targetInput.replaceAll("[^0-9]]",""));
        int n = 5;
        int target = 8;

        // 生成对应的可报数的列表
        list = new ArrayList<>();
        cached = new HashMap<>();
        for (int i = 1; i <= n; i++) list.add(i);

        // 这两种是一个特殊情况,刚好是需要顺次报完所有的数字的,偶数的话后手必胜,奇数的话A必胜
        if (n % 2 == 0 && target == (n + 1) * n / 2) System.out.println(false);
        else if (n % 2 == 1 && target == (n + 1) * n / 2) System.out.println(true);
        else
            // 正常需要迭代判断的情况
            System.out.println(isAlwaysWin(n, target));

        //
//        System.out.println(isAlwaysWinSingle(list,n,target));

    }
}

总结

  • 过不过再说哈,现在先写在这里!
  • 第一面还行,直接让我过了,说过两天给我发一道算法题,然后让我好好做一下!继续在准备,晚上去运动一下,然后接着看项目!加油!
    8/11
  • 今天晚上完成了wind数据的笔试,差不多花了四五个小时,然后想清楚了,也写完了。感觉还行,还能继续面试!
相关推荐
面试鸭1 小时前
离谱!买个人信息买到网安公司头上???
java·开发语言·职场和发展
测试19983 小时前
2024软件测试面试热点问题
自动化测试·软件测试·python·测试工具·面试·职场和发展·压力测试
马剑威(威哥爱编程)4 小时前
MongoDB面试专题33道解析
数据库·mongodb·面试
程序员勋勋6 小时前
【自动化测试】如何在jenkins中搭建allure
职场和发展·jenkins·测试覆盖率
独行soc6 小时前
#渗透测试#SRC漏洞挖掘#深入挖掘XSS漏洞02之测试流程
web安全·面试·渗透测试·xss·漏洞挖掘·1024程序员节
咕咕吖6 小时前
对称二叉树(力扣101)
算法·leetcode·职场和发展
理想不理想v6 小时前
‌Vue 3相比Vue 2的主要改进‌?
前端·javascript·vue.js·面试
sszmvb12347 小时前
测试开发 | 电商业务性能测试: Jmeter 参数化功能实现注册登录的数据驱动
jmeter·面试·职场和发展
测试杂货铺7 小时前
外包干了2年,快要废了。。
自动化测试·软件测试·python·功能测试·测试工具·面试·职场和发展
王佑辉7 小时前
【redis】redis缓存和数据库保证一致性的方案
redis·面试