面试问到的一些问题,总结一下

1.在设计数据库时,我们有多个课程老师,辅导员,它们权限都不同,该设计几个表,权限该怎么设计;

	最好的方式是四张表,user(用户表),role(角色表),right(权限表),userroleright(三表联合的表,这张表里其他三张表的主键作为一个联合主键),为了防止某一个角色没有任何人具有,从而丢失了其与权限的对应关系,我们需要添加一个特殊用户,具有所有的角色。同样,为了避免某一个角色没有任何权限,造成丢失这个角色和用户的对应关系,也需要制作一个通用权限,所有的角色都有这个权限;

2.给你一组 整数,选出n-1位数,使他们相乘结果最大,你该怎么办;

这题主要是考一个思维的全面性,方法其实也就是一个循环比大小;要考虑到这组数字全是正数,全是负数,包含0(包含一个0,包含几个0),包含负数(包含一个负数,包含几个负数),整数和负数和0都有的情况等等都要考虑到;然后你需要用一个变量来存储0或负数的个数,这样后面才好排除;

3.用手机app给远处的汽车发出关窗指令,这个过程是怎样的;

	就是http一次请求的流程;

4.快排,hash表 ,的时间复杂度,2的n次方你能怎样降低它的时间复杂度;

常用的数据结构的时间复杂度:
索引			查找			最优查找			   插入
数组		   O(1)			O(n)		O(log n)		O(n)
链表		    O(n)		O(n)		O(n)				O(1)
哈希表		O(1)		O(1)						O(1)
二叉查找树	O(log n)		O(log n)							O(log n)

常用数组排序算法的时间复杂度:
最好情况		平均情况			最坏情况
归并			O(n)		O(nlog n )		O(nlog n )
快排			O(n)		O(nlog n )		O(n的平方 )
冒泡			O(n)		O(n的平方 )		O(n的平方 )

5. 找出100个字符中最长的子字符串,例如:“babac” , 最长的是"ba" ;

kmp算法(字符串匹配算法)——
求next数组:即以模式字符串为主字符串,以模式字符串的前缀为目标字符串,一旦字符串匹配成功,那么当前的next值就是匹配成功的字符串的长度。具体来说,就是从模式字符串的第一位(注意,不包括第0位)开始对自身进行匹配运算。 在任一位置,能匹配的最长长度就是当前位置的next值
void getNext(char *p , int * next){
    next[0] = -1 ;
    int i=0 , j= -1 ;
    
    while(i<strlen(p)){
        if(j== -1  ||  p[i] == p[j]){
            ++i;  ++j ;   next[i] = j ;
        }else{
            j=next[j] ;
        }
    }
}
算法主体: 我们看到如果是在 j 位 失配,那么影响 j 指针回溯的位置的其实是第 j −1 位的 PMT 值,所以为了编程的方便, 我们不直接使用PMT数组,而是将PMT数组向后偏移一位。我们把新得到的这个数组称为next数组
int kmp(char *t,char *p){ //t是待匹配串,p是模板串
    int i=0,j=0 ;    //i指着t串,j指着p串
    while(i<strlen(t) && j<strlen(p)){
        if(j==-1 || t[i] == p[j])
        {
            i++ ;   j++ ;
        }else{
            j=next[j] ;
        }
     if(j==strlen(p))
        return i-j ;
     else
        return -1 ;
    }
}

6.给一段无重复数字的数字序列,输出它的所有可能输出序列,例如[1,2,3],
输出 [1,2,3] , [1,3,2] ,[2,1,3] ,[2,3,1] , [3,1,2] ,[3,2,1] ;

//用一个boolean[] visited数组标记未被访问的位置,
//然后for循环遍历这个数组,找到还没有被访问过的位置,加入队列。
class Solution {
    List<List<Integer>> lists = new ArrayList();
    public List<List<Integer>> permute(int[] nums) {
        List<Integer> arr = new ArrayList();
        boolean[] visited = new boolean[nums.length];
        backTracking(nums, visited, arr);
        return lists;
    }

public void backTracking(int[] nums, boolean[] visited, List<Integer> arr) {
        if (arr.size() == nums.length) {
            // 注意java的值传递,此处必须用重新创建对象的形式
            lists.add(new ArrayList(arr));
            return ;
        }
        for (int i = 0; i < visited.length; i++) {
            if (visited[i]) {
                continue;
            }
            visited[i] = true;
            arr.add(nums[i]);
            backTracking(nums, visited, arr);
            arr.remove(arr.size() - 1);
            visited[i] = false;
        }
    }
}

8.100万个数中,选出最大的10个数字,使得它们的和最大;

