八股文面试day2

一:SpringMVC处理一个请求的流程是怎样的?

  1. tomcat服务器接受到一个请求后,会交给DispatcherServlet进行处理
  2. DispatcherServlet会根据请求的path找到对应的Handler
  3. Handler就是一个加了@RequestMapping方法,然后通过反射执行该方法
  4. 执行该方法之前会去解析方法参数,比如解析@RequestParam、@RequestHeader、@PathVariable等注解
  5. 解析这些注解就是从请求中获取相对应的数据,比如请求头、请求parameters,然后把数据传给对应的参数
  6. 有了参数后就开始执行方法
  7. 执行方法后,就会得到方法的返回值,SpringMVC会对返回值进行解析
  8. 如果方法上加上@ResponseBody,那么就把返回值直接返回给浏览器
  9. 在这个过程中可能需要把一个对象转成JSON字符串才能返回给浏览器
  10. 如果方法上没有加@ResponseBody,那么就会进行视图解析,然后把解析之后的html数据返回给浏览器

二:SpringMVC工作流程

  • 用户发起请求到前端控制器(DispatcherServlet)

  • 前端控制器收到请求调用处理器映射器(HandlerMapping)

  • 处理器映射器根据请求的URL找到具体的处理器 生成处理器对象及处理器拦截器 一并返回给DispatcherServlet

  • 前端控制器调用处理器适配器(HandlerAdapter)去执行处理器(Handler)

  • 处理器适配器去执行Handler

  • Handler执行完给处理器适配器返回ModelAndView

  • 处理器适配器向前端控制器返回ModelAndView

  • 前端控制器请求视图解析器(ViewResolver)去执行视图解析

  • 视图解析器向前端控制器返回视图View

  • 前端控制器对视图View进行渲染

  • 前端控制器向用户响应结果

三:ArrayList扩容机制

四:归并排序(分治和合并)

4399笔试一

package com.huhu.sort;
import java.util.Arrays;
//归并排序
public class MergeSort {
    public static void main(String[] args) {
//        int[] arr = {8, 4, 5, 7, 1, 3, 6, 2};
        int[] arr = {100,5,7,20,97,18,39,50,72};

        int[] temp = new int[arr.length];//归并排序需要一个额外空间
        mergeSort(arr, 0, arr.length - 1, temp);
        System.out.println("归并排序后数组:" + Arrays.toString(arr));
    }

    //分+合方法
    public static void mergeSort(int[] arr, int left, int right, int[] temp) {
        if (left < right) {
            int mid = (left + right) / 2;//中间索引
            //向左递归进行分解
            mergeSort(arr, left, mid, temp);
            //向右递归进行分解
            mergeSort(arr, mid + 1, right, temp);
            //到合并
            merge(arr, left, mid, right, temp);
        }
    }

    //合并方法

    /**
     * @param arr   排序的原始数组
     * @param left  左边有序序列的索引
     * @param mid   中间索引
     * @param right 右边索引
     * @param temp  做中转的数组
     */
    public static void merge(int[] arr, int left, int mid, int right, int[] temp) {
        //System.out.println("xxxx");
        int i = left;//初始化i,左边有序序列的初始索引
        int j = mid + 1;//初始化j,右边有序序列的初始索引
        int t = 0;//指向temp数组的当前索引

        //(一)
        //先把左右两边(有序)的数据按照规则填充到temp数组
        //直到左右两边的有序序列,有一边处理完毕为止
        while (i <= mid && j <= right) {
            //如果左边的有序序列的当前元素,小于等于右边有序序列的当前元素
            //则把左边有序序列的当前元素放到temp数组
            //然后t++,i++
            if (arr[i] <= arr[j]) {
                temp[t] = arr[i];
                t += 1;
                i += 1;
            } else {
                //反之
                //如果左边的有序序列的当前元素,大于右边有序序列的当前元素
                //则把右边有序序列的当前元素放到temp数组
                //然后t++,i++
                temp[t] = arr[j];
                t += 1;
                j += 1;
            }
        }

        //(二)
        //把有剩余数据的一边的数据依次全部填充到temp
        while (i <= mid) {//左边的有序序列还有剩余的元素,就全部填充到temp
            temp[t] = arr[i];
            t += 1;
            i += 1;
        }

        while (j <= right) {//右边的有序序列还有剩余的元素,就全部填充到temp
            temp[t] = arr[j];
            t += 1;
            j += 1;
        }

        //(三)
        //将temp数组拷贝到arr
        //注意:并不是每次都拷贝所有
        t = 0;
        int tempLeft = left;//
        //System.out.println("tempLeft=" + tempLeft + ",right=" + right);
        while (tempLeft <= right) {//第一次合并 tempLeft=0 right=1 第二次合并 tempLeft=2 right=3 第三次合并 tempLeft=0 right=3
            //第四次合并 tempLeft=4 right=5 第五次合并 tempLeft=6 right=7 第六次合并 tempLeft=4 right=7
            //最后一次合并 tempLeft=0 right=7
            arr[tempLeft] = temp[t];
            t += 1;
            tempLeft += 1;
        }
    }
}

