Java面试题 每日一练(4.7)

1.关于Java的一些概念,下面哪些描述是正确的:( )

所有的Java异常和错误的基类都是java.lang.Exception, 包括java.lang.RuntimeException
通过try … catch … finally语句,finally中的语句部分无论发生什么异常都会得到执行
java中所有的数据都是对象
Java通过垃圾回收回收不再引用的变量,垃圾回收时对象的finallize方法一定会得到执行
Java是跨平台的语言,无论通过哪个版本的Java编写的程序都能在所有的Java运行平台中运行
Java通过synchronized进行访问的同步,synchronized作用非静态成员方法和静态成员方法上同步的目标是不同的

解析:

A、java异常和错误的基类Throwable,包括Exception和Error

B、try…catch…finally finally不管什么异常都会执行

C、java是面向对象的,但是不是所有的都是对象,基本数据类型就不是对象,所以才会有封装类的;

D、如果是等待清理队列中如果又被调用,则不会执行finallize方法

E、JAVA跨平台性 实现在任意平台的java程序都可以在其他平台运行

F、synchronized实现方式:三种

正确答案 BF

2.在Java中,关于HashMap类的描述,以下正确的是 ()

HashMap使用键/值得形式保存数据
HashMap 能够保证其中元素的顺序
HashMap允许将null用作键
HashMap允许将null用作值

解析:HashMap允许一个key为null,多个value为null,而Hashtable不允许有null值

​ HashMap 不按插入顺序排序,按照哈希值排序,所以无序。

正确答案 ACD

3.下面有关servlet service描述错误的是?

不管是post还是get方法提交过来的连接,都会在service中处理
doGet/doPost 则是在 javax.servlet.GenericServlet 中实现的
service()是在javax.servlet.Servlet接口中定义的
service判断请求类型,决定是调用doGet还是doPost方法

解析:doGet/doPost 则是在 javax.servlet.http.HttpServlet 中实现的

正确答案 B

4.下列关于JAVA多线程的叙述正确的是()

调用start()方法和run()都可以启动一个线程
CyclicBarrier和CountDownLatch都可以让一组线程等待其他线程
Callable类的call()方法可以返回值和抛出异常
新建的线程调用start()方法就能立即进行运行状态

解析:

A. start()方法来启动线程,真正实现了多线程运行,调用了run()方法;run()方法当作普通方法的方式调用。

B. CyclicBarrier让一组线程等待其他线程;CountDownLatch让一组线程等待某个事件发生。

C. Callable能够抛出checked exception。

D. start()方法让thread进去可运行状态(runnable),等待获取CPU的使用权。

正确答案:BC

5.下列容器中,哪些容器按 key 查找的复杂度为 O(log(n)) ()

std::unordered_set
std::multimap
std::map
std::deque

解析:STL库中,map和multimap底层都是红黑树实现的,两者的不同在于multimap允许重复的可以,而map中不行。红黑树的查找复杂度为O(log(n)),unodered_map/_set底层是哈希表实现的,查找复杂度为O(1)

正确答案:BC

6.下面程序段的时间复杂度是()

i = k = ``0``;`
 `while``( k < n ){``  
    ``i ++ ;
    ``k += i ;
   ``}
O(n)
O(n^1/2)
O(n*i)
O(n+i)

解析:

写写数字, 观察规律

i= 1, 2, 3, 4, 5, 6, 7, 8

k=1, 3, 6, 10, 15, 21, 28, 36

把k的数字两个两个一起看的话, 也就是(1,3), (6,10), (15, 21), (7,8), 求和后可以发现规律(1+3=4), (6+10=16), (15+21=36), (28+36=64)

也就是2^2, 4^2, 6^2, 8^2…偶数的平方

循环在x^2>=n时终止, 可得x等于根号n,也就是n^(1/2)

循环的次数是x/2, 时间复杂度为O((1/2)n^(1/2)), 一般而言时间复杂度认为常系数为1, 所以答案就是O(n^(1/2))

正确答案:B

7.以下代码结果是什么?

public class foo {

public static void main(String sgf[]) {

StringBuffer a=new StringBuffer(“A”);

StringBuffer b=new StringBuffer(“B”);

operate(a,b);

System.out.println(a+.+b);

}

static void operate(StringBuffer x,StringBuffer y) {

x.append(y);

y=x;

}

}
代码可以编译运行,输出“AB.AB”。
代码可以编译运行,输出“A.A”。
代码可以编译运行,输出“AB.B”。
代码可以编译运行,输出“A.B”。

解析:

引用a指向对象A

引用b指向对象B

引用x指向对象A

引用y指向对象B

在operate方法中,引用x指向的对象A被连接了B,对象A也就被改变为AB

然后又把引用y指向了x所指向的对象地址,也就是此时引用a,x,y指向同一个对象AB