第一种:
先取出前100个数,维护一个100个数的最小堆,遍历一遍剩余的元素,在此过程中维护堆就可以了。具体步骤如下: step1:取前m个元素(例如m=100),建立一个小顶堆。保持一个小顶堆得性质的步骤,运行时间为O(lgm);建立一个小顶堆运行时间为m*O(lgm)=O(m lgm);       
step2:顺序读取后续元素,直到结束。每次读取一个元素,如果该元素比堆顶元素小,直接丢弃 
如果大于堆顶元素,则用该元素替换堆顶元素,然后保持最小堆性质。最坏情况是每次都需要替换掉堆顶的最小元素,因此需要维护堆的代价为(N-m)*O(lgm); 最后这个堆中的元素就是前最大的10W个。时间复杂度为O(N lgm)。     简单来说就是:假设数组arr保存100个数字,首先取前100个数字放入数组arr,对于第101个数字k,如果k大于arr中的最小数,则用k替换最小数,对剩下的数字都进行这种处理。
第二种:
分块查找 ,先把100w个数分成100份,每份1w个数。先分别找出每1w个数里面的最大的数,然后比较。找出100个最大的数中的最大的数和最小的数,取最大数的这组的第二大的数,与最小的数比较。

9.某城市只有两种颜色的车,蓝色的概率为15%,红色的概率为85%,一天一辆车撞人后跑了,据目击者说是蓝车;警官判断目击者看清楚了的概率为80%,看错了的概率为20%,问 是蓝色车撞人的概率是多少?

10.一些 零散的小问题

字符串入栈出栈的可能排序组合:ABC 即A进baiA出,duB进B出,C进C出 ACB  A进A出,zhiB进C进,daozhuanC出B出 BAC A进shuB进,B出A出,C进C出 BCA A进B进,B出C进,C出A出 CBA A进B进,C进C出,B出A出 共5种 (CAB 不满足要要求的)

DMA是什么:DMA 预处理,CPU向DMA送命令,如DMA方式,主存地址,传送的字数等,之后CPU执行原来的程序,DMA 控制在 I/O 设备与主存间交换数据

深度优先排序是什么:
public class DepthFirstOrder {
    private boolean[] marked;//索引代表顶点,值表示当前顶点是否已经被搜索
    private Stack<Integer> reversePost;//使用栈,存储顶点序列

    public DepthFirstOrder(Digraph G){//创建一个检测环对象,检测图G中是否有环
        this.marked = new boolean[G.V()];//初始化marked数组
        this.reversePost = new Stack<Integer>();//初始化reversePost栈
        //遍历图中的每一个顶点,让每个顶点作为入口,完成一次深度优先搜索
        for (int v = 0; v < G.V(); v++) {
            if(!marked[v]){
                dfs(G,v);
            } } }
    /**
     * 基于深度优先搜索,检测图G中是否有环
     * @param G
     * @param v
     */
    private void dfs(Digraph G,int v){
        marked[v] = true; //标记当前v已经被搜索
        for (Integer w : G.adj(v)) {//通过循环深度搜索顶点v
            if(!marked[w]){
                dfs(G,w);//如果当前顶点w没有搜索,则递归调用dfs进行搜索
            }
        }
        //让顶点v进栈
        reversePost.push(v);
    }
    /**
     * 获取顶点线性序列
     * @return
     */
    public Stack<Integer> reversePost(){
        return reversePost;
    }
}

基于浏览器的一次完整的http请求:

https://www.jianshu.com/p/4cb8227cd766
1.URL解析/DNS解析查找域名IP地址:首先判断协议,如果是 http/https 就按照 Web 来处理,如果地址不是一个IP地址而是域名则通过DNS(域名系统)将该地址解析成IP地址
2.应用层客户端发送HTTP请求:HTTP请求报文由:请求行,请求头、空行和请求数据4部分组成
3.传输层TCP传输报文:浏览器会在传输层发起一条到达服务器的 TCP 连接,位于传输层的TCP协议为传输报文提供可靠的字节流服务,TCP协议通过“三次握手”等方法保证传输的安全可靠:发送端发一个带有SYN标志的数据包给接收端,接收端返回一个SYN/ACK标志的数据包表示自己已收到,发送端再发送一个带有ACK标志的数据包给接收端以示握手成功。
4.网络层IP协议查询MAC地址:IP协议的作用是把TCP分割好的各种数据包封装到IP包里面传送给接收方。而要保证确实能传到接收方还需要接收方的MAC地址,也就是物理地址才可以。IP地址和MAC地址是一 一对应的关系。
5.数据到达数据链路层:在找到对方的MAC地址后,已被封装好的IP包再被封装到数据链路层的数据帧结构中,将数据发送到数据链路层传输,再通过物理层的比特流送出去。这时,客户端发送请求的阶段结束。
6.服务器接收数据:接收端的服务器在链路层接收到数据包,再层层向上直到应用层。这过程中包括在传输层通过TCP协议将分段的数据包重新组成原来的HTTP请求报文。
7.服务器响应请求并返回相应文件:http 服务器首先会查看重写规则,然后如果请求的文件是真实存在,例如一些图片,或 html、css、js 等静态文件,则会直接把这个文件返回,如果是一个动态的请求就根据动态语言的脚本,来决定调用什么类型的动态文件脚本解释器来处理这个请求(Java,php);
8.Web服务器关闭TCP连接:一般情况下,一旦 Web 服务器向浏览器发送了请求的数据,它就要关闭 TCP 连接,但是如果浏览器或者服务器在其头信息加入了这行代码:Connection:keep-alive ,TCP连接在发送后将仍然保持打开状态;
9.浏览器开始处理数据信息并渲染页面

