题目目录:
链表题:
题目1:列表合并
升序链表融为一体:
输入:1->2->4, 1->3->4
输出:1->1->2->3->4->4
代码:
class Solution(object):
def mergeTwoLists(self, l1, l2):
cur1,cur2 = l1, l2
if cur1==None and cur2==None:
return []
elif cur1==None:
return cur2
elif cur2==None:
return cur1
result = ListNode(0)
re_cur = result
while True:
if cur1.val <= cur2.val:
re_cur.val = cur1.val
cur1 = cur1.next
else:
re_cur.val = cur2.val
cur2 = cur2.next
if cur1==None:
re_cur.next=cur2
break
elif cur2==None:
re_cur.next=cur1
break
re_cur.next = ListNode(0)
re_cur = re_cur.next
return result
题目2:反转列表
反转链表:
输入:1->2->4, 1->3->4
输出:1->1->2->3->4->4
代码:
class Solution:
def reverseList(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
cur=head
pre=None
while cur:
mid=pre
pre=cur
cur=cur.next
pre.next=mid
return pre
递归版:
def ReverseList(self, pHead):
if not pHead: return None
if not pHead.next: return pHead
headNode = self.ReverseList(pHead.next)
pHead.next.next = pHead
pHead.next = None
return headNode
题目3:删除元素
给定单向链表的头指针和一个要删除的节点的值,定义一个函数删除该节点。
返回删除后的链表的头节点。
示例 1:
输入: head = [4,5,1,9], val = 5
输出: [4,1,9]
解释: 给定你链表中值为 5 的第二个节点,那么在调用了你的函数之后,该链表应变为 4 -> 1 -> 9.
class Solution(object):
def deleteNode(self, head, val):
"""
:type head: ListNode
:type val: int
:rtype: ListNode
"""
if head.val==val:
return head.next
pre_head=head
cur_head=head.next
while True:
if cur_head.val!=val:
pre_head=pre_head.next
cur_head=cur_head.next
else:
cur_head=cur_head.next
pre_head.next=cur_head
return head
迭代:
class Solution(object):
def deleteNode(self, head, val):
if head.val==val:
return head.next
head.next=self.deleteNode(head.next, val)
return head
题目4:链表截取最后几个
输入一个链表,输出该链表中倒数第k个节点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾节点是倒数第1个节点。例如,一个链表有6个节点,从头节点开始,它们的值依次是1、2、3、4、5、6。这个链表的倒数第3个节点是值为4的节点
初始化: 前指针 former 、后指针 latter ,双指针都指向头节点 head 。
构建双指针距离: 前指针 former 先向前走 k 步(结束后,双指针 former 和 latter 间相距 k 步)。
双指针共同移动: 循环中,双指针 former 和 latter 每轮都向前走一步,直至 former 走过链表 尾节点 时跳出(跳出后, latter 与尾节点距离为 k-1,即 latter 指向倒数第 k 个节点)。
返回值: 返回 latter 即可。
class Solution:
def getKthFromEnd(self, head: ListNode, k: int) -> ListNode:
former, latter = head, head
for _ in range(k):
former = former.next
while former:
former, latter = former.next, latter.next
return latter
题目5:链表相交的节点(双指针法)
输入两个链表,找出它们的第一个公共节点。
们使用两个指针 node1,node2 分别指向两个链表 headA,headB 的头结点,然后同时分别逐结点遍历,当 node1 到达链表 headA 的末尾时,重新定位到链表 headB 的头结点;当 node2 到达链表 headB 的末尾时,重新定位到链表 headA 的头结点。
这样,当它们相遇时,所指向的结点就是第一个公共结点。
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def getIntersectionNode(self, headA, headB):
node1, node2 = headA, headB
while node1 != node2:
node1 = node1.next if node1 else headB
node2 = node2.next if node2 else headA
return node1
题目5:环形链表(双指针法–快慢型)
给定一个链表,判断链表中是否有环。
如果链表中存在环,则返回 true 。 否则,返回 false 。
class Solution(object):
def hasCycle(self, head):
"""
:type head: ListNode
:rtype: bool
"""
if not head or not head.next: return False
slow = head
fast = head.next
while slow!=fast:
if not fast or not fast.next:
return False
slow=slow.next
fast=fast.next.next
return True
题目5:反转链表(穿针引线法)
给你单链表的头节点 head 和两个整数 left 和 right ,其中 left <= right 。请你反转从位置 left 到位置 right 的链表节点,返回 反转后的链表 。
var reverseBetween = function(head, left, right) {
// 设置 dummyNode 是这一类问题的一般做法(防止头部出现额外的判断)
const dummy_node = new ListNode(-1);
dummy_node.next = head;
let pre = dummy_node;
for (let i = 0; i < left - 1; ++i) {
pre = pre.next;
}
let cur = pre.next;
for (let i = 0; i < right - left; ++i) {
const next = cur.next;
cur.next = next.next;
next.next = pre.next;
pre.next = next;
}
return dummy_node.next;
};
构造数据结构:
题目1:构造RLU缓存
设计和构建一个“最近最少使用”缓存,该缓存会删除最近最少使用的项目。缓存应该从键映射到值(允许你插入和检索特定键对应的值),并在初始化时指定最大容量。当缓存被填满时,它应该删除最近最少使用的项目。
它应该支持以下操作: 获取数据 get 和 写入数据 put 。
获取数据 get(key) - 如果密钥 (key) 存在于缓存中,则获取密钥的值(总是正数),否则返回 -1。
写入数据 put(key, value) - 如果密钥不存在,则写入其数据值。当缓存容量达到上限时,它应该在写入新数据之前删除最近最少使用的数据值,从而为新的数据值留出空间。
/**
* @param {number} capacity
*/
var Node = function(key=0,value=0){
this.key =key;
this.value = value
this.prev = null
this.next = null
}
var LRUCache = function(capacity) {
this.cache ={}
this.head = new Node()
this.tail = new Node()
this.head.next = this.tail
this.tail.prev = this.head
this.capacity = capacity
this.size = 0
};
/**
* @param {number} key
* @return {number}
*/
LRUCache.prototype.get = function(key) {
if (key in this.cache == false)
return -1
node = this.cache[key]
this.moveToHead(node)
return node.value
};
/**
* @param {number} key
* @param {number} value
* @return {void}
*/
LRUCache.prototype.put = function(key, value) {
if (key in this.cache == false){
// 如果 key 不存在,创建一个新的节点
node = new Node(key, value)
// 添加进哈希表
this.cache[key] = node
// 添加至双向链表的头部
this.addToHead(node)
this.size += 1
if (this.size > this.capacity){_
// 如果超出容量,删除双向链表的尾部节点
removed = this.removeTail()
// 删除哈希表中对应的项
delete this.cache[removed.key]
this.size -= 1}
}
else{
// 如果 key 存在,先通过哈希表定位,再修改 value,并移到头部
node = this.cache[key]
node.value = value
this.moveToHead(node)
}
};
LRUCache.prototype.addToHead=function(node){
node.prev = this.head
node.next = this.head.next
this.head.next.prev = node
this.head.next = node
}
LRUCache.prototype.removeNode=function(node){
node.prev.next = node.next
node.next.prev = node.prev
}
LRUCache.prototype.moveToHead=function(node){
this.removeNode(node)
this.addToHead(node)
}
LRUCache.prototype.removeTail=function(){
node = this.tail.prev
this.removeNode(node)
return node
}
/**
* Your LRUCache object will be instantiated and called as such:
* var obj = new LRUCache(capacity)
* var param_1 = obj.get(key)
* obj.put(key,value)
*/