登录
OAmaster

Images are stored as grids of 0/1. A connected region is a set of cells containing 1 that are reachable from each other by moving row or column through adjacent 1-cells. Given two grids of the same size, count the number of regions in the second grid that match (occupy the exact same set of cell positions as) some region in the first grid.

Example

grid1 = [[1,1,1],[1,0,0],[1,0,0]]
grid2 = [[1,1,1],[1,0,0],[1,0,1]]
Answer: 1
Grid1 has one region {(0,0),(0,1),(0,2),(1,0),(2,0)}.
Grid2 has two regions: that same set plus {(2,2)}. Only the first matches.

解法

对两张网格分别做 BFS/DFS 提取连通块的坐标集合;把每个集合规范化为排序后的元组/字符串作 key;统计 grid2 中 key 出现在 grid1 集合里的连通块数。复杂度 O(N*M)

def countMatchingRegions(grid1, grid2):
    def regions(g):
        n, m = len(g), len(g[0])
        seen = [[False]*m for _ in range(n)]
        out = []
        for i in range(n):
            for j in range(m):
                if g[i][j] == 1 and not seen[i][j]:
                    region, stack = set(), [(i, j)]
                    while stack:
                        x, y = stack.pop()
                        if 0 <= x < n and 0 <= y < m and g[x][y] == 1 and not seen[x][y]:
                            seen[x][y] = True
                            region.add((x, y))
                            stack += [(x+1,y),(x-1,y),(x,y+1),(x,y-1)]
                    out.append(frozenset(region))
        return out
    r1 = set(regions(grid1))
    return sum(1 for r in regions(grid2) if r in r1)
class Solution {
    int n, m;
    int[][] g;
    boolean[][] seen;

    Set<String> collect(int[][] grid) {
        g = grid; n = g.length; m = g[0].length;
        seen = new boolean[n][m];
        Set<String> regions = new HashSet<>();
        for (int i = 0; i < n; i++)
            for (int j = 0; j < m; j++)
                if (g[i][j] == 1 && !seen[i][j]) {
                    List<int[]> cells = new ArrayList<>();
                    Deque<int[]> st = new ArrayDeque<>();
                    st.push(new int[]{i, j});
                    while (!st.isEmpty()) {
                        int[] p = st.pop();
                        int x = p[0], y = p[1];
                        if (x < 0 || x >= n || y < 0 || y >= m || g[x][y] != 1 || seen[x][y]) continue;
                        seen[x][y] = true;
                        cells.add(new int[]{x, y});
                        st.push(new int[]{x+1, y}); st.push(new int[]{x-1, y});
                        st.push(new int[]{x, y+1}); st.push(new int[]{x, y-1});
                    }
                    cells.sort((a, b) -> a[0] != b[0] ? a[0] - b[0] : a[1] - b[1]);
                    StringBuilder sb = new StringBuilder();
                    for (int[] c : cells) sb.append(c[0]).append(',').append(c[1]).append(';');
                    regions.add(sb.toString());
                }
        return regions;
    }

    int countMatchingRegions(int[][] g1, int[][] g2) {
        Set<String> a = collect(g1), b = collect(g2);
        int cnt = 0;
        for (String r : b) if (a.contains(r)) cnt++;
        return cnt;
    }
}
set<string> collect(vector<vector<int>>& g) {
 int n = g.size(), m = g[0].size();
 vector<vector<int>> seen(n, vector<int>(m, 0));
 set<string> regions;
 int dx[] = {1, -1, 0, 0}, dy[] = {0, 0, 1, -1};
 for (int i = 0; i < n; i++)
 for (int j = 0; j < m; j++)
 if (g[i][j] == 1 && !seen[i][j]) {
 vector<pair<int,int>> cells;
 stack<pair<int,int>> st;
 st.push({i, j});
 while (!st.empty()) {
 auto [x, y] = st.top(); st.pop();
 if (x < 0 || x >= n || y < 0 || y >= m || g[x][y] != 1 || seen[x][y]) continue;
 seen[x][y] = 1;
 cells.push_back({x, y});
 for (int d = 0; d < 4; d++) st.push({x + dx[d], y + dy[d]});
 }
 sort(cells.begin(), cells.end());
 string key;
 for (auto& [x, y] : cells) key += to_string(x) + "," + to_string(y) + ";";
 regions.insert(key);
 }
 return regions;
}

