Leetcode Weekly Contest 109

933. Number of Recent Calls

https://leetcode.com/problems/number-of-recent-calls/description/
这道题,维护一个队列,每当一个新的时间进来,看看队列头,时间是不是超出了那个范围,超出了就POP,一直到在范围里。

Deque q = new ArrayDeque<>();
    public RecentCounter() {
        
    }
    
    public int ping(int t) {
        
        while(!q.isEmpty() && t - q.peekFirst() > 3000) {
            q.pollFirst();
        }
        q.offerLast(t);
        return q.size();
    }

934. Shortest Bridge

这道题用FLOOD FILL 找到2个岛,分别把坐标存进2个SET。
随后就可以用BFS,找最短路的。这里BFS,和word ladder那道题是一样的。
对所有点,往外扩散,找到这个岛所有一步可达,所有2步可达,所有三步可达。一直到触碰到另外一个岛。

int h;
    int l;
    final int[][] dirs = {{1,0},{0,1},{0,-1},{-1,0}};
    public int shortestBridge(int[][] A) {
        h = A.length;
        l = A[0].length;
        Set st = new HashSet<>();
        Set ed = new HashSet<>();
        
        for (int i = 0; i < h; i++) {
            for (int j = 0; j < l; j++) {
                if (A[i][j] == 0) continue;
                if(st.isEmpty())
                    floodfill(st,A,i,j);
                else
                    floodfill(ed,A,i,j);
            }
        }
        int step = 0;
        
        Set seen = new HashSet<>(st);
        while(true) {
            Set next = new HashSet<>();
            for (int i : st) {
                int y = i / l;
                int x = i % l;
                for(int[] dir : dirs){
                    int ny = y + dir[0];
                    int nx = x + dir[1];
                    int nkey = ny * l + nx;
                    if(ny == h || nx == l || nx < 0 || ny < 0 || seen.contains(nkey)) continue;
                    if(ed.contains(nkey)) return step;
                    seen.add(nkey);
                    next.add(nkey);
                }
            }
            st = next;
            step++;
        }
        
    }
    private void floodfill(Set s, int[][] A, int y, int x) {
        s.add(y * l + x);
        for(int[] dir : dirs){
            int ny = y + dir[0];
            int nx = x + dir[1];
            int nkey = ny * l + nx;
            if(ny == h || nx == l || nx < 0 || ny < 0 || A[ny][nx] == 0 || s.contains(nkey)) continue;
            floodfill(s,A,ny,nx);
        }
    }

935. Knight Dialer

https://leetcode.com/problems/knight-dialer/description/
这道题我看了下,就是每个状态可以转移到另外的一些状态。
根据跳跃规则。那么一共有10个状态。每个状态可以通过一步跳到对应的状态我存进STEP。
随后就是对每一步的这个状态,去映射到下一步的状态。用个DP数组来存。
最后对这种步长的所有走法求和就行。
dp i j 就是 花了 I 步 落在第J个数字上的步数。
那么转移方程,就是根据一个数字 怎么到 另一个数字 都加上去。

public int knightDialer(int N) {
        int[][] dp = new int[N][10];
        int[][] steps = new int[][]{{4,6},{8,6},{7,9},{4,8},{3,9,0},{},{1,7,0},{2,6},{1,3},{2,4}};
        int M = 1000000007;
        Arrays.fill(dp[0],1);
        for (int i = 1; i < N; i++) {
            for (int j = 0; j < 10; j++) {
                for(int k = 0; k < steps[j].length; k++){
                    dp[i][steps[j][k]] = (dp[i][steps[j][k]] + dp[i-1][j])%M;
                }
            }
        }
        long res = 0;
        for (int i = 0; i < 10; i++) {
            res += dp[N-1][i];
        }
        res %= M;
        return (int)res;
    }

936. Stamping The Sequence

https://leetcode.com/problems/stamping-the-sequence/description/
这道题的难点在于逆向思维,以终·为始。如果我们可以一开始就构造好了,随后要把他们全抹掉,记录顺序,顺序也是反着生成的。
首先我们定义每一个位置,都有2种属性,可以直接消的就是字符相等的集合,和没法在这个位置上消的字符。
分别放进MADE, TODO。
然后我们把所有MADE 是满的,也就是TODO 是空的,那些MADE的坐标放进QUEUE。 这个点,都是最后一步覆盖上去的。
然后把这个点,都放进STACK。随后从QUEUE里弹出来用过的坐标。对他们能影响到的其他NODE里,去删除那些NODE里的TODO。 那么一旦有新的NODE,TODO 是空了,又可以放进QUEUE。
最后根据stack 就可以反向生成步骤了。

public int[] movesToStamp(String stamp, String target) {
        int sl = stamp.length();
        int tl = target.length();
        Queue q = new LinkedList<>();
        boolean[] done = new boolean[tl];
        Stack st = new Stack<>();
        List res = new ArrayList<>();
        for (int i = 0; i <= tl - sl; i++) {
            Set made = new HashSet<>();
            Set todo = new HashSet<>();
            for (int j = 0; j < sl; j++) {
                if (stamp.charAt(j) == target.charAt(i + j)) {
                   made.add(i + j); 
                } else {
                    todo.add(i + j);
                }
            }
            Node cur = new Node(made, todo);
            if (todo.isEmpty()) {
                for (int j : made) {
                    if (done[j]) continue;
                    q.offer(j);
                    done[j] = true;
                }
                st.push(i);
            }
            res.add(cur);
        }
        while (!q.isEmpty()) {
            int cur = q.poll();
            for (int i = Math.max(0,cur - sl + 1); i < Math.min(tl - sl + 1,cur + sl); i++) {
                Node newn = res.get(i);
                if (!newn.todo.contains(cur)) continue;
                
                newn.todo.remove(cur);
                if (newn.todo.isEmpty()) {
                    for (int j : newn.made) {
                        if (done[j]) continue;
                        q.offer(j);
                        done[j] = true;
                    }
                    st.push(i);
                }
                
            }
        }
        for(boolean d : done) if(!d) return new int[0];
        int[] ans = new int[st.size()];
        int idx = 0;
        while (!st.isEmpty()) {
            ans[idx++] = st.pop();
        }
        return ans;
    }
    class Node {
        Set made, todo;
        public Node(Set made, Set todo) {
            this.made = made;
            this.todo = todo;
        }
    }

你可能感兴趣的:(Leetcode Weekly Contest 109)