1 数据结构
1.1 数组(Array)
- 数组:Array,是有序的元素序列,数组是在内存中开辟一段连续的空间,并在此空间存放元素。就像是一排出租屋,有100个房间,从001到100每个房间都有固定编号,通过编号就可以快速找到租房子的人。
特点:
- 查找元素快:通过索引,可以快速访问指定位置的元素
- 增删元素慢
- 指定索引位置增加元素:需要创建一个新数组,将指定新元素存储在指定索引位置,再把原数组元素根据索引,复制到新数组对应索引的位置。如下图
- 指定索引位置删除元素: 需要创建一个新数组,把原数组元素根据索引,复制到新数组对应索引的位置,原数组中指定索引位置元素不复制到新数组中
1.2 链表(Linked List)
1.2.1 增加元素
1.2.2 删除元素 即为增加的逆操作
1.3.3 链表代码实现
class LinkedList {
Node head; // 表头
/* 表结点*/
class Node {
int data;
Node next;
Node(int d) { data = d; }
}
}
1.3 跳表(Skip List)
为了优化链表缺陷(lookup查找)时间复杂度为O(n),就有了跳表
实质就是空间换时间,例如添加一个尾指针同时向前查找
跳表的实现:
增加索引:每一集索引跳前一级索引的倍数:2-4-8-16
增加多级索引:
1.3.1 时间复杂度的分析
每一集索引跳前一级索引的倍数:2-4-8-16,对应结点个数(假设要查的元素在最后一位)为n/2-4-6-8
第k级索引的结点个数就是n/(2k)
假设索引的深度为h,最高级的索引只有两个结点(一步就找到)得到n/(2h) = 2
所以h = log2(n) - 1
时间复杂度为O(logn)
1.3.2 空间复杂度的分析
1.4 重点
- 是三者之间增加删除的时间复杂度
- 两种思想:
- 空间换时间
- 升维
2 算法题详解
2.1 Array
1)爬楼梯问题
/*
-
[70] 爬楼梯
-
思路:列出规律
-
1:1
-
2:2
-
3:3
-
4:5
-
5:8
-
可以看出是一个斐波拉契数列:F(n) = F(n-1) + F(n-2)
-
实现:
例如数字8是由 前两项相加得到的 3+5,而3和5也分别由他们的前两项相加得到
实现方法
定义三个变量,通过循环实现F(3) = F(2) + F(1)改变三个变量的值
三个为一个循环
f3 = f1 + f2
f1 = f2
f2 = f3
public int climbStairs(int n) {
int f1 = 1;
int f2 = 2;
int f3 = 3;
if (n < 3) return n;
for (int i = 3; i < n + 1; i++) { // ,前两次为1,2,从第三阶开始,得到3才能构成斐波拉契数列
f3 = f1 + f2; // 先实现第三层
f1 = f2; // 替换之前的f1,f2相当于都往后移动一格
f2 = f3;
}
return f3;
}
- 使用数组,数组lookup的时间复杂度为0(1),
设置长度为n(以数组下标为准,n-1即对应n阶层)的可变数组,方法和上面相同
存入数组
// @lc code=start
class Solution {
public int climbStairs(int n) {
if (n < 3) return n;
int result = 0;
int[] array = new int[n];
array[0] = 1;
array[1] = 2;
array[2] = 3;
for (int i = 2; i < n; i++) {
array[i] = array[i-1] + array[i-2];
result = array[i];
}
return result;
}
}
2)加一
- [66] 加一
- 需要考虑两种情况:
- 1.末位为9
- 2.末位为非9
- 末位为非9数字很简单,+1即可
- 末位为9,需要考虑进位 以及 之前元素是否为9,
- 解题方法:递归
import sun.security.util.Length;
// @lc code=start
class Solution {
int count = 0; // 记录递归的次数
public int[] plusOne(int[] digits) {
int len = digits.length - count++; // 当前列表长度
if (digits[len-1] != 9) digits[len-1] += 1;
else {
while (len-1 > 0) {
digits[len-1] = 0;
return plusOne(digits);
}
// 如果递归到数组中第一个元素仍为9,那么就只有一种情况,需要开辟新的数组例如[1,0,0]
digits = new int[digits.length + 1];
digits[0] = 1;
return digits;
}
return digits;
}
}
// @lc code=end