最后的希望,快手三面了...

2024-01-04 12:23:19 浏览数 (2)

哈喽~,大家好,我是千羽。

快手三面还是考问的简单几道题,讨论了数据库查询、Redis分布式模式和JDK1.8的优化,同时分享了算法题的回溯法解决方案。问的很常规。算法写出来了,三面求过过过过!!

  • (1) count(1), count(*) 和 count(col)的差别?
  • (2) redis有几种分布式模式
  • (3) JDK1.8相比JDK1.7有哪些优化
  • (4) 线程池shutDown和shutDownNow有什么区别
  • (5)算法题:
  • (6)实习课题的介绍和反思

(1) count(1), count(*) 和 count(col)的差别?

  1. COUNT(1) 这个语法表示对行的计数,不管行中的数据是什么。使用 COUNT(1) 或者 COUNT(*) 都会计算表中的所有行数,不会对具体的列进行计算。 例如:SELECT COUNT(1) FROM table_name;
  2. COUNT(*)COUNT(1) 类似,也是对行进行计数,不管行中的数据是什么。它与 COUNT(1) 的效果基本一致,通常被用来计算表中的行数。 例如:SELECT COUNT(*) FROM table_name;
  3. COUNT(col) 这个语法中的 col 是指定的列名,COUNT(col) 会对指定列中非 NULL 值的数量进行计数。 例如:SELECT COUNT(col_name) FROM table_name;

(2) redis有几种分布式模式

  1. 主从复制(Master-Slave Replication): 这是最基本的 Redis 分布式模式之一。在主从复制中,有一个主节点(Master)和多个从节点(Slave)。主节点负责处理写操作和读操作,而从节点则复制主节点的数据,可以处理读请求,但不允许写入。主从复制提高了读取性能和数据的冗余备份。
  2. Sentinel(哨兵模式): Sentinel 是用于监控 Redis 主从复制结构的一种机制。它会监控 Redis 的运行状况,并在主节点失效时自动将一个从节点升级为新的主节点,确保系统的高可用性。
  3. Cluster(集群模式): Redis Cluster 是 Redis 提供的分布式解决方案之一。它通过分片(Sharding)的方式将数据分布到多个节点上,并允许跨节点进行数据的读写操作。每个节点都负责管理一部分数据,并且可以处理自己分片的读写请求。
  4. Twemproxy(nutcracker): Twemproxy 是一个代理层,用于在 Redis 服务器和客户端之间进行负载均衡和分片。它可以将客户端的请求分发到不同的 Redis 实例,实现数据的分片存储和负载均衡。

(3) JDK1.8相比JDK1.7有哪些优化

  1. Lambda 表达式和函数式编程支持: JDK 1.8 引入了 Lambda 表达式和函数式接口,使得 Java 更好地支持函数式编程范式。这使得编写简洁、易读的代码更加容易,并且能够更好地利用多核处理器的优势。
  2. Stream API: 引入了 Stream API,使得对集合进行高效的、函数式的处理变得更加简单。它提供了丰富的操作符(如 map、filter、reduce 等),可以进行链式操作,简化了对集合的操作和处理。
  3. 接口默认方法和静态方法: JDK 1.8 支持在接口中添加默认方法和静态方法。默认方法允许在接口中提供默认的实现,使得现有的接口可以向后兼容;而静态方法则允许在接口中定义静态方法。
  4. 新的日期时间 API: 引入了 java.time 包,提供了新的日期时间 API,解决了旧 API 存在的许多问题,并提供了更好的性能和灵活性。
  5. Parallel 并行库增强: 对并行编程进行了改进和增强,例如并行流和并行数组操作,使得利用多核处理器进行并行计算更加方便。
  6. 新的编译器(JVM 改进): JDK 1.8 中包含了一些对于 JVM 的改进,如改进的 JIT 编译器、新的垃圾收集器(G1 垃圾收集器)等,提高了性能和稳定性。
  7. 其他改进: 还有一些其他的改进,比如改进的注解处理(Type Annotations、Repeatable Annotations 等)、更好的 JavaScript 引擎(Nashorn)等。

(4) 线程池shutDown和shutDownNow有什么区别

  1. shutdown() 这个方法会先允许已经提交的任务(包括正在执行和等待执行的任务)执行完毕,然后关闭线程池。它不会接受新的任务提交,但会等待已提交的任务执行完成后才会关闭线程池。shutdown() 方法返回后,线程池状态将变为 SHUTDOWN
  2. shutdownNow() 这个方法会尝试立即关闭线程池。它会中断所有正在执行的任务,并返回等待执行的任务列表。shutdownNow() 方法会试图停止所有的活动线程,不管是否完成任务。它会立即停止接受新的任务,并尝试终止当前正在执行的任务。shutdownNow() 方法返回后,线程池状态将变为 SHUTDOWN 或者 STOP

(5)算法题:

“对于给定一个数组arr,找到和为n的所有集合。例如arr = [1,2,3,4,5,6], n = 7 返回[[1,6], [2,5],[3,4], [1,2,4]]

这个问题可以使用回溯法(backtracking)来解决。回溯法通常用于解决组合、排列和搜索等问题。

使用 Java 实现的回溯法来找到和为目标值的所有集合:

代码语言:javascript复制
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class FindSumCombinations {
    public static List<List<Integer>> findCombinations(int[] arr, int target) {
        List<List<Integer>> result = new ArrayList<>();
        Arrays.sort(arr); // 对数组进行排序

        backtrack(arr, target, 0, new ArrayList<>(), result);
        return result;
    }

    private static void backtrack(int[] arr, int target, int start, List<Integer> path, List<List<Integer>> result) {
        if (target == 0) { // 如果目标和为0,表示找到了一个组合
            result.add(new ArrayList<>(path));
            return;
        }

        for (int i = start; i < arr.length; i  ) {
            if (arr[i] > target) {
                break; // 当前值已经超过了目标和,结束循环
            }

            // 回溯法:尝试添加当前值到组合中
            path.add(arr[i]);
            backtrack(arr, target - arr[i], i   1, path, result);
            path.remove(path.size() - 1); // 回溯,移除当前值,尝试下一个可能的值
        }
    }

    public static void main(String[] args) {
        int[] arr = {1, 2, 3, 4, 5, 6};
        int target = 7;

        List<List<Integer>> result = findCombinations(arr, target);
        System.out.println(result);
    }
}

这段代码会输出 [[1, 6], [2, 5], [1, 2, 4], [3, 4]],它使用了回溯法来找到数组中和为目标值的所有集合。

(6)实习课题的介绍和反思

  • 原文链接:https://github.com/warthecatalyst/What-to-in-Graduate-School/blob/main/秋招的面经/华科计科第二人的秋招报告.md

0 人点赞