Linux常用命令有哪些?

cd 切换到某个目录
ls 列出当前目录的所有文件,文件夹
pwd 列出当前目录的路径
cp 复制
mv 剪切
rm 删除
find 查找
ps 查看进程
cat 查看某文件
tar 打包
chmod 赋权限
vim 文本编辑

数据库
请写出一个SQL来查询分数前五5的所有人?
mysql:select * from 分数表 order by 分数 desc limit 5;

算法
字符串反转输出?

public String reverse(String s){
char[] letters=s.toCharArray();
char temp;
int len=letters.length;
for(int i=len/2-1;i>=0;i--){
temp=letters[i];
letters[i]=letters[len-1-i];
letters[len-1-i]=temp;
}
return new String(letters);
}

11 http请求报文的内容:

1.内容包括 请求行,请求头部,空行和请求数据 四个部分
请求行由请求方法字段、URL字段和HTTP协议版本字段3个字段组成,它们用空格分隔。例如,GET /index.html HTTP/1.1。
请求头部由关键字/值对组成,每行一对,关键字和值用英文冒号“:”分隔。
Accept:客户端可识别的内容类型列表。	Host:请求的主机名,允许多个域名同处一个IP地址,即虚拟主机。
最后一个请求头之后是一个空行,发送回车符和换行符,通知服务器以下不再有请求头。
请求数据不在GET方法中使用,而是在POST方法中使用。POST方法适用于需要客户填写表单的场合。

12 转发和重定向的区别

转发在服务器发生,浏览器地址不变,只能发送到此web页面能发送到的地方,地址栏不用写到应用程序的;重定向在客户端发生,浏览器地址改变,能发送到任何地方,需要把应用程序的地址也写上。

13 内存调优的方法你知道哪些

(1)避免阻塞主线程,不要让主线程担任过多的任务,只让他渲染,管理交互反应,回应交互等就好
(2)使用重用和延时加载视图,(3)使用cache缓存技术;

14 递归实现5!

public static int jiecheng(int n){
    if(n==1) return 1 ;
    if(n!=1) return n*jiecheng(n-1) ;
}

1.堆 和 栈 有什么区别?
:通常我们定义一个基本数据类型的变量,一个对象的引用,还有就是函数调用的现场
保存都使用内存中的栈空间;而通过new关键字和构造器创建的对象放在堆空间;
程序中的字面量如直接书写的100,“hello”和常量都是放在静态区中;
栈空间操作起来最快但是栈很小,通常大量的对象都是放在堆空间。

3.jvm加载class文件的原理机制
:当java程序需要使用某个类时,jvm会确保这个类已经被加载,连接(验证,准备和解析)和初始化。类的加载是指把类的.class文件中的数据读入到内存中,通常是创建一个字节数组读入.class文件,然后产生与所加载类对应的class对象。加载完成后,
Class 对象还不完整,所以此时的类还不可用。当类被加载后就进入连接阶段,这一阶段包 括验证、准备(为静态变量分配内存并设置默认的初始值)和解析(将符号引用替换为直接 引用)三个步骤。最后 JVM 对类进行初始化,包括:1)如果类存在直接的父类并且这个类 还没有被初始化,那么就先初始化父类;2)如果类中存在初始化语句,就依次执行这些初始 化语句。

4.举例说明同步和异步
:如果系统中存在临界资源(资源数量少于竞争资源的线程数量的资源),例如正在写的 数据以后可能被另一个线程读到,或者正在读的数据可能已经被另一个线程写过了,那么这 些数据就必须进行同步存取(数据库操作中的排他锁就是最好的例子)。当应用程序在对象 上调用了一个需要花费很长时间来执行的方法,并且不希望让程序等待方法的返回时,就应 该使用异步编程,在很多情况下采用异步途径往往更有效率。事实上,所谓的同步就是指阻 塞式操作,而异步就是非阻塞式操作。

