第三课
第一节 数组、链表和跳表的基本实现和特性
ArrayList 的添加和删除 源代码。
LinkedList
两个list相关时间和空间复杂度
question 100w 个数据 使用哪个比较快。
SkipList
跳表中心思想。
升维。空间换时间。
跳表:增加索引,增加多级索引。
思想:空间换时间。 后面的树,二叉搜索树!都是基于这个思想。
O(logN)的时间复杂度。
空间复杂度:O(n)
n,n/2, n/4, n/8 ...
第二节 实战
练习步骤:
- 思考5-10mins!!!思考可能的题解,比较时间和空间复杂度。
- 有思路:自己开始做和写代码。否则看题解。
- 自己能默写、背诵。
练习题
1. 两数之和
class Solution {
public int[] twoSum(int[] nums, int target) {
HashMap<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
if (map.containsKey(nums[i])) {
return new int[]{map.get(nums[i]), i};
} else {
map.put(target - nums[i], i);
}
}
return null;
}
}
15. 三数之和
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> res = new ArrayList<>();
if (nums == null || nums.length == 0) return res;
Arrays.sort(nums);
for (int i = 0; i < nums.length - 2; i++) {
int low = i + 1, high = nums.length - 1;
if (nums[i] > 0) break;
if (i > 0 && nums[i] == nums[i - 1]) continue;
int target = 0 - nums[i];
while (low < high) {
if (target == nums[low] + nums[high]) {
List<Integer> list = new ArrayList<>();
list.add(nums[i]);
list.add(nums[low]);
list.add(nums[high]);
res.add(list);
while (low < high && nums[low] == nums[low + 1]) {low++;}
while (low < high && nums[high] == nums[high - 1]) {high--;}
low++;
high--;
} else if (target < nums[low] + nums[high]) {
high--;
} else {
low++;
}
}
}
return res;
}
}
189. 轮转数组
给你一个数组,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。
示例 1:
输入: nums = [1,2,3,4,5,6,7], k = 3 输出: [5,6,7,1,2,3,4] 解释: 向右轮转 1 步: [7,1,2,3,4,5,6] 向右轮转 2 步: [6,7,1,2,3,4,5] 向右轮转 3 步: [5,6,7,1,2,3,4]
// 我的简单思路
/*
1. 开辟新数组,把array[i + k % nums.length] = nums[i]
*/
class Solution {
public void rotate(int[] nums, int k) {
int[] array = new int[nums.length];
for (int i = 0; i < nums.length; i++) {
array[(i + k) % nums.length] = nums[i];
}
for (int i = 0; i < nums.length; i++) {
nums[i] = array[i];
}
}
}
// 老外
class Solution {
public void rotate(int[] nums, int k) {
k %= nums.length;
reverse(nums, 0, nums.length - 1);
reverse(nums, 0, k - 1);
reverse(nums, k, nums.length - 1);
}
// 闭区间
public void reverse(int[] nums, int left, int right) {
while (left < right) {
int temp = nums[left];
nums[left] = nums[right];
nums[right] = temp;
left++;
right--;
}
}
}
解释:
nums = "----->-->"; k =3
result = "-->----->";
reverse "----->-->" we can get "<--<-----"
reverse "<--" we can get "--><-----"
reverse "<-----" we can get "-->----->"
this visualization help me figure it out :)
21. 合并两个有序链表
24. 两两交换链表中的节点
public ListNode swapPairs(ListNode head) {
ListNode dummy = new ListNode(-1, head);
ListNode pre = dummy;
ListNode cur = head;
while (cur != null && cur.next != null) {
ListNode nextNode = cur.next;
cur.next = nextNode.next;
nextNode.next = cur;
pre.next = nextNode;
pre = cur;
cur = cur.next;
}
return dummy.next;
}
\