五:动态规划 

4399笔试二

有 n 个气球,编号为0 到 n - 1,每个气球上都标有一个数字,这些数字存在数组 nums 中。

现在要求你戳破所有的气球。戳破第 i 个气球,你可以获得 nums[i - 1] * nums[i] * nums[i + 1] 枚硬币。 这里的 i - 1 和 i + 1 代表和 i 相邻的两个气球的序号。如果 i - 1或 i + 1 超出了数组的边界,那么就当它是一个数字为 1 的气球。

求所能获得硬币的最大数量。

示例 1:
输入:nums = [3,1,5,8]
输出:167
解释:
nums = [3,1,5,8] --> [3,5,8] --> [3,8] --> [8] --> []
coins =  3*1*5    +   3*5*8   +  1*3*8  + 1*8*1 = 167
示例 2:输入:nums = [1,5]
输出:10

n == nums.length
1 <= n <= 300
0 <= nums[i] <= 100

题解:求解戳破所有气球之和最大硬币数量,换思路来说假设第k个气球为最后一个戳破的,那么maxCoin=Math.max(dp[i][j],dp[i,k]+dp[k,j]+nums[0]*nums[nums.length]*nums[k])(nums数组原来气球基础上首尾加上虚拟气球值1,方便计算,注意区间都是左开右开)

重要技巧:我们初始一维数组所有值都为-1

import java.util.Arrays;

public class BiShi3 {
    public static void main(String[] args) {
        int[] a = {3, 1, 5, 8};
        ChuoQiQiu c = new ChuoQiQiu();
        System.out.println(c.maxCoins(a));
    }
}

class ChuoQiQiu {
    int[][] dp;

    public int maxCoins(int[] a) {
        int n = a.length;
        int[] temp = new int[n + 2];
        temp[0] = 1;
        temp[n + 1] = 1;
        for (int i = 0; i < n; i++) {
            temp[i + 1] = a[i];
        }
        dp = new int[n + 2][n + 2];
        for (int i = 0; i < n + 2; i++) {
            Arrays.fill(dp[i], -1);//标记位dp[i]下一维数组都为-1
        }
        return solve(temp, 0, n + 1);
    }

    // 开区间(l,r)
    private int solve(int[] temp, int l, int r) {
        if (l + 2 > r) {// 区间内没有气球
            return 0;
        }
        if (l + 2 == r) {// 区间刚好有1个气球
            return temp[l] * temp[l + 1] * temp[r];
        }
        if (dp[l][r] != -1) {
            return dp[l][r];
        }
        int k = l + 1;//戳第k个气球
        int res=0;
        // k的范围是[1,n]
        while (k <= r - 1) {
            int left = solve(temp, l, k);//第k个气球左区间最大硬币值
            int right = solve(temp, k, r);//第k个气球右区间最大硬币值
            res=Math.max(res,left+right+temp[l]*temp[k]*temp[r]);
            k++;
        }
        dp[l][r]=res;
        return res;
    }
}

招聘笔试

输入一个字符串,在其中寻找长度最长的,不含重复字符的字符串,如果有多个长度相同的最长子字符串,则全部输出

注意:子字符串应由输入的字符串中的连续字符组成

输入:abcdabcde

输出:abcde

输入:abcdabcde

输出:abcd,bcda,cdab,dabc,abcd

package 滑动窗口;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
public class Main {

