链表长度与翻转
谨以此纪念我在某尼划水的时光! /手动滑稽
继续熟悉链表吧, 接下来介绍使用频率最高的两个操作, 获取链表长度和翻转链表. 真的很简单, 但是使用频率非常高!
获取链表长度
首先, 很多人可能认为, 获取链表长度的复杂度是O(n), 代价很高. 其实不然, 我们用这个不等式作为复杂度的标尺: O(1) < O(logn) < O(n) < O(nlogn) < O(n^2) < O(n^3) < O(n^4). 一次使用O(n)对整个程序的影响并不大, 加上数组的使用就能够迅速解决很多链表的问题(但是特别注意空间成本).
1. O(1)的操作: 如哈希表的查找和数组;
2. O(logn)的操作: 例如红黑树的插入, 还有平衡二叉树的查找;
3. O(n)的操作: 经常就是单向链表的查找啦, 没有办法, 要省空间就要花点时间; 还有就是一些字符串匹配KMP什么的; 顺便放道题好了, 两数之和 (字节面试题).
4. O(nlogn)的操作: 各种排序算法, 如merge sort和quick sort, heap sort.
5. O(n^2)的操作: 例如, insertion sort, 还有再放一道题, 哈哈, 三数之和 (这道题建立在两数之和 基础上);
4. O(n^3)的操作: 例如, 你懂的, 那就是 四数之和. /手动狗头
5. O(n^4)的操作: 四数之和 处理不好就容易变成O(n^4), 千万小心, 能够降一个level是一个level;
言归正传, 现在讲获取长度的问题.
public int getSize(ListNode head) {
int i = 0;
ListNode tmp = head;
while(tmp!= null) {
i++;
tmp = tmp.next;
}
return i;
}
使用场景: 很多情况下都需要你先获取size, 然后进行下一步操作.见题目: 链表中的下一个最大元素
, 相交链表 (字节面试题).
翻转链表
reverse是使用频率非常高的操作, 解决链表的问题, 可以思考从reverse着手.
public ListNode reverse(ListNode head) {
ListNode prev = null;
ListNode tmp = head;
while (tmp != null) {
ListNode next = tmp.next;
tmp.next = prev;
prev = tmp;
tmp = next;
}
return prev;
}
比如, 回文链表 的题目就是利用reverse和fast-slow两种基本操作. 其他题目: 反转列表 , 反转列表 II , 重排链表 , 链表中的下一个更大节点 , 反转链表 II. 当然还有更加骚的操作, 就是将list从头部变长, 达到指定长度.