说一说虚拟地址空间有哪些部分 ?
虚拟地址空间分步图如下:
主要分为两个部分:内核空间和用户空间
内核空间
存放内核的代码和数据,所有进程的内核代码段都映射到同样的物理内存,并在内存中持续存在,是操作系统的一部分。内核空间为内核保留,不允许应用程序读写该区域的内容或直接调用内核代码定义的函数。
用户空间
用户空间给各个进程使用,也称为使用者空间。用户空间中的代码运行在较低的特权级别上,只能看到允许它们使用的部分系统资源,并且不能使用某些特定的系统功能,也不能直接访问内核空间和硬件设备,以及其他一些具体的使用限制。用户空间又大致细分为下列一些空间:
- 栈空间
- 共享区
- 堆空间
- BSS段(未初始化的数据段)
- DATA段(已初始化的数据段)
- TEXT段(代码段)
- 保留区
TCP协议的特点有哪些?
- TCP是面向连接的传输层协议(物理层-数据链路层-网络层-传输层-会话层-应用层)
- 每个TCP连接必须是一对一
- TCP提供可靠的服务。通过TCP连接传输的数据,不丢失,不重复,无差错,并且按需到达。
- TCP提供全双工的通信。TCP运行通信双方的应用程序在任何时候都能发送数据。
- 面向字节流。含义:虽然应用程序和TCP的交互一次一个数据块,但是TCP把应用程序交下来的数据仅仅看成是一连串的无结构字节流。(这条可以省略解释)
说说进程有多少种状态,如何转换?
三种状态,存在四种转换。
阻塞,就绪,运行。
阻塞>>就绪
就绪>>阻塞
就绪>>运行
运行>>阻塞
说说你对SpringIOC的理解
IoC是控制反转的意思,是一种面向对象编程的设计思想。在不采用这种思想的情况下,我们需要自己维护对象与对象之间的依赖关系,很容易造成对象之间的耦合度过高。尤其是在一个大型的项目中,对象与对象之间的关系是十分复杂的,这十分不利于代码的维护。IoC则可以解决这种问题,它可以帮我们维护对象与对象之间的依赖关系,并且降低对象之间的耦合度。
说到IoC就不得不说DI,DI是依赖注入的意思,它是IoC实现的实现方式。由于IoC这个词汇比较抽象而DI比较直观,所以很多时候我们就用DI来代替它,在很多时候我们简单地将IoC和DI划等号,这是一种习惯。实现依赖注入的关键是IoC容器,它的本质就是一个工厂。
编程题:数组中出现次数超过一半的数字
给一个长度为 n 的数组,数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。
例如输入一个长度为9的数组[1,2,3,2,2,2,5,4,2]。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。
package Temp;
/*
* @Author: jun
* @Date:2023/2/19 12:09
* @概述:
*/
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
/**
* 数组中出现次数超过一半的数字
* 总共有三种解题思路:
* 思路一:使用哈希map,利用键值对,比较出现的次数是否大于数组长度一半的值
* 思路二:对数组内的数组进行排序,出现次数最多的数字一定在中间位置,然后再检测该数字是否满足出现次数超过一半的要求
*/
public class niuke008 {
public static int solution01(int[] arr) {
//利用map的key value 模型来存放arr[i]和对应出现的次数
HashMap<Integer,Integer> map = new HashMap<>();
for (int i = 0; i < arr.length; i++) {
if (map.containsKey(arr[i])){//这里key用来存放对应的数组元素,value存放对应的出现次数
map.put(arr[i],map.get(arr[i])+1);//已经存在就给value加一
}
else{
map.put(arr[i],1);
}
}
for (Map.Entry<Integer,Integer> entry:map.entrySet()){
if (entry.getValue()>arr.length/2){
return entry.getKey();
}
}
return 0;
}
public static int solution02(int[] arr){
//先对数组排序,如果这个数存在,那它一定在arr[mid]的位置
Arrays.sort(arr);
int count = 0;
int mid = arr.length/2;
//统计整个数组看中间值的次数出现了多少次
for (int i = 0; i < arr.length; i++) {
if (arr[mid] == arr[i]){
count++;
}
}
if (count>mid){//出现次数大于数组长度的一半
return arr[mid];
}
return 0;
}
public static void main(String[] args) {
int[] arr = {1,2,3,2,2,2,5,4,2};
//解法一
int result = solution01(arr);
System.out.println(result);
//解法二
int result2 = solution02(arr);
System.out.println(result2);
}
}
编程题:在旋转过的有序数组中寻找目标值
有一个长度为 n 的按严格升序排列的整数数组 nums ,在实行 search 函数之前,在某个下标 k 上进行旋转,使数组变为[nums[k],nums[k+1],…,nums[nums.length-1],nums[0],nums[1],…,nums[k-1]]。
给定旋转后的数组 nums 和一个整型 target ,请你查找 target 是否存在于 nums 数组中并返回其下标(从0开始计数),如果不存在请返回-1。
package Temp;
/*
* @Author: jun
* @Date:2023/2/19 14:09
* @概述:
*/
import java.util.HashMap;
/**
* 在旋转过的有序数组中寻找目标值
*
* 解法:先把数组推进HashMap中
* 然后使用二分查找找到目标值
*/
public class niuke009 {
public int search(int[] nums,int target){
HashMap<Integer,Integer> integerHashMap = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
//遍历数组将元素推进map
integerHashMap.put(nums[i],i);
}
int left = 0;
int right = nums.length-1;
int mid = left+ (right-left)/2;
while (left <= right){
if (nums[mid] == target){
return mid;
}
if (nums[mid] >target){
right = mid-1;
}
if (nums[mid] < target){
left = mid+1;
}
}
return -1;
}
public static void main(String[] args) {
int[] arr = {6,8,10,0,2,4};
int target = 10;
niuke009 niuke009 = new niuke009();
int result = niuke009.search(arr, target);
System.out.println(result);
}
}