QQ空间 新浪微博 腾讯微博 微信 更多
  

七月伊始 LeetCode算法总结

七月伊始

早上买了LeetCode的课程,解锁了付费题目,付费倒逼学习;

意识到这么久学习的东西,都是写在自己的笔记, 如今希望自己能够用自己拙笔记录这个学习和总结的过程。

队列的学习

设计循环队列

设计你的循环队列实现。 循环队列是一种线性数据结构,其操作表现基于 FIFO(先进先出)原则并且队尾被连接在队首之后以形成一个循环。它也被称为“环形缓冲器”。

循环队列的一个好处是我们可以利用这个队列之前用过的空间。在一个普通队列里,一旦一个队列满了,我们就不能插入下一个元素,即使在队列前面仍有空间。但是使用循环队列,我们能使用这些空间去存储新的值。

你的实现应该支持如下操作:

  • MyCircularQueue(k): 构造器,设置队列长度为 k 。
  • Front: 从队首获取元素。如果队列为空,返回 -1 。
  • Rear: 获取队尾元素。如果队列为空,返回 -1 。
  • enQueue(value): 向循环队列插入一个元素。如果成功插入则返回真。
  • deQueue(): 从循环队列中删除一个元素。如果成功删除则返回真。
  • isEmpty(): 检查循环队列是否为空。
  • isFull(): 检查循环队列是否已满。
class MyCircularQueue {
private int[] data;
private int size;
private int head; //头指针
private int tail; //尾指针

public MyCircularQueue(int k) {
    this.data = new int[k];
    this.size = 0;
    this.head = -1;
    this.tail = -1;
}

public boolean enQueue(int value) {
    if(size == data.length){
        return false;
    }
    tail = (tail + 1)%data.length;
    data[tail] = value;
    if(size == 0){
        head = tail;
    }
    size++;
    return true;
}

public boolean deQueue() {
    if(size == 0){
        return false;
    }
    head = (head+1)%data.length;
    size--;
    return true;
}

public int Front() {
    if(size == 0){
        return -1;
    }
    return data[head];
}

public int Rear() {
    if(size == 0){
        return -1;
    }
    return data[tail];
}

public boolean isEmpty() {
    return size == 0;
}

public boolean isFull() {
    return size == data.length;
}

}

数据流中的移动平均值

给定一个整数数据流和一个窗口大小,根据该滑动窗口的大小,计算其所有整数的移动平均值。

class MovingAverage {    
    int size = 0;  
    List<Integer> list = new ArrayList<Integer>();
    /** Initialize your data structure here. */
    public MovingAverage(int size) {
        this.size = size;
    }    
    public double next(int val) {
        int count = 0;
        list.add(val);
        if(list.size() < this.size){
            for(int j=0;j<list.size();j++){
                count += list.get(j);
            }
            return (double)count/list.size();
        }
        for(int i=list.size()-1;i>(list.size()-1-this.size);i--){
            count += list.get(i);
        }
        return (double)count/this.size;
    }
}

(春招问道了类似的题目, 酷家面试二面的,一面问我全部关于链表的,二面全是队列的)

墙与门

你被给定一个 m × n 的二维网格,网格中有以下三种可能的初始化值:

  1. -1 表示墙或是障碍物
  2. 0 表示一扇门
  3. INF 无限表示一个空的房间。然后,我们用 231 - 1 = 2147483647 代表 INF。你可以认为通往门的距离总是小于 2147483647 的。

你要给每个空房间位上填上该房间到 最近 门的距离,如果无法到达门,则填 INF 即可。

宽度优先搜索
与其从一个空的房间开始找门,我们何不按另一种方式来搜索?换言之,我们从门开始做宽度优先搜索。由于宽度优先搜索保证我们在搜索 d + 1 距离的位置时, 距离为 d 的位置都已经被搜索过了,所以到达每一个房间的时候都一定是最短距离。

private static final int EMPTY = Integer.MAX_VALUE;
private static final int GATE = 0;
private static final List<int[]> DIRECTIONS = Arrays.asList(
        new int[] { 1,  0},
        new int[] {-1,  0},
        new int[] { 0,  1},
        new int[] { 0, -1}
);

public void wallsAndGates(int[][] rooms) {
    int m = rooms.length;
    if (m == 0) return;
    int n = rooms[0].length;
    Queue<int[]> q = new LinkedList<>();
    for (int row = 0; row < m; row++) {
        for (int col = 0; col < n; col++) {
            if (rooms[row][col] == GATE) {
                q.add(new int[] { row, col });
            }
        }
    }
    while (!q.isEmpty()) {
        int[] point = q.poll();
        int row = point[0];
        int col = point[1];
        for (int[] direction : DIRECTIONS) {
            int r = row + direction[0];
            int c = col + direction[1];
            if (r < 0 || c < 0 || r >= m || c >= n || rooms[r][c] != EMPTY) {
                continue;
            }
            rooms[r][c] = rooms[row][col] + 1;
            q.add(new int[] { r, c });
        }
    }
}
posted @ 2019-07-02 15:07  nupt想象之中  阅读(371)  评论(0编辑  收藏  举报