Day12 LeetCode146 148 155(JAVA版)

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();
 */
已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页