而引用b没有发生任何变化,依旧指向对象B。

正确答案 C

8.实现或继承了Collection接口的是()

Map
List
Vector
Iterator
Set

解析:

在java.util包中提供了一些集合类,常用的有List、Set和Map类,其中List类和Set类继承了Collection接口。这些集合类又称为容器,长度是可变的,数组用来存放基本数据类型的数据,集合用来存放类对象的引用。

List接口、Set接口、Map接口以及Collection接口的主要特征如下:

  1. Collection接口是List接口和Set接口的父接口,通常情况下不被直接使用。
  2. List接口继承了Collection接口,List接口允许存放重复的对象,排序方式为按照对象的插入顺序。
  3. Set接口继承了Collection接口,Set接口不允许存放重复的对象,排序方式为按照自身内部的排序规则。
  4. Map接口以键值对(key—value)的形式存放对象,其中键(key)对象不可以重复,值(value)对象可以重复,排序方式为按照自身内部的规则。

C:Vector实现了List接口,即间接实现Collection接口
D:Iterator是Java迭代器最简单的实现,没有实现Collection接口

正确答案:BCE

9.ArrayList list = new ArrayList(20);中的list扩充几次

0
1
2
3

解析:Arraylist默认数组大小是10,扩容后的大小是扩容前的1.5倍,最大值小于Integer 的最大值减8,如果新创建的集合有带初始值,默认就是传入的大小,也就不会扩容

正确答案:A

10.代码片段:

byte` `b1=``1``,b2=``2``,b3,b6; 
final` `byte` `b4=``4``,b5=``6``; 
b6=b4+b5; 
b3=(b1+b2); 
System.out.println(b3+b6);

关于上面代码片段叙述正确的是()

输出结果:13
语句:b6=b4+b5编译出错
语句:b3=b1+b2编译出错
运行期抛出异常

解析:

被final修饰的变量是常量,这里的b6=b4+b5可以看成是b6=10;在编译时就已经变为b6=10了

而b1和b2是byte类型,java中进行计算时候将他们提升为int类型,再进行计算,b1+b2计算后已经是int类型,赋值给b3,b3是byte类型,类型不匹配,编译不会通过,需要进行强制转换。

Java中的byte,short,char进行计算时都会提升为int类型。

正确答案: C

11.以下关于final关键字说法错误的是()

final是java中的修饰符,可以修饰类、接口、抽象类、方法和属性
final修饰的类肯定不能被继承
final修饰的方法不能被重载
final修饰的变量不允许被再次赋值

解析:

final修饰类、方法、属性!不能修饰抽象类,因为抽象类一般都是需要被继承的,final修饰后就不能继承了。

final修饰的方法不能被重写而不是重载!

final修饰属性,此属性就是一个常量,不能被再次赋值!

正确答案:AC

12.DBMS 中实现事务持久性的子系统是()

安全性管理子系统
完整性管理子系统
并发控制子系统
恢复管理子系统

解析:

原子性:事务是一组不可分割的操作单元,这组单元要么同时成功要么同时失败(由DBMS的事务管理子系统来实现);
一致性:事务前后的数据完整性要保持一致(由DBMS的完整性子系统执行测试任务);
隔离性:多个用户的事务之间不要相互影响,要相互隔离(由DBMS的并发控制子系统实现);
持久性:一个事务一旦提交,那么它对数据库产生的影响就是永久的不可逆的,如果后面再回滚或者出异常,都不会影响已提交的事务(由DBMS的恢复管理子系统实现的)

正确答案:D

13.关于中间件特点的描述.不正确的是()

中间件运行于客户机/服务器的操作系统内核中,提高内核运行效率
中间件应支持标准的协议和接口
中间件可运行于多种硬件和操作系统平台上
跨越网络,硬件,操作系统平台的应用或服务可通过中间件透明交互

解析:中间件是一种独立的系统软件或服务程序,分布式应用软件借助这种软件在不同的技术之间共享资源。中间件位于客户机/ 服务器的操作系统之上,管理计算机资源和网络通讯。是连接两个独立应用程序或独立系统的软件。相连接的系统,即使它们具有不同的接口,但通过中间件相互之间仍能交换信息。执行中间件的一个关键途径是信息传递。通过中间件,应用程序可以工作于多平台或OS环境。

(简单来说,中间件并不能提高内核的效率,一般只是负责网络信息的分发处理)

正确答案 A

14.对文件名为Test.java的java代码描述正确的是()

class` `Person {
  ``String name = ``"No name"``;
  ``public` `Person(String nm) {
    ``name = nm;
  ``}
}
class` `Employee extends Person {
  ``String empID = ``"0000"``;
  ``public` `Employee(String id) {
    ``empID = id;
  ``}
}
public` `class` `Test {
  ``public` `static` `void` `main(String args[]) {
    ``Employee e = ``new` `Employee(``"123"``);
    ``System.out.println(e.empID);
  ``}
}
输出:0000
输出:123
编译报错
输出:No name

