设计场景题

vivo智能手机产能

https://www.nowcoder.com/questionTerminal/2e4363c23c6741f98319d5a7e3882325?toCommentId=14113374

import java.util.*;

public class Solution {

    public int solution (int n) {
        int afterDay = 1; //接下来的1,2,3,4天
        int i = 0; //第几天--也可以从1开始,不过需要修改条件<=n, i== n+1
        int sum = 0;
        while(i < n) {
            //接下来的afterDay天内,产量都是afterDay
            for(int j = 1; j <= afterDay; j++) {                
                sum+=afterDay;
                i++;
                if(i == n) return sum;
            }
            afterDay+=1;
        }
        return sum;
    }
}
146. LRU 缓存

缓存,意味着某些元素到了一定条件就会被清除,而对于被重复使用的元素则会被保存更久。
力扣:https://leetcode.cn/problems/lru-cache/

思路:哈希表+双向链表
LRU缓存需要两个操作,一个是get操作,一个是put操作,由于get和put要达到O(1)级别,所以只有用哈希表存放才能实现。LRU缓存还要求那些不常用的元素要被移除(条件是当缓存超过指定大小),这就需要实现双向链表了。put的时候,如果超过大小,需要先移除不常用元素才能添加,不常用的元素可通过头节点移除,在通过尾节点添加新元素。对于get访问过的节点,只需要移到链表尾部即可,这样就能保证其活得更久。其中移除只有使用双链表才能使速度达到O(1)级别,因为链表移除一个非头部或尾部的节点需要前一个节点的协助。只有双向链表能根据一个节点移除该节点

class LRUCache {

    class Node {   //有前后指针的节点
        Node prev;  //指向上一个
        Node next;  //指向下一个
        Integer value;
        Integer key;

        public Node() {
        }

        public Node(Integer key, Integer value) {
            this.key = key;
            this.value = value;
        }
    }

    Map<Integer, Node> map = null; //存放key和node
    int capacity;
    Node head; //头节点---------用于移除最近最少使用的元素
    Node tail; //尾节点---------用于添加元素

    public LRUCache(int capacity) {
        map = new HashMap<>(capacity);
        this.capacity = capacity;
        //初始化双向链表
        head = new Node();
        tail = new Node();
        head.next = tail;
        tail.prev = head;
    }

    public int get(int key) {
        if (!map.containsKey(key)) return -1;
        //将该节点移到链表尾部==移除+添加
        Node node = map.get(key);
        remove(node);
        insert(node);
        return node.value;
    }

    public void put(Integer key, Integer value) {
        //存在则更新
        if(map.containsKey(key)) {
            Node node = map.get(key);
            remove(node);
            node.value = value;
            insert(node);
            return;
        }
        //超过缓存大小
        if(map.size() == this.capacity) {               
            //head.next代表链表的第二个节点,也就是不常用的节点
            //先删除map中的键值;然后移除节点,顺序不可颠倒,因为先移除head.next会改变。
            map.remove(head.next.key);
            remove(head.next);                
        }
        Node node = new Node(key, value);
        map.put(key, node);
        insert(node);
    }

    //根据节点移除该节点
    public void remove(Node node) {
        node.prev.next = node.next;
        node.next.prev = node.prev;
        node.prev = null;
        node.next = null;
    }

    //将元素添加到尾节点
    public void insert(Node node) {
        tail.prev.next = node;  //倒数第二个节点指向node
        node.prev = tail.prev;  //node指向倒数第二个节点        
        tail.prev = node;      //尾节点执行node
        node.next = tail;       //node指向尾节点        
    }

}

测试用例

["LRUCache","get","put","get","put","put","get","get"]
[[2],[2],[2,6],[1],[1,5],[1,2],[1],[2]]
["LRUCache","put","put","put","put","get","get"]
[[2],[2,1],[1,1],[2,3],[4,1],[1],[2]]
*滑动窗口最大值

链接:https://leetcode.cn/problems/sliding-window-maximum/

class Solution {
    public int[] maxSlidingWindow(int[] nums, int k) {
        //双端队列
        LinkedList<Integer> queue = new LinkedList<>();
        //预处理前三个元素----可以合并到下面,当i>=k时,执行res
        for(int i = 0 ; i < k; i++) {
            while(!queue.isEmpty() && nums[queue.peekLast()] <= nums[i]) {
                queue.pollLast();
            }
            queue.add(i);
        }
        int l = nums.length;
        int[] res = new int[l - k + 1];
        int c = 0;
        for(int i = k; i < l; i++) {            
            res[c++] = nums[queue.peek()];
            //保证队列单调递减
            while(!queue.isEmpty() && nums[queue.peekLast()] <= nums[i]) {
                queue.pollLast();             
            }
            queue.add(i);
            //判断是否需要移除队头元素,如果该位置在滑动窗口左边就要移除
            if(queue.peek() <= i - k) {
                queue.poll();
            }
        }
        res[c++] = nums[queue.peek()];
        return res;
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值