题目名称
- Swap Nodes in Pairs(Leetcode #24)
- Copy List with Random Pointer(Leetcode #138)
- Linked List Cycle(Leetcode #141)
- Reorder List(Leetcode #143)
- LRU Cache(Leetcode #146)
- 环的入口节点(剑指offer #23)
- 翻转链表(剑指offer #24)
- 合并已排序的链表(剑指offer #25)
- 树的子结构(剑指offer #26)
- 二叉树的镜像(剑指offer #27)
Swap Nodes in Pairs(Leetcode #24)
题目描述
Given a linked list, swap every two adjacent nodes and return its head.
Example:1
Given 1->2->3->4, you should return the list as 2->1->4->3.
Note:
Your algorithm should use only constant extra space.You may not modify the values in the list’s nodes, only nodes itself may be changed.
解题思路
迭代版:采用三指针从头到尾遍历,当不再存在一对节点时终止遍历。
递归版:对于一对节点,我们只需要明确,first->newfirst,second->first,当不再存在节点对时终止递归。
解题方案
迭代
1 | /** |
递归
1 | class Solution { |
Copy List with Random Pointer(Leetcode #138)
题目描述
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.
解题思路
可以用hashmap完成存储,但这里我采用的时空间O(1)的算法。思路大致如下:
- 针对每一个节点都完成复制,从而令链表1—>2->3变成1->1->2->2->3->3
- 将random节点进行连接,具体表现为cur->next->random=cur->random->next
- 分离两个链表
解题方案
1 | class Solution { |
Linked List Cycle(Leetcode #141)
题目描述
Given a linked list, determine if it has a cycle in it.
解题思路
快慢指针,没什么好说的。
解题方案
1 | class Solution { |
扩展
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.
解题思路
还是快慢指针,p的前进速度是q的两倍。设head到环起点的距离为S,环起点到pq相遇点的距离为M。假设当他们相遇时q走了K步,显然存在K=S+M。又p走了2K步(速度2倍),表明环的长度为K,即q再走K-M步必然到达环起点,而K-M=S。因此令一个指针从head前进,当其与q相遇时必然该点为环起点。
解题方案
1 | class Solution { |
Reorder List(Leetcode #143)
题目描述
Given a singly linked list L: L0→L1→…→Ln-1→Ln,reorder it to: L0→Ln→L1→Ln-1→L2→Ln-2→…
You may not modify the values in the list’s nodes, only nodes itself may be changed.
Example 1:1
Given 1->2->3->4, reorder it to 1->4->2->3.
Example 2:1
Given 1->2->3->4->5, reorder it to 1->5->2->4->3.
解题思路
解题思路大致是找到中间的那个节点,然后前半部分不动,后半部分翻转,然后再合并两个链表,大致如下所示:1->2->3->4->5 1->2->3<-4<-5 1->5->2->4->3
解题方案
1 | class Solution { |
LRU Cache(Leetcode #146)
题目描述
Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations: get and put.
get(key) - Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1.
put(key, value) - Set or insert the value if the key is not already present. When the cache reached its capacity, it should invalidate the least recently used item before inserting a new item.
Follow up:
Could you do both operations in O(1) time complexity?
Example:1
2
3
4
5
6
7
8
9
10LRUCache cache = new LRUCache( 2 /* capacity */ );
cache.put(1, 1);
cache.put(2, 2);
cache.get(1); // returns 1
cache.put(3, 3); // evicts key 2
cache.get(2); // returns -1 (not found)
cache.put(4, 4); // evicts key 1
cache.get(1); // returns -1 (not found)
cache.get(3); // returns 3
cache.get(4); // returns 4
解题思路
我们采用hashmap与双链表来完成LRU算法,原因在于双链表的插入与删除可以O(1),hashmap的查找可以O(1)。
具体实现细节:
- 越靠近链表头部说明最近使用频次越高,反之则说明最少。
- 访问节点时,若该节点存在,将其交换至链表头部,同时更新hashmap中该节点的地址。
- 插入节点时,若size已饱和,将list尾端元素删除,同时删除hashmap中对应的项,将新节点放在链表头部。
解题方案
1 | //LRUCache.h |
环的入口节点(剑指offer #23)
(本题已在上文有所提及,略去不表)
翻转链表 (剑指offer #24)
解题思路
无非是分为迭代和递归两种。
迭代:1->2->3 => 1<-2 3 => 1<-2<-3
递归:找出末尾节点p=func(head),然后对于每一个输入节点head,都有head->next->next=head,head->next=nullptr;
解题方案
迭代
1 | class Solution { |
递归
1 | class Solution { |
合并已排序的链表(剑指offer #25)
解题思路
直接参考了STL merge算法。
解题方案
1 | class Solution { |
树的子结构(剑指offer #26)
解题思路
递归解法建立在求解两个树是否相等的基础上。撰写一个判断两个树是否相等的函数,然后再主函数中针对左右子树递归调用即可。
解题方案
(本解法认为空树是任何树的子树)1
2
3
4
5
6
7
8
9
10
11
12
13
14class Solution {
public:
bool isSubtree(TreeNode* s, TreeNode* t) {
if(!s) return false;
if(isSame(s,t)) return true;
return isSubtree(s->left,t)||isSubtree(s->right,t);
}
private:
bool isSame(TreeNode* a, TreeNode*b){
if(!a&&!b) return true;
if((!a||!b)||a->val!=b->val) return false;
return isSame(a->left,b->left) && isSame(a->right,b->right);
}
};
树的镜像
解题思路
同样是递归思路求解。递归过程如下:
- root为空,返回;
- 若root不为空,交换两颗子树,并对它们执行镜像操作。
解题方案
1 | class Solution { |