int countMatchingRegions(vector<vector<int>>& g1, vector<vector<int>>& g2) {
 auto a = collect(g1), b = collect(g2);
 int cnt = 0;
 for (auto& r : b) if (a.count(r)) cnt++;
 return cnt;
}

A biological researcher is examining bacteria interactions, where some bacteria are poisonous to others. The samples are arranged consecutively in a row from 1 to n. Given a list detailing which bacteria are poisonous to others, determine the number of intervals (contiguous, no reorder) within the row that contain only samples capable of coexisting.

Example

n = 3, allergic = [2, 1, 3], poisonous = [3, 3, 1]
Answer: 4
Conflicts: {2,3}, {1,3}, {1,3}. Valid intervals: (1), (2), (3), (1,2).

解法

滑动窗口:枚举右端 r,若 r 的任一冲突菌 x[l, r-1]x >= l,则把 l 跳到 x + 1;累加窗口长度 r - l + 1。复杂度 O(n + m)

def bioHazard(n, allergic, poisonous):
    conflict = [[] for _ in range(n + 1)]
    for a, p in zip(allergic, poisonous):
        conflict[a].append(p)
        conflict[p].append(a)
    ans = 0
    l = 1
    in_window = [False] * (n + 1)
    for r in range(1, n + 1):
        for x in conflict[r]:
            if in_window[x] and x >= l:
                while l <= x:
                    in_window[l] = False
                    l += 1
        in_window[r] = True
        ans += r - l + 1
    return ans
class Solution {
    static long bioHazard(int n, int[] allergic, int[] poisonous) {
        List<List<Integer>> conflict = new ArrayList<>();
        for (int i = 0; i <= n; i++) conflict.add(new ArrayList<>());
        for (int i = 0; i < allergic.length; i++) {
            conflict.get(allergic[i]).add(poisonous[i]);
            conflict.get(poisonous[i]).add(allergic[i]);
        }
        long ans = 0;
        int l = 1;
        boolean[] inWin = new boolean[n + 1];
        for (int r = 1; r <= n; r++) {
            for (int x : conflict.get(r)) {
                if (inWin[x] && x >= l) {
                    while (l <= x) { inWin[l] = false; l++; }
                }
            }
            inWin[r] = true;
            ans += r - l + 1;
        }
        return ans;
    }
}
long long bioHazard(int n, vector<int>& allergic, vector<int>& poisonous) {
 vector<vector<int>> conflict(n + 1);
 for (size_t i = 0; i < allergic.size(); i++) {
 conflict[allergic[i]].push_back(poisonous[i]);
 conflict[poisonous[i]].push_back(allergic[i]);
 }
 long long ans = 0;
 int l = 1;
 vector<int> inWin(n + 1, 0);
 for (int r = 1; r <= n; r++) {
 for (int x : conflict[r]) {
 if (inWin[x] && x >= l) {
 while (l <= x) { inWin[l] = 0; l++; }
 }
 }
 inWin[r] = 1;
 ans += r - l + 1;
 }
 return ans;
}

Complete the function below. The function receives the full standard input as a single string and returns the exact standard output lines for a chat-event tracker. Implement two operations for tracking chat events:

  • processEvent(userId, chatId, timestamp): record that userId had an event in chatId at timestamp.
  • getCount(userId, chatId, timestamp): return how many events for that exact (userId, chatId) pair occurred in the last 15 minutes, inclusive of the query timestamp and exclusive of events older than timestamp - 15 minutes. In this command-based version, each line is either EVENT userId chatId timestamp or COUNT userId chatId timestamp. Return one output line for each COUNT command. Function Description Complete solveChatEventCounts. It has one parameter, String input, containing newline-separated commands. Return the stdout payload as an array of lines, without trailing newline characters.

