百度实习面经2022-4-24(第一次面试,暂时只面了一场,感觉人无了)

我的学习进度

我走的是JavaEE企业版的开发,目前大三在读,路线也是先学的 c语言、java、HTML+CSS3、Jquery、python等 之后专注于 java 走后端开发路线学了MySQL、JavaWeb、SSM、目前学校还在教Springboot

但我感觉进度太慢了,自学了Springboot、Git、MP、SpringCloud(在学)、Linux(再学)、dubbo+zookeeper等一些知识点,然后把JavaSE、MySQL复习了一遍、目前还在复习Java多线程的知识点

笔试过程

为什么给大家说我学的路线和进度呢 ,因为我做笔试的时候就发现了一个很大的问题,我选错职位了,只看见了招Java的就去了,报的是移动开发(Android或者IOS),做题那叫一个懵逼啊,还好有java基础题、数据结构设计、计算机网络、操作系统等题还看得懂,但还是懵逼的很,还有三道算法,做了两个小时,也不知道做了啥,交上去就感觉无了,但就这样神奇的通过了笔试,虽然我不知道是怎么过的,但大家千万不要妄自菲薄,虽然自己不咋地,但同届的又有多强呢,有职位就投,但还是得看看自己对口的是什么,不然过了笔试,面试也会懵逼。

面试通知下达

这里我说一下,百度发面试通知的时候,会有个链接,点进去后选择自己希望面试的时间,这里大家尽力早的选择,我因为想跟辅导员了解一下面试过程就点晚了,提示我当前面试页面显示的这些时间段人满了(链接里没有任何hr的联系方式),这就搞得我更懵逼了,给面试机会不让面试,这不是耍猴吗,但当时时间还早,距离面试还有两天,我当晚去笔试了另一家银行后,在进入页面,就有其他的时间段了,所以遇事不要慌,是等等党的胜利(但工作这事你不上,别人就上了,我特指没办法的是,不要让慌张让你紊乱,该干啥干啥)

面经(牛客网上面试)

我约的四点的面试,三点半我想试试可以联线吗,一点排队,面试官秒接,然后面试就开始了,面试官一上来找我要了一份简历,看了之后说,你学的与我们招的不对口还需要继续吗?(虽然面试官态度真的很好,但对我是暴击),所以投简历的时候一点要看职位与专业对不对口,我就硬着头皮说“我可以学,可以继续面试吗”(我也不想错过这第一次面试的机会),面试官会根据你的情况出题,所以没有问我关于Android相关的问题

一、做自我介绍

我介绍了我自己和做项目的经历(这里可以挖些坑,比如你用了什么方法,不细讲,如果运气好,下一个问题或许会问,这样你可以根据自己学的高谈阔论)

二、根据自我介绍的问题问项目经历

自己挖的坑自己填,然后不要弄些假项目,不然不好说

三、由于我做了微信小程序(问了一下小程序相关的知识点)

这个跟java无关,就略了

四、用过多线程吗?怎么保证线程安全?是怎么实现的加锁?

用过:我用过...

线程安全:

(1) 竞争与原子操作

多线程同时访问和修改同一个数据时,可能存在风险,数据不能保证我们得到的预期数据,解决的办法,我们可以采用原理类,比如JAVA 本身提供了很多的原子类,AtomicInteger ,AtomicLong 等常见的基本数据类型的原子包装类定义,实现数据安全。

(2) 同步与锁

多线程中我们定于的数据,使用Lock去保证数据操作的过程中只有一个线程进入,这个线程拿到锁后,其他线程都不能拿到该锁,进而保证数据的可靠性。

(3) 可重入

一个函数被重入,表示这个函数没有执行完成,但由于外部因素或内部因素,又一次进入该函数执行。例如单片机、处理器的中断会出现重入现象。

参考文章:函数可重入性(Reentrancy)概念详解_Smith先生的博客-CSDN博客_可重入性

(4) 过度优化

即使使用了合理使用锁,也不一定保证了线程安全,因此需要进行代码的二次优化,使用volatile关键字试图阻止过度优化,它可以做两件事:第一,阻止编译器为了提高速度将一个变量缓存到寄存器而不写回;第二,阻止编译器调整操作volatile变量的指令顺序。

参考文章:确保线程安全的几种方法_周兆熊的博客-CSDN博客_确保线程安全的几种方法

java 加锁的三种方式:

1、synchronized方式(重量级锁)

加锁方式:synchronized(object)传入对象,不同对象代表不同锁,可以在线程外部新建对象。

2、Lock(比synchronized要轻量级)

  • 新建锁对象Lock l = new ReentrantLock();
  • 加锁 l.lock()
  • 解锁 l.unlock()

3、wait() notify() notifyAll()

wait() notify() notifyAll() 是Object上的方法,只有Object是对象监视器时候才能调用此方法

  •  notify() 唤醒同一个对象监视器上的线程
  • wait(Long timeout) 传入数值,表示超过某个时间还没有被唤醒则自动唤醒
  • wait和sleep区别:
    •  sleep() 可以在同步中和同步外使用,线程遇到sleep不释放锁,时间到了继续向下执行
    •  w ait() 只能在同步中使用,由对象监视器调用, 线程进入wait状态时释放掉 

五、我在简历中写了熟悉MVC和MVVM模式,谈谈我的理解

所以简历里信息的一定真实

MVC:

