线性结构
数组和队列是线性结构的两种物理实现方式,而栈和队列是在数组和队列的基础上实现的有特殊功能的线性结构(栈先进后出,类似弹夹;队列先进先出,类似排队等号)
数组
稀疏数组的应用
场景:五子棋
- 有9X9棋盘,8个有效数据
- 第一遍遍历,得到有效数据的个数 8
- 创建8+1 行,3列 的数组,第一行数组的数据为 :
arr[0][0]=9 , arr[0][1]=9,arr[0][2]=8- 遍历第二遍,稀疏数组除了第一行外,第一列表示有效数据所在行标,第二列表示有效数据的列标,第三列表示数据本身。
数组实现的循环队列
循环队列需要注意的点:在判断是否已满,以及有多少有效个数时,一定要对size取模。
链表
单链表
常见的面试题:
面试中的java链表1
面试中的java链表2
问题1:如何判断单链表是否有环?
解答:两个指针p1、p2,p1每次走1步,p2每次走2步,如果相遇则表明有环。
问题2:如何知道入环点在哪里。
解答:p1、p2相遇后,p3从头开始,每次走一步,当p1,和p3再次相遇时,则是入环点
问题3:求环的长度
解答:p1、p2相遇后,开始计次,当再次相遇时,p1所走的长度就是环的长度。
场景:Josephus 问题
故事:据说著名犹太历史学家 Josephus有过以下的故事:在罗马人占领乔塔帕特後,39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被人抓到,于是决定了一个自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀,然后再由下一个重新报数,直到所有人都自杀身亡为止。
Josephu 问题为:设编号为 1,2,… n 的 n 个人围坐一圈,约定编号为 k(1<=k<=n)的人从 1 开始报数,数到m 的那个人出列,它的下一位又从 1 开始报数,数到 m 的那个人又出列,依次类推,直到所有人出列为止,由此产生一个出队编号的序列。
public void countBoy(int startNum, int countNum) {
if (first == null || startNum < 1 || startNum > size) {
System.out.println("参数输入有误,请重新输入");
return;
}
// 创建一个辅助指针,这个辅助指针总是指向first
Person helper = first;
while (helper.getNext() != first) {
helper = helper.getNext();
}
// 移动到startNum
for (int i = 0; i < startNum-1; i++) {
first = first.getNext();
helper = helper.getNext();
}
// 出列
while (first.getNext() != first) {
for (int i = 0; i < countNum-1; i++) {
first = first.getNext();
helper = helper.getNext();
}
System.out.println(first);
first = first.getNext();
helper.setNext(first);
}
System.out.println(first);
}
双链表
栈
场景:数学表达式计算(中缀表达式的实现)
场景:后续表达式的实现
递归
递归的用途:
- 解决数学问题
- 解决算法问题:
- 对栈所解决的问题,进行优化,简洁代码。
场景:可以参考google编程大赛的题目
1. 八皇后问题
2. 迷宫问题
3. 汉诺塔问题
4. 球和篮子问题
5. 阶乘
排序算法
都有哪些排序种类 :
选鸡插硅胶
- 选择排序 : 简单选择排序、堆排序 (简单选、选一堆)
- 基数排序
- 插入排序 : 直接插入排序、希尔排序(直接插、插希尔)
- 归并排序
- 交换排序 : 冒泡排序、快速排序(快速冒泡)
时间复杂度
概念:用于比较算法快慢的描述。
计算时间复杂度的方法:
- 只保留最高阶项
- 去除最高阶项系数
- 只有常数项时,常数设为1
常见的时间复杂度:
- 常数阶 O(1)
- 对数阶 O(log2n)
- 线性阶 O(n)
- 线性对数阶 O(nlog2n)
- 平方阶 O(n^2)
- 立方阶 O(n^3)
- k 次方阶 O(n^k)
- 指数阶 O(2^n)