数据结构面试题整理

一 数据结构

1.你熟悉什么数据结构?
数组 链表
栈 队列 哈希
二叉树 二叉查找树 二叉堆
b树 b+树

2.b树 b+树 b*树
b和b+都是节点可以有很多子节点,区别是b树所有的节点都可以存储关键字,而b+树只有叶子节点存储关键字,适用于数据库索引。

3.树的中序遍历

在这里插入图片描述

4.二叉平衡树,怎么用一维数组存储
在这里插入图片描述
使用数组存储时,会按照层级顺序把二叉树的节点放到数组中对应的位置上。如果某一个节点的左孩子或者右孩子空缺,则数据的相应位置也空出来。

设计思路:

假设一个父节点的下标是p
左孩子下标=2p +1
右孩子下标=2
p+2

反过来,左孩子的下标是l,它父节点下标为:(l - 1)/2

二 算法

1.快排?快排的实现过程?复杂度如何?简单代码实现?
方式:
双边循环法(代码实现复杂)
单边循环法(推荐)

复杂度:
nlogn

单边循环法实现过程
1-先找到一个基准元素,起始下标
2-遍历,如果元素比基准元素小,下标+1
此元素与下标对应元素交换位置
3-当遍历完后,基准元素与当前下标元素交换位置,此时基准元素就分成了两组数据
4-两边的数据在递归调用,分而治之,直到起始下标和终止下标结束,则不能在拆分
5-遍历数组元素即可

单边循环法代码实现:

public static void quickSort(int[] arr, int startIndex, int endIndex) 
{ 
// 递归结束条件:startIndex大于或等于endIndex时 
 if (startIndex >= endIndex) { 
 return;
 } 
 // 得到基准元素位置 
 int pivotIndex = partition(arr, startIndex, endIndex); 
 // 根据基准元素,分成两部分进行递归排序
 quickSort(arr, startIndex, pivotIndex - 1); 
 quickSort(arr, pivotIndex + 1, endIndex); 
} 
 /** 
 * 分治(单边循环法) 
 * @param arr 待交换的数组 
 * @param startIndex 起始下标
 * @param endIndex 结束下标 
 */ 
private static int partition(int[] arr, int startIndex, int endIndex) { 
 // 取第1个位置(也可以选择随机位置)的元素作为基准元素
 int pivot = arr[startIndex]; 
 int mark = startIndex; 

 for(int i=startIndex+1; i<=endIndex; i++){ 
 if(arr[i]<pivot){ 
    mark ++;
    int p = arr[mark]; 
    arr[mark] = arr[i];
    arr[i] = p; 
 }
}

      arr[startIndex] = arr[mark]; 
      arr[mark] = pivot; 
      return mark; 
 } 

 public static void main(String[] args) { 
    int[] arr = new int[] {4,4,6,5,3,2,8,1}; 
    quickSort(arr, 0, arr.length-1); 
    System.out.println(Arrays.toString(arr)); 
 }

说明:
递归代码的书写特点,先找到一个循环的代码,在找出跳出循环的条件,递归的调用循环代码。

2.二分查找原理,简单的一个代码
算法思想:
设置开始位置start,结束位置end,以及中间位置 mid=(end+start)/2,
如果arr[index]=mid,返回mid
如果arr[index]>mid,从后半段查找,将start设置为mid+1
如果arr[index]<mid,从后半段查找,将end设置为mid-1
如果start>end,返回-1,说明所查元素不存在

代码:

public class Select1_SuanFa2 {

	public static void main(String[] args) {		
	     System.out.println(select(44));	
	}	
	
	public static int select(int target) {		
	//定义数组		
	int[] arr = {21,32,36,44,45,36,47,38,29};		
	//定义初始位置		
	int start = 0;		
	//定义结束位置		
	int end = arr.length-1;		
	//定义中间位置		
	int mid = (start+end)/2;	
		
	while(true) {			
	//如果没有这个元素,则start>=end,返回-1			
	if(start>end) {		 	
	return -1;			
	}			
	//判断是否和中间位置元素值相等			
	if(arr[mid] == target) {				
	//将中间位置的索引赋值给目标位置				
	return mid;			
	}else {				
	if(arr[mid] > target) {					
	//将end位置设置为中间位置减一					
	end = mid-1;				
	}else {					
	//将start位置设置为中间位置加1					
	start = mid+1;				
	}				
	//取出新的中间位置(别忘记了)				
	mid = (start+end)/2;			
	}		
	}					
	}    
	}

3.怎么判断链表是否有环?
在这里插入图片描述

思路:
两个指针分别按照固定步长行走,P1一次走1布,P2一次走2布,如果链表有环,P1和P2会有相遇的时刻。(追击问题解法)

代码:

/** 
 * 判断是否有环 
 * @param head 链表头节点 
*/ 
 public static boolean isCycle(Node head) { 
Node p1 = head; 
 Node p2 = head; 
while (p2!=null && p2.next!=null){ ;
 p1 = p1.next; 
 p2 = p2.next.next; 
 if(p1 == p2){ 
 return true; 
} 
return false; 
 } 

/** 
 * 链表节点 
 */ 
private static class Node { 
int data; 
Node next;
Node(int data) { 
 this.data = data; 
} 
} 

 public static void main(String[] args) throws Exception { 
Node node1 = new Node(5); 
 Node node2 = new Node(3); 
 Node node3 = new Node(7); 
 Node node4 = new Node(2); 
 Node node5 = new Node(6); 
 node1.next = node2; 
 node2.next = node3; 
 node3.next = node4; 
 node4.next = node5; 
 node5.next = node2; 

System.out.println(isCycle(node1)); 
 } 

4.链表的定义,怎么实现链表翻转?
链表翻转代码参考: https://blog.csdn.net/xu491361421xiao/article/details/81385435

5.怎么求数组的最大子序列和

6.栈中最小值
在这里插入图片描述
在这里插入图片描述
代码如下:

private Stack<Integer> mainStack = new Stack<Integer>(); 
private Stack<Integer> minStack = new Stack<Integer>(); 

/** 
 * 入栈操作 
 * @param element 入栈的元素 
 */ 
public void push(int element) { 
 mainStack.push(element); 
 //如果辅助栈为空,或者新元素小于或等于辅助栈栈顶,则将新元素压入辅助栈 
 if (minStack.empty() || element <= minStack.peek()) { 
 minStack.push(element); 
 } 
 } 

 /** 
 * 出栈操作 
 */ 
 public Integer pop() { 
 //如果出栈元素和辅助栈栈顶元素值相等,辅助栈出栈 
if (mainStack.peek().equals(minStack.peek())) { 
minStack.pop(); 
}
 return mainStack.pop(); 
 } 

/** 
 * 获取栈的最小元素 
 */ 
 public int getMin() throws Exception { 
 if (mainStack.empty()) { 
 throw new Exception("stack is empty"); 
 } 

 return minStack.peek(); 
 } 

 public static void main(String[] args) throws Exception { 
 MinStack stack = new MinStack(); 
 stack.push(4); 
 stack.push(9); 
 stack.push(7); 
 stack.push(3); 
 stack.push(8); 
 stack.push(5); 
 System.out.println(stack.getMin()); 
stack.pop(); 
 stack.pop(); 
stack.pop(); 
System.out.println(stack.getMin()); 
 }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值