5.jdbc怎么用的
:加载驱动,创建连接,创建语句,执行语句,处理结果,关闭资源

6.获得一个类的类对象的三种方式:

  1. 类型.class 例如:String.class
  2. 对象.getClass() 例如:“hello” . getClass()
  3. Class.forName() 例如: Class.forName(“java.lang.String”)

8.反射是什么
Java 反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为 Java 语言的反射机制。
Spring中的依赖注入,类的加载就用的反射

9.HashSet集合怎样判断重复:
1.先调用对象的hashcode方法生成hash值(int值 保证添加时的效率)
2.再调用equals进行比较,防止hash值一样内容却不一样的现象

10.静态成员何时加载?
:类加载时就开始加载,因为静态成员是属于类的,不属于方法

11.子类继承父类的是非私有的成员变量和方法,还是全部都继承了?
:全部都继承了,只是私有的成员变量子类无法直接访问,必须通过get/set方法的形式访问;

12/Lambda表达式的用法? 暂时不会,先放着

13.直到read(byte[] b)方法返回-1,即表明到了输入流的结束点,到了结束点为什么会返回-1 ?
因为本来FileReader 是char型的,它的read方法返回值我们定义的是int型,char的取值范围为0~65535,不包含负数,int取值范围可以包含,所以用个-1 来表示到数组末尾了就很好了;免得如果在char的范围内的话,可能还没读完就以为到结尾了。

  1. Unicode 字符集中符号大于 0xC0 的所有符号组合构成(各符号之间没有空格)有哪些?
    :Unicode编码用两个字节表示一个字符,ASCII码用1个字节,0xC0,通过查ascii码表可知代表字符‘A’ ,大于它的 包括所有的中文,日文,韩文等。

15.在Java中要对对象排序的两种方式:
一是在创建对象的类实现comparable接口,二是在排序时实现comparator接口

2021/7/1:面试的算法题
题目:定义两个二维数组A,B,给A赋值,然后以A[i][j]为中心找出它周围的所有元素,
按从小到大排序后找出中间值,中间值=周围元素的数量/2 的位置,B[i][j]的值就等于中间值,输出B二维数组。

Student(S#,Sname,Sage,Ssex) 学生表 Course(C#,Cname,T#) 课程表 SC(S#,C#,score) 成绩表 Teacher(T#,Tname) 教师表 问题: 1、查询“001”课程比“002”课程成绩高的所有学生的学号; select a.S# from (select s#,score from SC where C#='001') a,(select s#,score from SC where C#='002') b where a.score>b.score and a.s#=b.s#; 2、查询平均成绩大于60分的同学的学号和平均成绩; select S#,avg(score) from sc group by S# having avg(score) >60; 3、查询所有同学的学号、姓名、选课数、总成绩; select Student.S#,Student.Sname,count(SC.C#),sum(score) from Student left Outer join SC on Student.S#=SC.S# group by Student.S#,Sname 4、查询姓“李”的老师的个数; select count(distinct(Tname)) from Teacher where Tname like '李%'; 5、查询没学过“叶平”老师课的同学的学号、姓名; select Student.S#,Student.Sname from Student where S# not in (select distinct( SC.S#) from SC,Course,Teacher where SC.C#=Course.C# and Teacher.T#=Course.T# and Teacher.Tname='叶平'); 6、查询学过“001”并且也学过编号“002”课程的同学的学号、姓名; select Student.S#,Student.Sname from Student,SC where Student.S#=SC.S# and SC.C#='001'and exists( Select * from SC as SC_2 where SC_2.S#=SC.S# and SC_2.C#='002'); 7、查询学过“叶平”老师所教的所有课的同学的学号、姓名; select S#,Sname from Student where S# in (select S# from SC ,Course ,Teacher where SC.C#=Course.C# and Teacher.T#=Course.T# and Teacher.Tname='叶平' group by S# having count(SC.C#)=(select count(C#) from Course,Teacher where Teacher.T#=Course.T# and Tname='叶平')); 8、查询课程编号“002”的成绩比课程编号“001”课程低的所有同学的学号、姓名; Select S#,Sname from (select Student.S#,Student.Sname,score ,(select score from SC SC_2 where SC_2.S#=Student.S# and SC_2.C#='002') score2 from Student,SC where Student.S#=SC.S# and C#='001') S_2 where score2 60); 10、查询没有学全所有课的同学的学号、姓名; select Student.S#,Student.Sname from Student,SC where Student.S#=SC.S# group by Student.S#,Student.Sname having count(C#) <(select count(C#) from Course); 11、查询
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值