1. LRU 缓存机制(LeetCode 146 题)
1.1题目
1.2思路
本题首先做缓存的过程,对键值对进行存储我们就应该想到采用hashmap存储。还需要对数据进行线性存储。进行get操作时需要进行查找,同时刷新热区数据。进行put操作也需要刷新热区数据,同时插入时超出内存应该进行删除操作后进行插入操作。完成这些操作的结构我们采用双向链表来进行存储。同时hashmap的key采用存储数据的key,value使用双向链表节点指针。
1.3代码
class LRUCache {
//双向链表定义
class DLinkedNode{
int key;
int value;
DLinkedNode prev;
DLinkedNode next;
public DLinkedNode(){}
public DLinkedNode(int _key, int _value) {
key = _key;
value = _value;
}
}//hashmap定义
private Map<Integer,DLinkedNode> cache = new HashMap<>();
private int size;
private int capacity;
private DLinkedNode head,tail;
public LRUCache(int capacity) {
//存储结构数据的初始化
this.size = 0;
this.capacity = capacity;
head = new DLinkedNode();
tail = new DLinkedNode();
head.next = tail;
tail.prev = head;
}
public int get(int key) {
DLinkedNode node = cache.get(key);
if(node == null){
return -1;
}
moveToHead(node);
return node.value;
}
public void put(int key, int value) {
DLinkedNode node = cache.get(key);
//进行put操作首先查看是否存在key的数据。
//如果存在即进行更新。以及新增至头部位置。
//如果不存在检查是否超出范围,如果超出删除链表尾部数据,将直接插入头部即可。
if(node==null){
DLinkedNode newNode = new DLinkedNode(key,value);
cache.put(key,newNode);
addToHead(newNode);
++size;
if(size>capacity){
DLinkedNode tail = removeTail();
cache.remove(tail.key);
size--;
}
}else{
node.value = value;
moveToHead(node);
}
}
private void addToHead(DLinkedNode node){
node.prev = head;
node.next = head.next;
head.next.prev = node;
head.next = node;
}
private void removeNode(DLinkedNode node){
node.prev.next = node.next;
node.next.prev = node.prev;
}
private void moveToHead(DLinkedNode node){
removeNode(node);
addToHead(node);
}
private DLinkedNode removeTail(){
DLinkedNode res = tail.prev;
removeNode(res);
return res;
}
}
/**
* Your LRUCache object will be instantiated and called as such:
* LRUCache obj = new LRUCache(capacity);
* int param_1 = obj.get(key);
* obj.put(key,value);
*/
2. 排序链表(LeetCode 148 题)
2.1题目
2.2思路
解法1
因为本题需要排序解答,同时对链表操作,在堆排序,归并排序,快速排序中选择归并排序的方法,将时间复杂度降到nlogn。
采用归并排序的方法需要找到中间位置,如何找中间位置,我们使用快慢指针。快慢指针找到mid位置
然后对head,mid以及mid、tail位置进行归并递归。最后将两个排好序的l1、l2链表进行拼接。
2.3代码
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode sortList(ListNode head) {
return sortL(head,null);
}
public ListNode sortL(ListNode head,ListNode till){
if(head==null) return head;
if(head.next==till){
head.next = null;
return head;
}
ListNode fast = head;
ListNode slow = head;
ListNode mid;
while(fast!=till){
slow = slow.next;
fast = fast.next;
if(fast!=till){
fast = fast.next;
}
}
mid = slow;
ListNode l1 = sortL(head,mid);
ListNode l2 = sortL(mid,till);
ListNode ans = sorttwo(l1,l2);
return ans;
}
public ListNode sorttwo(ListNode l1,ListNode l2){
ListNode ans = new ListNode(0);
ListNode ansp = ans;
while(l1!=null&&l2!=null){
if(l1.val<l2.val){
ansp.next = l1;
l1 = l1.next;
}
else{
ansp.next = l2;
l2 = l2.next;
}
ansp = ansp.next;
}
if(l1!=null) ansp.next = l1;
else if(l2!=null) ansp.next = l2;
return ans.next;
}
}
3. 最小栈(LeetCode 155题)
3.1题目
3.2思路
这是一个设计类的题。你可以直接用他的栈数据结构。我采用了双向链表数据结构实现栈的操作。
判断栈是否为空,为空存储put的第一个数据为最小值。每次新put与min做比较,及时更新。因此put时间复杂度为1。通常的最小值求解时间复杂度也为1。
在删除栈元素中,如果末尾不等于最小值,删除的时间复杂度也为1。如果等于最小值,删除的时间复杂度为n。
每次求解最小值时间复杂度都为1。取top时间复杂度也为1。
3.3代码
class MinStack {
class FTList{
int val;
FTList next;
FTList pre;
public FTList() {}
public FTList(int val) {
this.val = val;
}
}
private FTList head,tail ;
private int min;
/** initialize your data structure here. */
public MinStack() {
head = new FTList();
tail = new FTList();
head.next = tail;
tail.pre = head;
}
public void push(int x) {
if(head.next==tail){
min = x;
}
else{
min = x<min?x:min;
}
FTList node = new FTList(x);
node.pre = tail.pre;
node.next = tail;
tail.pre.next = node;
tail.pre = node;
}
public void pop() {
if(tail.pre.val==min){
FTList node = head.next;
min = node.val;
while(node!=tail.pre){
min = node.val<min?node.val:min;
node = node.next;
}
}
tail.pre = tail.pre.pre;
tail.pre.next = tail;
}
public int top() {
return tail.pre.val;
}
public int getMin() {
return min;
}
}
/**
* Your MinStack object will be instantiated and called as such:
* MinStack obj = new MinStack();
* obj.push(x);
* obj.pop();
* int param_3 = obj.top();
* int param_4 = obj.getMin();
*/