考点重要程度:链表 -> DFS/BFS ->DP
基础
test:
|
相关习题
Remove Duplicates from Sorted List
题目
Given a sorted linked list, delete all duplicates such that each element appear only once.
For example,
Given1->1->2
, return1->2
.
Given1->1->2->3->3
, return1->2->3
.
分析
删掉链表中有重复的节点,保留一个
因为删除某个节点node,需要让node的前序节点.next = node.next,因此需要构造一个dummy node,让其指向前序节点,这样需要删除head的时候就可以令dummy.next = node.next。初始化时令dummy.next=head
最后返回dummy.next
代码
|
Remove Duplicates from Sorted List II
题目
Given a sorted linked list, delete all nodes that have duplicate numbers, leaving only distinct numbers from the original list.
For example,
Given1->2->3->3->4->4->5
, return1->2->5
.
Given1->1->1->2->3
, return2->3
.
分析
删除链表中重复出现的节点,全部删掉一个都不保留
因为删除某个节点node,需要让node的前序节点.next = node.next,删除全部重复的元素可能删掉head元素,因此需要构造一个dummy node,让其指向head的前序节点,也就是dummy.next = head。这样需要删除head的时候就可以令dummy.next = head.next。
最后反回dummy.next
代码
|
Reverse Linked List
题目
Reverse a singly linked list.、
Hint:
A linked list can be reversed either iteratively or recursively. Could you implement both?
链表反转
分析
|
代码
|
Reverse Linked List II
Reverse a linked list from position m to n. Do it in-place and in one-pass.
For example:
Given1->2->3->4->5->NULL
, m = 2 and n = 4,return
1->4->3->2->5->NULL
.Note:
Given m, n satisfy the following condition:
1 ≤ m ≤ n ≤ length of list.
将链表的第m-n位置上的元素反转
分析
|
代码
|
Partition List
题目
Given a linked list and a value x, partition it such that all nodes less than x come before nodes greater than or equal to x.
You should preserve the original relative order of the nodes in each of the two partitions.
For example,
Given 1->4->3->2->5->2
and x = 3,
return 1->2->2->4->3->5
.
给定一个链表和一个数x,将链表中比x小的排在左边,大于等于x的数字排在右边,数字的相对顺序保持不变
分析
将链表排成两队,小于x的一队,大于等于x的一队,然后把两个链表连起来。
链表的结构会发生变化,所以需要两个dummy node,一个用来指向小的队dummy_low,一个用来指向大的队dummy_high。
解题步骤:
- 遍历数组,将比x小的元素放到dummy_low队伍后面,将比x大的元素放到dummy_high队伍后面
- 结束后将两个链表连接起来:dummy_low.next指向dummy_high.next
- 将链表结尾置空:tail.next = null,否则会保留原始节点的next。
- 返回dummy_low.next;
代码
|
Merge Two Sorted Lists
题目
Merge two sorted linked lists and return it as a new list. The new list should be made by splicing together the nodes of the first two lists.
Example:
> Input: 1->2->4, 1->3->4> Output: 1->1->2->3->4->4>
分析
链表结构可能改变, 所以需要dummy node
需要一个prev指针记录当前节点,初始化指向dummy_node两个curt指针分别指向两个链表当前节点,用于比较,将比较小的接在prev后面,知道两个curt中有一个为空,将另一个链表的后面直接接到prev后面。
最后返回dummy.next
代码
|
Sort List
题目
Sort a linked list in O(n log n) time using constant space complexity.
将链表排序,时间复杂度为 O(n log n)
分析
时间复杂度为nlogn的排序:quick sort\merge sort\heap sort
quick sort和merge sort的区别:
算法流程
quik sort:整体有序 -> 局部有序、不稳定排序
- 整体有序:选定一个元素,比它小的都在它左边,比它大的都在它右边
- 局部有序:然后再对左段和右段分别做快排
merge sort:局部有序 -> 整体有序、稳定排序
- 局部有序:选取中点将序列分成左右两段,对左右两边分别排序
- 整体有序:将左右两边sort list 进行merge操作使得整个list有序
排序的稳定性
[2 , 1' , 1'', 1''' , 4 , 3' , 3'']merge sort的merge操作不会改变元素的相对顺序,所以是稳定排序quick sort会改变元素的相对位置,所以不是稳定排序
时间复杂度
quick sort平均时间复杂度,最坏时间复杂度
merge sort时间复杂度:
空间复杂度
quick sort:
merge sort: ,但是在链表中不需要开辟额外的空间
解题步骤:
merge sort
具体步骤:
- merge sort在链表中找中点,有两种方法:
- 遍历一遍,得到链表的长度n,则中间位置是n/2,再从头遍历一遍,到n/2的位置停止,找到中点
- 设置两个错位指针,一个slow一个fast,初始化都指向head,slow每次向右移动一位,fast每次向右移动两位,fast移动到末尾的时候,head指向中间,取到链表中点
- 对左右两段递归进行排序
- merge两段有序链表
代码
|
Reorder List
题目
Given a singly linked list L: L0→L1→…→L**n-1→Ln,
reorder it to: L0→L**n→L1→L**n-1→L2→L**n-2→…
You must do this in-place without altering the nodes’ values.
For example,
Given
{1,2,3,4}
, reorder it to{1,4,2,3}
.
分析
题目需要从后向前访问链表,但是链表是单向的,所以需要reverse反转操作,再和原链表merge。
具体步骤:
- 找到链表中点,mid
- 将mid之后的链表反转
- 将mid之前的链表和mid之后反转的链表做merge操作
代码
|
Fast-slow pointer
1. Middle of Linked List
寻找指针链表中点,快慢指针,快指针每次走两步,慢指针每次走一步,快指针走到链表结尾时,慢指针在中间
2 .Remove Nth Node From End of List
题目
Given a linked list, remove the nth node from the end of list and return its head.
For example,
> Given linked list: 1->2->3->4->5, and n = 2.>> After removing the second node from the end, the linked list becomes 1->2->3->5.>>
>
Note:
Given n will always be valid.
Try to do this in one pass.
删除掉从末尾开始第n个节点
分析
两个指针,fast先走n+!步slow再出发,当fast==null时,slow指向倒数第n+1个节点,删掉slow后面的节点:slow.next = slow.next.next
代码
|
3. Linked List Cycle
题目
Given a linked list, determine if it has a cycle in it.
Follow up:
Can you solve it without using extra space?
给定一个链表,判断是否有圈
分析
方法一:
判断node是否有被重复访问
从head出发,把所有访问过的点放到一个hash表里,空间复杂度O(n)
方法二:
一个快指针一个慢指针,如果路径上有环,快慢指针一定会相遇
初始化:slow = head;fast = head.next
代码
|
4. Linked List Cycle II
题目
Given a linked list, return the node where the cycle begins. If there is no cycle, return
null
.Note: Do not modify the linked list.
Follow up:
Can you solve it without using extra space?
是否有环,如果有,找到环的入口
分析
slow从快慢指针相遇的地方出发,fast指针从初始地方出发,两个指针每次走一步,直到相遇,就是环的入口
代码
|
5. Rotate List
题目
Given a list, rotate the list to the right by k places, where k is non-negative.
Example:
> Given 1->2->3->4->5->NULL and k = 2,> return 4->5->1->2->3->NULL.>
分析
将链表向后移k次
|
求解步骤:
- 求链表长度len,如果k>len,k = k%len;
- 找到从后往前数第k个元素,也就是从前往后数第len-k个元素node,和末尾元素tail
- tail.next = dummy.next;dummy.next = node.next;node.next = null
代码
|
Merge k Sorted Lists
题目
Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.
merge k 个有序链表
分析
一共三种方法,都需要掌握:
方法一:heap
用PriorityQueue实现
第一个参数 - 第二个参数:升序,最小堆
第二个参数 - 第一个参数:降序,最大堆
初始化:将链表头放进去
每次弹出最小的元素,放到结果链表后面,然后将其next入堆,重复上述
N:所有数的个数
K:链表个数
时间复杂度: ,heap中最多有k各元素,插入操作时间复杂度是
空间复杂度:
|
方法二:分治法
merge k 个链表
- 拆分成merge前k/2个链表得到list1和merge后k/2个链表得到list2
- 合并list1和 list2,得到结果
递归调用求解上述子问题
时间复杂度:
|
方法三:两两合并
1、2合并,3、4合并,….n
向上递归合并
时间复杂度:
如果是1、2合并,然后忽然3合并,…n
时间复杂度O(NK)
|
Copy List with Random Pointer
题目
A linked list is given such that each node contains an additional random pointer which could point to any node in the list or null.
Return a deep copy of the list.
给定一个链表,每个节点除包含一个next指针以外,还有一个指向任意节点的random pointer,clone链表
分析
方法一:
hash_map
先按next指针复制链表,把原链表老节点和新链表新节点的映射关系存入hash_map,再遍历一遍原链表,按照hash_map中的对应关系,把random pointer在对应的新节点中标出。
空间复杂度
|
方法二:
代码
|
总结
leetcode 相关习题
Palindrome Linked List
题目
Given a singly linked list, determine if it is a palindrome.
Follow up:
Could you do it in O(n) time and O(1) space?
给定链表,判读是否是回文串,要求时间复杂度,空间复杂度
分析
方法一:
利用stack,先进后出的性质:
- 找到终点,过程中将前半部分链表入栈
- 继续向后遍历,出栈,对比元素是否一致
|
方法二:
- 先找到中点
- 将后半部分的链表反转
- 对比前后两部分是否一致
|
160.Intersection of Two Linked Lists
题目
Write a program to find the node at which the intersection of two singly linked lists begins.
For example, the following two linked lists:
> A: a1 → a2> ↘> c1 → c2 → c3> ↗> B: b1 → b2 → b3>>
>
begin to intersect at node c1.
Notes:
- If the two linked lists have no intersection at all, return
null
.- The linked lists must retain their original structure after the function returns.
- You may assume there are no cycles anywhere in the entire linked structure.
- Your code should preferably run in O(n) time and use only O(1) memory.
找到两个链表相交的地方
分析
是个技巧题,想到了就能做出来,想不到就做不出来
方法:
两个指针分别遍历,一个先A后B,一个先B后A,两指针指向节点相等即为相交处
代码
|