    public static void main(String[] args) {
        String str="abcdabcd";
        HashMap<Object, ArrayList<Object>> map = new HashMap<>();
        for (int i=0;i<str.length();i++){
            //第一次从a开始   第二次从b开始
            ArrayList<Object> array = new ArrayList<>();
            for (int j=i;j<str.length();j++){
                char c = str.charAt(j);
                if (!array.contains(c)){
                    array.add(c);
                    //处理边界  当i==5的时候  到遍历结束都不会进入到else代码块里面  所以需要判断一下
                    if (j==str.length()-1){
                        map.put(i,array);
                    }
                }else {
                    map.put(i,array);
                    //结束循环
                    break;
                }
            }
        }
        ArrayList<ArrayList<Object>> arrayList = new ArrayList<>();
        //将map转为collection集合,放到List里面去
        arrayList.addAll(map.values());
        //保存最大长度数字
        int maxCount=0;
        //获取最大长度
        for (ArrayList<Object> obj:arrayList){
            int size = obj.size();
            if (size>maxCount){
                maxCount=size;
            }
        }
        StringBuilder stringBuilder = new StringBuilder();
        for (ArrayList<Object> obj:arrayList){
            if (obj.size()==maxCount){
                //遍历
                for (Object o:obj){
                    stringBuilder.append(o);
                }
                stringBuilder.append(",");
            }
        }
        System.out.println(stringBuilder);
        //获取最后一个字符
        char c = stringBuilder.toString().charAt(stringBuilder.length() - 1);
        if (c==','){
            //去掉最后一个 ,
            String substring = stringBuilder.substring(0, stringBuilder.length() - 1);
            System.out.println(substring);
        }
        System.out.println();
        //输出map进行查看
        map.forEach((key,value)->{
            System.out.println(Arrays.toString(value.toArray()));
        });
    }
}

题目:美味度之和最大值 输入参数n ai bi n代表天数 零食a:每天对应的美味度 零食b:每天对应的美味度 且零食a和零食b不能连续吃2天即一天得换一种口味,也可以选择不吃

import java.util.Scanner;

public class BiShi1 {
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        int n=sc.nextInt();
        int[] a=new int[n];
        int[] b=new int[n];
        for (int i = 0; i < n; i++) {
            a[i]=sc.nextInt();
        }
        for (int i = 0; i < n; i++) {
            b[i]=sc.nextInt();
        }
        System.out.println(maxHappy(a,b,n,0));
    }
    public static int maxHappy(int[] a, int[] b,int n,int choice){
        if(n == 0){
            return 0;
        }
        int c = maxHappy(a,b,n-1,0);
        // 回溯
        int a1 = a[a.length - n] + maxHappy(a,b,n-1,1);
        int b1 = b[b.length - n] + maxHappy(a,b,n-1,2);
        //0代表上一天没吃零食 可以选择吃a或b
        if(choice == 0){
            return Math.max(Math.max(a1,b1),c);
        }

        //1代表上一天吃的a零食,只能选择不吃或者吃b
        if(choice == 1){
            return Math.max(c,b1);
        }else {
            return Math.max(c,a1);//2代表上一天吃的b零食,只能选择不吃或者吃a
        }

    }
}

吃法:2->3->3->4>5   结果相加为17

六:OSI七层协议模型中各层作用及其有关的网络协议

  1. 物理层:利用传输介质为数据链路层提供物理连接,实现比特流的透明传输
  2. 数据链路层:在物理层提供的比特流的基础上,通过差错控制、流量控制方法,使有差错的物理线路变为无差错的数据链路,即提供可靠的通过物理介质传输数据的方法。
  3. 网络层:通过路由将数据从源地址转发到目的地址,实现ip跳转(IP、ICMP、ARP、RARP)
  4. 传输层:向网络层提供可靠的端到端的差错和流量控制,保证报文的正确传输;同时向高层屏蔽下层数据通信的细节,保证上层(应用层)提供数据正确、无误(TCP、UDP)
  5. 会话层:管理和协调不同主机上各种进程之间的通信(对话),即负责建立、管理和终止应用程序之间的会话建立、管理和维护会话(SMTP、DNS)
  6. 表示层:处理用户信息的表示问题,如编码、数据格式转换和加密解密等
  7. 应用层:直接向用户提供服务,完成用户希望在网络上完成的各种工作(HTTP、TFTP) 

OSI下3层的任务是数据通信,上3层的任务是数据处理。而传输层是OSI模型的第4层。该层提供建立、维护和拆除传输连接的功能,起到承上启下的作用。 

MAC地址即物理地址(不可变)

IP地址即逻辑地址 (可变)

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值