Constraints

Timestamps are integer minutes and commands are processed in input order. Counts are keyed by both user id and chat id.

Example 1

Input:

input = "EVENT u1 c1 0\nEVENT u1 c1 10\nEVENT u1 c2 12\nCOUNT u1 c1 14\nCOUNT u1 c1 16\nEVENT u1 c1 20\nCOUNT u1 c1 25\nCOUNT u1 c2 25"

Output:

["2","1","2","1"]

Explanation: At timestamp 16, the event at minute 0 is older than 15 minutes and is not counted.

解法

为每个 (userId, chatId) 维护一个有序时间戳列表。EVENT 直接 append;COUNT 时用二分找到 ≥ ts - 15 的下标,结果 = 列表长度 - 下标。时间 O(E + Q log E)

from bisect import bisect_left
from collections import defaultdict
from typing import List

def solveChatEventCounts(input: str) -> List[str]:
    store = defaultdict(list)
    out = []
    for line in input.split('\n'):
        if not line:
            continue
        parts = line.split()
        op, user, chat = parts[0], parts[1], parts[2]
        ts = int(parts[3])
        key = (user, chat)
        if op == 'EVENT':
            store[key].append(ts)
        else:  # COUNT
            arr = store[key]
            lo = ts - 15
            idx = bisect_left(arr, lo)
            # 同时 ≤ ts
            hi = bisect_left(arr, ts + 1)
            out.append(str(hi - idx))
    return out
import java.util.*;

class Solution {
    String[] solveChatEventCounts(String input) {
        Map<String, List<Integer>> store = new HashMap<>();
        List<String> out = new ArrayList<>();
        for (String line : input.split("\n")) {
            if (line.isEmpty()) continue;
            String[] p = line.split(" ");
            String op = p[0], key = p[1] + "|" + p[2];
            int ts = Integer.parseInt(p[3]);
            store.computeIfAbsent(key, k -> new ArrayList<>());
            if (op.equals("EVENT")) {
                store.get(key).add(ts);
            } else {
                List<Integer> arr = store.get(key);
                int lo = lowerBound(arr, ts - 15);
                int hi = lowerBound(arr, ts + 1);
                out.add(String.valueOf(hi - lo));
            }
        }
        return out.toArray(new String[0]);
    }
    int lowerBound(List<Integer> a, int target) {
        int lo = 0, hi = a.size();
        while (lo < hi) {
            int mid = (lo + hi) >>> 1;
            if (a.get(mid) < target) lo = mid + 1;
            else hi = mid;
        }
        return lo;
    }
}
class Solution {
public:
    vector<string> solveChatEventCounts(string input) {
        unordered_map<string, vector<int>> store;
        vector<string> out;
        size_t pos = 0;
        while (pos < input.size()) {
            size_t end = input.find('\n', pos);
            if (end == string::npos) end = input.size();
            string line = input.substr(pos, end - pos);
            pos = end + 1;
            if (line.empty()) continue;
            // parse tokens
            stringstream ss(line);
            string op, user, chat;
            int ts;
            ss >> op >> user >> chat >> ts;
            string key = user + "|" + chat;
            auto& arr = store[key];
            if (op == "EVENT") {
                arr.push_back(ts);
            } else {
                auto lo = lower_bound(arr.begin(), arr.end(), ts - 15);
                auto hi = lower_bound(arr.begin(), arr.end(), ts + 1);
                out.push_back(to_string(hi - lo));
            }
        }
        return out;
    }
};
Pro 会员

解锁剩余 7 道 OA 真题

开通后立即解锁完整题面 + Python / Java / C++ 三语题解。 全站 165 家公司 · 1000+ 道 OA · 月度更新。