解析:

如果子类构造器没有显示地调用超类的构造器,则将自动地调用超类默认(没有参数)的构造器。如果超类没有不带参数的构造器,并且在子类的构造器中有没有显示地调用超类的其他构造器,则Java编译器将报告错误。使用super调用构造器的语句必须是子类构造器的第一条语句。——p153《Java核心技术卷I》

正确答案 C

15.给你 n 个非负整数 a1,a2,…,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0)。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。

说明:你不能倾斜容器,且 n 的值至少为 2。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-n49reANb-1586267078982)(C:\Users\57237\Desktop\question_11.jpg)]

图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。

示例:

输入:[1,8,6,2,5,4,8,3,7]
输出:49

思路一:暴力法,遍历所有可能,取最大值:

class Solution {

  public int maxArea(int[] height) {int max = 0;for(int i=0;i<height.length;i++){for(int j=0;j<height.length;j++){

​        max = Math.max((i-j)*Math.min(height[i],height[j]),max);}}return max;

  }

}

思路二:双指针法:两线段之间形成的区域总是会受到其中较短那条长度的限制。此外,两线段距离越远,得到的面积就越大。

我们在由线段长度构成的数组中使用两个指针,一个放在开始,一个置于末尾。 此外,我们会使用变量 maxareamaxarea 来持续存储到目前为止所获得的最大面积。 在每一步中,我们会找出指针所指向的两条线段形成的区域,更新 maxareamaxarea,并将指向较短线段的指针向较长线段那端移动一步。

代码:

public class Solution {
    public int maxArea(int[] height) {
        int maxarea = 0, l = 0, r = height.length - 1;
        while (l < r) {
            maxarea = Math.max(maxarea, Math.min(height[l], height[r]) * (r - l));
            if (height[l] < height[r])
                l++;
            else
                r--;
        }
        return maxarea;
    }
}

16.罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。

字符 数值
I 1
V 5
X 10
L 50
C 100
D 500
M 1000
例如, 罗马数字 2 写做 II ,即为两个并列的 1。12 写做 XII ,即为 X + II 。 27 写做 XXVII, 即为 XX + V + II 。

通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而是 IV。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX。这个特殊的规则只适用于以下六种情况:

I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。
X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。
C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。
给定一个整数,将其转为罗马数字。输入确保在 1 到 3999 的范围内。

示例 1:

输入: 3
输出: “III”
示例 2:

输入: 4
输出: “IV”
示例 3:

输入: 9
输出: “IX”
示例 4:

输入: 58
输出: “LVIII”
解释: L = 50, V = 5, III = 3.
示例 5:

输入: 1994
输出: “MCMXCIV”
解释: M = 1000, CM = 900, XC = 90, IV = 4.

思路:贪心算法

实现:

public class Solution {

    public String intToRoman(int num) {
        // 把阿拉伯数字与罗马数字可能出现的所有情况和对应关系,放在两个数组中
        // 并且按照阿拉伯数字的大小降序排列,这是贪心选择思想
        int[] nums = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1};
        String[] romans = {"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"};

        StringBuilder stringBuilder = new StringBuilder();
        int index = 0;
        while (index < 13) {
            while (num >= nums[index]) {
                stringBuilder.append(romans[index]);
                num -= nums[index];
            }
            index++;
        }
        return stringBuilder.toString();
    }
}

给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有满足条件且不重复的三元组。

注意:答案中不可以包含重复的三元组。

示例:

给定数组 nums = [-1, 0, 1, 2, -1, -4],

满足要求的三元组集合为:
[
[-1, 0, 1],
[-1, -1, 2]
]

思路:双指针+排序

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
 List<List<Integer>> ans = new ArrayList();
        int len = nums.length;
        if(nums == null || len < 3) return ans;
        Arrays.sort(nums); // 排序
        for (int i = 0; i < len ; i++) {
            if(nums[i] > 0) break; // 如果当前数字大于0,则三数之和一定大于0,所以结束循环
            if(i > 0 && nums[i] == nums[i-1]) continue; // 去重
            int L = i+1;
            int R = len-1;
            while(L < R){
                int sum = nums[i] + nums[L] + nums[R];
                if(sum == 0){
                    ans.add(Arrays.asList(nums[i],nums[L],nums[R]));
                    while (L<R && nums[L] == nums[L+1]) L++; // 去重
                    while (L<R && nums[R] == nums[R-1]) R--; // 去重
                    L++;
                    R--;
                }
                else if (sum < 0) L++;
                else if (sum > 0) R--;
            }
        }        
        return ans;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值