MVC(Model View Controller)是软件工程中的一种软件架构模式,它把软件系统分为模型视图控制器三个基本部分。用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。

M:Model,模型。 JavaBean

  • 完成具体的业务操作,如:查询数据库,封装对象

V:view视图。JSP、HTML等来进行数据展示

C:Controller控制器。 Servlet

  • 获取View的请求

  • 调用模型将数据交给视图进行展示

控制器Controller 的作用就是将Model 与 View一一对应起来

我们用用户登录这个例子来说明:

View层是 index.jsp,Cotroller是 /loginServlet,Model是 JavaBean(pojo) 对象

  1. 用户看到的是JSP展示页面,用户输入数据点击登录按钮时,这是JSP会通过数据共享将请求转发到/loginServlet控制器上

  2. 然后控制器再将请求分发到Model上,通过JDBC连接到数据库来查询数据库中是否存在该用户信息。

  3. 若存在该用户,则返回信息,让控制器告诉前台页面展示登陆成功的信息;不存在则告诉登陆失败…

  4. View来响应控制器交给它的数据

在这个过程中,控制器其实只是起到了承上启下的作用,它只负责中转(指挥调度),不负责具体的业务操作。

MVVM:

MVVM是Model-View-ViewModel的简写。它本质上就是MVC 的改进版,整体和mvc差不多,最大的区别就是mvc是单向的,而mvvm是双向的,并且是自动的,也就是数据发生变化自动同步视图,视图发生变化自动同步数据,同时解决了 mvc 中大量的 DOM 操作使页面渲染性能降低,加载速度变慢,影响用户体验。和当 Model 频繁发生变化,开发者需要主动更新到 View

一句话总结:vm层(视图模型层)通过接口从后台m层(model层)请求数据,vm层继而和v(view层)实现数据的双向绑定。

六、做题

题一:反转链表

 百度实习面经2022-4-24(第一次面试,暂时只面了一场,感觉人无了)_第1张图片 

解一:使用栈解决

import java.util.Stack;
public class Solution {
public ListNode ReverseList(ListNode head) {
    Stack stack= new Stack<>();
    //把链表节点全部摘掉放到栈中
    while (head != null) {
        stack.push(head);
        head = head.next;
    }
    if (stack.isEmpty())
        return null;
    ListNode node = stack.pop();
    ListNode dummy = node;
    //栈中的结点全部出栈,然后重新连成一个新的链表
    while (!stack.isEmpty()) {
        ListNode tempNode = stack.pop();
        node.next = tempNode;
        node = node.next;
    }
    //最后一个结点就是反转前的头结点,一定要让他的next
    //等于空,否则会构成环
    node.next = null;
    return dummy;
}
}

解二:双链表求解

public ListNode ReverseList(ListNode head) {
    //新链表
    ListNode newHead = null;
    while (head != null) {
        //先保存访问的节点的下一个节点,保存起来
        //留着下一步访问的
        ListNode temp = head.next;
        //每次访问的原链表节点都会成为新链表的头结点,
        //其实就是把新链表挂到访问的原链表节点的
        //后面就行了
        head.next = newHead;
        //更新新链表
        newHead = head;
        //重新赋值,继续访问
        head = temp;
    }
    //返回新链表
    return newHead;
}

题二:求二叉树的层序遍历

 百度实习面经2022-4-24(第一次面试,暂时只面了一场,感觉人无了)_第2张图片 

解一:递归(前序遍历)

/**
 * struct TreeNode {
 *    int val;
 *    struct TreeNode *left;
 *    struct TreeNode *right;
 * };
 */

class Solution {
public:
    /**
     * 
     * @param root TreeNode类 
     * @return int整型vector>
     */
    //前序遍历模板;
    void f(TreeNode* root,int level,vector> &res){
        if(!root)return ;
        if(level>=res.size()){//最新的深度,申请一个数组存储;
            res.push_back(vector {});
        }
        res[level].push_back(root->val);
        f(root->left,level+1,res);//遍历左子树;
        f(root->right,level+1,res);//遍历右子树;
    }

    vector > levelOrder(TreeNode* root) {
        // write code here
        vector> res;//存储最终结果;
        f(root,0,res);//前序遍历;
        return res;//返回结果;
    }
};

 解二:BFS(迭代)

/**
 * struct TreeNode {
 *    int val;
 *    struct TreeNode *left;
 *    struct TreeNode *right;
 * };
 */

class Solution {
public:
    /**
     * 
     * @param root TreeNode类 
     * @return int整型vector>
     */
    vector > levelOrder(TreeNode* root) {
        // write code here
        vector > vv;
        if(!root){
            return vv;//二叉树为空
        }
        queue qq;//队列存放相邻两层节点;
        qq.push(root);
        while(!qq.empty()){
            vector tempv;
            int size=qq.size();
            for(int i=0;ival);
                //将下一层的节点入队;
                if(tt->left)qq.push(tt->left);
                if(tt->right)qq.push(tt->right);
            }
            vv.push_back(tempv);//加入将要返回的数组中;
        }
        return vv;//返回最终结果
    }
};

这就是百度面试经过,别问我为什么算法题怎么清晰,TM的这是牛客网的原题,晚上我参加腾讯的笔试(五道算法)时在牛客网刷到了!!!!!!所以去看刷题(算法不能少)吧,基础绝对不能落下

 

你可能感兴趣的:(随谈,java,android,百度,面试)