03 数组、链表、跳表
|Word count:1.7k|Reading time:7min|Post View:
1.基本实现和特性
1.1 数组
内存中,一段连续的地址,可以通过内存管理器直接访问,时间复杂度为$O(1)$,访问时间比较快;
增加删除元素比较麻烦,时间复杂度为 $O(n)$
1.2 链表

- 增加删除结点时间复杂度:$O(1)$
- 访问结点时间复杂度:$O(n)$
1.3 跳表 SkipList
主要在Redis中使用
链表的缺陷:访问时间复杂度比较高 $O(n)$
给链表进行加速中心思想:升维(空间换时间)
跳表:索引,增加索引,链表next速度为1,一级索引速度为2,二级索引速度为4,

实际使用中,可以增加多级索引,实际增加 $log~2n$级索引

跳表查询的时间复杂度 $O(logn)$
n/2, n/4, n/8, 第k级索引结点的个数就是 $n/(2^k)$
假设索引有h级,最高级的索引有2个结点。$n(2^h)=2$,从而求得$h=log2(n)-1$

现实中跳表的形态
- 维护成本比较高,
- 增加和删除的时间复杂度 $O(logn)$

跳表空间复杂度$O(n)$
2.例题
2.1零移动
https://leetcode.cn/problems/move-zeroes/description/
1 2 3
| 给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。
请注意 ,必须在不复制数组的情况下原地对数组进行操作。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| class Solution { public: void moveZeroes(vector<int>& nums) { int j = 0; for (int i = 0; i < nums.size(); i++) { if (nums[i] != 0) { nums[j] = nums[i]; if (i != j) { nums[i] = 0; } j++; } } }
void moveZeroes_swap(vector<int>& nums) { int j = 0; for (int i = 0; i < nums.size(); i++) { if (nums[i] != 0) { int tmp = nums[j]; nums[j] = nums[i]; nums[i] = tmp; j++; } } } };
|
2.2 盛水最多的容器
11. 盛最多水的容器 - 力扣(LeetCode)
1 2 3 4 5 6 7
| 给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。
找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
返回容器可以储存的最大水量。
说明:你不能倾斜容器。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| class Solution { public: int maxArea1(vector<int>& height) { int max_water = 0; for (int i = 0; i < height.size() - 1; i++) { for (int j = i + 1; j < height.size(); j++) { int tmp = std::min(height[i], height[j]) * (j - i); max_water = std::max(max_water, tmp); } }
return max_water; }
int maxArea2(vector<int>& height) { int left = 0; int right = height.size() - 1; int max_water = 0;
while(left < right) { int tmp = std::min(height[left], height[right]) * (right - left); max_water = tmp > max_water ? tmp : max_water;
if (height[left] < height[right]) { left++; } else { right--; } }
return max_water; } int maxArea(vector<int>& height) { int max_water = 0; for (int i = 0, j = height.size() - 1; i < j; ) { int min_height = height[i] < height[j] ? height[i ++] : height[j --]; max_water = std::max(max_water, (j - i + 1) * min_height); }
return max_water; }
};
|
2.3 爬楼梯
70. 爬楼梯 - 力扣(LeetCode)
1 2 3
| 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
|
class Solution { public: int climbStairs(int n) { if (n <= 2) { return n; }
int f1 = 1; int f2 = 2; int f3 = 3;
for (int i = 3; i <= n; i++) { f3 = f1 + f2; f1 = f2; f2 = f3; }
return f3; } };
|
2.4 三数之和
15. 三数之和 - 力扣(LeetCode)
1 2 3 4 5
| 给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请
你返回所有和为 0 且不重复的三元组。
注意:答案中不可以包含重复的三元组。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
|
class Solution { public: vector<vector<int>> threeSum1(vector<int>& nums) { std::vector<std::vector<int>> ans; for (int i = 0; i < nums.size() - 2; i++) { for (int j = i + 1; j < nums.size() - 1; j++) { for (int k = j + 1; k < nums.size(); k++) { if (nums[i] + nums[j] + nums[k] == 0) { ans.push_back({nums[i], nums[j], nums[k]}); } } } }
return ans; }
vector<vector<int>> threeSum(vector<int>& nums) { int size = nums.size(); if (size < 3) return {}; std::vector<std::vector<int>> res; std::sort(nums.begin(), nums.end()); for(int i = 0; i < size; i++) { if (nums[i] > 0) return res; if (i > 0 && nums[i] == nums[i-1]) continue; int left = i + 1; int right = size - 1; while(left < right) { if (nums[left] + nums[right] > -nums[i]) right--; else if(nums[left] + nums[right] < -nums[i]) left++; else { res.push_back(std::vector<int>{nums[i], nums[left], nums[right]}); left++; right--;
while (left < right && nums[left] == nums[left-1]) left++; while (left < right && nums[right] == nums[right+1]) right--; } } }
return res; } };
|