2022/11 LeetCode练习

🔰🔰🔰:困难
🔰🔰:中等
🔰:简单
💤:待补题

🔰1662.检查两个字符串数组是否相等

https://leetcode.cn/problems/check-if-two-string-arrays-are-equivalent/

简单的双指针操作

class Solution {
public:
    bool arrayStringsAreEqual(vector<string>& word1, vector<string>& word2) {
        int a = 0, b = 0;
        int i = 0, j = 0;
        int n = word1.size(), m = word2.size();
        while(i < n && j < m)
        {
            if(word1[i][a++] != word2[j][b++]) return false;
            if(a == word1[i].size()){
                a = 0;
                ++i;
            }
            if(b == word2[j].size()){
                b = 0;
                ++j;
            }
        }

        return i == n && j == m;
    }
};

🔰🔰2453.摧毁一系列目标

https://leetcode.cn/problems/destroy-sequential-targets/

暴力, 超时

  1. 先用map记录了每个位置上目标的数量, 以及最远的位置maxnum
  2. 在区间[nums[i], nums[i]+space*j] (nums[i]+space*j <= maxnum)中累加符合条件的位置上的目标数量, 并更新最大值
class Solution {
public:
    int destroyTargets(vector<int>& nums, int space) {
        int n = nums.size();
        map<int, int> mp;
        int maxnum = -1;
        for(int i = 0; i < n; ++i){
            mp[nums[i]] ++;
            maxnum = nums[i]>maxnum ? nums[i]:maxnum;
        }

        int res = 1e9, resnum = -1;
        for(int i = 0; i < n; ++i){
            int t = 0;
            int k = ((maxnum-nums[i])/space)+1;
            for(int j = 0; j <= k; ++j){
                t += mp[nums[i]+space*j];
            }
            if(t >= resnum){
                resnum = t;
                res = res < nums[i] ? res : nums[i];
            }
        }
        return res;
    }
};

转化思路:

  1. 要找到尽可能多的数x满足nums[i]+c*space 👉 找到尽可能多的数k = x%space = nums[i]%space
  2. 在摧毁数目最多的前提下,nums[i]的最小值 👉 从小到大遍历num[],找满足最多的那个k
class Solution {
public:
    int destroyTargets(vector<int>& nums, int space) {
        unordered_map<int, int> cnt;
        sort(nums.begin(), nums.end());
        for(auto& x:nums) ++cnt[x%space];

        int res = 0, t = 0;
        for(auto& x:nums){
            if(t < cnt[x%space]){
                t = cnt[x%space];
                res = x;
            }
        }
        return res;
    }
};

🔰1620.网络信号最好的坐标

https://leetcode.cn/problems/coordinate-with-maximum-network-quality/
纯枚举

class Solution {
public:
    vector<int> bestCoordinate(vector<vector<int>>& towers, int radius) {
        int n = towers.size();
        int resx, resy, _max = -1;
        for(int i = 0; i <= 50; ++i) {
            for(int j = 0; j <= 50; ++j) {
                int t = 0;
                for(auto& e:towers){
                    double d = sqrt((i-e[0])*(i-e[0])+(j-e[1])*(j-e[1]));
                    if(d <= radius) t += (int)(e[2]/(1+d));
                }
                if(t > _max) {
                    resx = i, resy = j;
                    _max = t;
                }
            }
        }
        return {resx, resy};
    }
};

✨蓝桥杯H: 扫雷

💣
小明最近迷上了一款名为《扫雷》的游戏。
其中有一个关卡的任务如下:
在一个二维平面上放置着 n 个炸雷,第 i 个炸雷 (xi,yi,ri) 表示在坐标 (xi,yi) 处存在一个炸雷,它的爆炸范围是以半径为 ri 的一个圆。
为了顺利通过这片土地,需要玩家进行排雷。
玩家可以发射 m 个排雷火箭,小明已经规划好了每个排雷火箭的发射方向,第 j 个排雷火箭 (xj,yj,rj) 表示这个排雷火箭将会在 (xj,yj) 处爆炸,它的爆炸范围是以半径为 rj 的一个圆,在其爆炸范围内的炸雷会被引爆。
同时,当炸雷被引爆时,在其爆炸范围内的炸雷也会被引爆。
现在小明想知道他这次共引爆了几颗炸雷?
你可以把炸雷和排雷火箭都视为平面上的一个点。
一个点处可以存在多个炸雷和排雷火箭。
当炸雷位于爆炸范围的边界上时也会被引爆。
输入格式
输入的第一行包含两个整数 n、m。
接下来的 n 行,每行三个整数 xi,yi,ri,表示一个炸雷的信息。
再接下来的 m 行,每行三个整数 xj,yj,rj,表示一个排雷火箭的信息。

输出格式
输出一个整数表示答案。

数据范围

对于 40% 的评测用例:0 ≤ x, y ≤ 10^9, 0 ≤ n, m ≤ 10^3, 1 ≤ r ≤ 10,
对于 100% 的评测用例:0 ≤ x, y ≤ 10^9, 0 ≤ n, m ≤ 5×10^4, 1 ≤ r ≤ 10。

输入样例:

2 1
2 2 4
4 4 2
0 0 5

输出样例:

2

样例解释

示例图如下,排雷火箭 1 覆盖了炸雷 1,所以炸雷 1 被排除;炸雷 1 又覆盖了炸雷 2,所以炸雷 2 也被排除。
image

图遍历 + 手动哈希

#include<iostream>
#include<algorithm>
#include<cstring>

using namespace std;
typedef long long LL;
const int N = 5e4+10, M = 1e6+7;
struct Circle{
    int x, y, r;
}cir[N];

LL h[M];
int st[M];
int id[M];

bool check(int x, int y, int i, int j, int r) {
    return (x-i)*(x-i)+(y-j)*(y-j) <= r*r;
}

//(x, y) => LL
LL get_key(int x, int y) {
    return x*1000000001ll + y;
}

//(x, y) => hashcode
int find(int x, int y) {
    LL key = get_key(x, y);
    int t = (key % M + M) % M;

    while(h[t] != -1 && h[t] != key)
        if(++t == M)
            t = 0;
    
    return t;
}

void dfs(int x, int y, int r) {
    st[find(x, y)] = true;

    for (int i = x-r; i <= x+r; ++i){
        for(int j = y-r; j <= y+r; ++j){
            if(check(x, y, i, j, r)){
                int t = find(i, j);
                if(id[t] && !st[t]) dfs(i, j, cir[id[t]].r);
            }
        }
    }
}

int main()
{
    memset(h, -1, sizeof(h));
    int n, m;
    scanf("%d%d", &n, &m);

    int x, y, r;
    for(int i = 1; i <= n; ++i){
        scanf("%d%d%d", &x, &y, &r);
        cir[i] = {x, y, r};

        int t = find(x, y);
        if(h[t] == -1) h[t] = get_key(x, y);
        if(!id[t] || cir[id[t]].r < r) id[t] = i;
    }

    while(m --)
    {
        scanf("%d%d%d", &x, &y, &r);

        for (int i = x-r; i <= x+r; ++i){
            for(int j = y-r; j <= y+r; ++j){
                if(check(x, y, i, j, r)){
                    int t = find(i, j);
                    if(id[t] && !st[t]) dfs(i, j, cir[id[t]].r);
                }
            }
        }
    }

    int res = 0;
    for(int i = 1; i <= n; ++i)
        if(st[find(cir[i].x, cir[i].y)])
            ++res;

    printf("%d", res);
    return 0;
}

🔰1668.最大重复子字符串

https://leetcode.cn/problems/maximum-repeating-substring/
注意审题

class Solution {
public:
    int maxRepeating(string sequence, string word) {
        int res = 0;
        string k_rep = word;
        while(sequence.find(k_rep) != -1)
        {
            res ++;
            k_rep += word;
        }
        return res;
    }
};

🔰🔰754.到达终点数字

https://leetcode.cn/problems/reach-a-number/
参考题解: 灵茶山艾府

class Solution {
public:
    int reachNumber(int target) {
        target = target < 0 ? -target : target;
        int num = 0;
        while(target > 0)
        {
            ++num;
            target -= num;
        }

        return target&1 ? num+1+num%2 : num;
    }
};

优化

上面的while循环目的是寻找满足 $ \frac {n(n+1)}{2} \leqslant |target| $ 的最小值num,
即$ num = \lceil \frac {-1 + \sqrt {1+8 | target | }}{2} \rceil $

class Solution {
public:
    int reachNumber(int target) {
        target = target < 0 ? -target : target;
        int num =ceil((sqrt(1+8L*target)-1)/2);
        return (num*(num+1)/2-target)&1 ? num+1+num%2 : num;
    }
};

🔰🔰🔰1106.解析布尔表达式

https://leetcode.cn/problems/parsing-a-boolean-expression/
栈的运用

class Solution {
public:
    bool parseBoolExpr(string expression) {
        stack<char> stk;
        for(auto e : expression) {
            if(e == '(' || e == ',') continue;
            if(e == 't' || e == 'f') stk.push(e);
            else if(e == '|' || e == '&' || e == '!') stk.push(e);
            else {
                int tnum = 0, fnum = 0;
                while(stk.top() == 't' || stk.top() == 'f'){
                    if(stk.top() == 't') ++tnum;
                    else ++fnum;
                    stk.pop();
                }
                char op = stk.top();
                stk.pop();
                stk.push(calculate(tnum, fnum, op));
            }
        }

        return stk.top() == 't';
    }

    char calculate(int tnum, int fnum, char op){
        if(op == '!') return tnum ? 'f' : 't';
        if(op == '|') return tnum ? 't' : 'f';
        if(op == '&') return fnum ? 'f' : 't';
        return 't';
    }
};

🔰🔰6230.长度为 K 子数组中的最大和

https://leetcode.cn/problems/maximum-sum-of-distinct-subarrays-with-length-k/
滑动窗口
维护一个长度为k的窗口, 以及一个哈希表(用来记录滑动窗口内数字的是否存在)

class Solution {
public:
    long long maximumSubarraySum(vector<int>& nums, int k) {
        int st[100010];
        memset(st, 0, sizeof(st));
        
        int n = nums.size();
        long long sum = 0, res = 0;
        for(int l = 0, r = 0; r < n; r++) {
            st[nums[r]] ++;
            sum += nums[r];
            while(st[nums[r]] > 1 || r+1-l > k) {
                sum -= nums[l];
                st[nums[l]] --;
                l ++;
            }
            if(r+1-l == k){
                res = max(res, sum);
            }
        }

        return res;
    }
};

🔰🔰816.模糊坐标

https://leetcode.cn/problems/ambiguous-coordinates/

.的添加与否
对于一个数字字符串s

  • s == "0" || s[0] != "0"直接加入左/右的items序列,并return
  • s[0] != "0",直接加入左/右的items序列
  • 最后一位为0, 则return (该字符串s无法添加小数点, 否则会有多余的0,不合题意)
  • 最后一位不为0,
    • 首位为0(此时只能是0.k/0.00k[k=1...9]的形式), 将该小数字符串返回
    • 首位不为0, 则在任意两字符间添加小数点均可
class Solution {
public:
    vector<string> getItems(string s) {
        vector<string> items;
        if(s == "0") {
            items.push_back(s);
            return items;
        }
        if (s[0] != '0') items.push_back(s);
        int len = s.size();

        if(s[len-1] == '0') return items;
        if(s[0] == '0') items.push_back("0."+s.substr(1));
        else{
            for (int p = 1; p < len; ++p)
                items.push_back(s.substr(0, p) + "." + s.substr(p));
        }
        return items;
    }

    vector<string> ambiguousCoordinates(string s) {
        int n = s.size();
        s = s.substr(1, n-2);

        vector<string> res;
        for (int i = 1; i < n-2; ++i) {
            vector<string> l_items = getItems(s.substr(0, i));
            if(!l_items.size()) continue;
            vector<string> r_items = getItems(s.substr(i, n-2));
            if(!r_items.size()) continue;

            for(auto& a : l_items)
                for(auto& b : r_items) {
                    res.push_back("("+ a + ", " + b + ")");
                }
        }
        return res;
    }
};

🔰🔰(动态规划)764.最大加号标志

https://leetcode.cn/problems/largest-plus-sign/

image

class Solution {
public:
    int orderOfLargestPlusSign(int n, vector<vector<int>>& mines) {
        int res = 0;
        vector<vector<int>> g(n, vector<int>(n, n));
        for(auto t : mines) g[t[0]][t[1]] = 0;

        for(int i = 0; i < n; ++i){
            int d[4] = {0}; 
            // dir[0,1,2,3]: 从左/右/上/下开始数到当前位置连续的"1"的数量
            for(int j = 0, k = n-1; j < n; ++j,--k){
                d[0] = g[i][j] ? d[0]+1 : 0;
                d[1] = g[i][k] ? d[1]+1 : 0;
                d[2] = g[j][i] ? d[2]+1 : 0;
                d[3] = g[k][i] ? d[3]+1 : 0;
                g[i][j] = g[i][j] < d[0] ? g[i][j] : d[0];
                g[i][k] = g[i][k] < d[1] ? g[i][k] : d[1];
                g[j][i] = g[j][i] < d[2] ? g[j][i] : d[2];
                g[k][i] = g[k][i] < d[3] ? g[k][i] : d[3];
            }
        }
        for(auto t : g) {
            res = max(res, *max_element(t.begin(), t.end()));
        }
        return res;
    }
};

🔰🔰(动态规划)790.多米诺和托米诺平铺

https://leetcode.cn/problems/domino-and-tromino-tiling/
>>题解

class Solution {
public:
    int numTilings(int n) {
        int f[1010];
        int mod = 1e9+7;

        memset(f, 0, sizeof(f));
        f[1] = 1;
        f[2] = 2;
        f[3] = 5;
        for(int i = 4; i <= n; ++i) {
            f[i] = (2*f[i-1]%mod + f[i-3]%mod)%mod;
        }
        return f[n];
    }
};

🔰🔰6234.最小公倍数为 K 的子数组数目

https://leetcode.cn/problems/number-of-subarrays-with-lcm-equal-to-k/

class Solution {
public:
	int gcd(int a,int b) {
        return b ? gcd(b, a%b) : a;
    }
    int subarrayLCM(vector<int>& nums, int k) {
        int n = nums.size();

        int j;
        int cnt = 0;
        for(int i = 0; i < n; ++i) {
            if(nums[i] == k) ++cnt;
            j = i+1;
            int tmp_num = nums[i];//当前最小公倍数
            while(j < n){
                int g = gcd(tmp_num, nums[j]);
                tmp_num = (tmp_num/g) * nums[j];
                if(tmp_num == k){
                    ++cnt;
                }else if(tmp_num > k){
                    break;
                }
                ++j;
            }
        }
        return cnt;
    }
};

🔰🔰🔰(状态压缩 + 常规bfs)864.获取所有钥匙的最短路径

https://leetcode.cn/problems/shortest-path-to-get-all-keys/

是我最喜欢的走迷宫(^-^)V, 写起来就爽就完了

一道常规的BFS, 不用记录是否访问,
需要不断更新到当前坐标时的某种状态的最短路程,
使用k位二进制数(k是钥匙的数量)记录钥匙的状态, 即有无

image

class Solution {
public:
    int dist[31][31][1<<6];
    struct Room{
        int x, y, st;
    };

    int shortestPathAllKeys(vector<string>& grid) {
        int n = grid.size(), m = grid[0].size();
        int knum = 0;//钥匙数
        memset(dist, 0x3f, sizeof(dist));
        queue<Room> q;

        for(int i = 0; i < n; ++i)
            for(int j = 0; j < m; ++j) {
                if(grid[i][j] == '@') {;
                    q.push({i, j, 0});
                    dist[i][j][0] = 0;
                }else if(grid[i][j] >= 'a' && grid[i][j] <= 'f') {
                    ++knum;
                }
            }

        int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};
        int onePiece = (1 << knum) - 1; //目标状态
        while(q.size()) { //bfs
            auto t = q.front();
            q.pop();
            int d = dist[t.x][t.y][t.st];

            for(int i = 0; i < 4; ++i) {
                int nx = t.x + dx[i], ny = t.y + dy[i], ns = t.st;
                if(nx < 0 || nx >= n || ny < 0 || ny >= m || grid[nx][ny] == '#')
                    continue;

                char ch = grid[nx][ny];
                //钥匙
                if(ch >= 'a' && ch <= 'f') {
                    ns |= 1 << (ch - 'a');
                    if(ns == onePiece) return d + 1; //集齐所有钥匙, 且路程最短
                    if(dist[nx][ny][ns] > d + 1) {
                        q.push({nx, ny, ns});
                        dist[nx][ny][ns] = d + 1;
                    }
                }
                //锁
                else if(ch >= 'A' && ch <= 'F') {
                    if(ns & (1 << ch - 'A')) { //有当前锁的钥匙
                        if(dist[nx][ny][ns] > d + 1) {
                            q.push({nx, ny, ns});
                            dist[nx][ny][ns] = d + 1;
                        }
                    }
                }
                else {
                    if(dist[nx][ny][ns] > d + 1) {
                        q.push({nx, ny, ns});
                        dist[nx][ny][ns] = d + 1;
                    }
                }
            }
        }

        return -1;
    }
};

class Solution {
public:
    int dist[31][31][1<<6];
    struct Room{
        int x, y, st;
    };

    int shortestPathAllKeys(vector<string>& grid) {
        int n = grid.size(), m = grid[0].size();
        int knum = 0;//钥匙数
        memset(dist, 0x3f, sizeof(dist));
        queue<Room> q;

        for(int i = 0; i < n; ++i)
            for(int j = 0; j < m; ++j) {
                if(grid[i][j] == '@') {;
                    q.push({i, j, 0});
                    dist[i][j][0] = 0;
                }else if(grid[i][j] >= 'a' && grid[i][j] <= 'f') {
                    ++knum;
                }
            }

        int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};
        int onePiece = (1 << knum) - 1; //目标状态
        while(q.size()) { //bfs
            auto t = q.front();
            q.pop();
            int d = dist[t.x][t.y][t.st];

            for(int i = 0; i < 4; ++i) {
                int nx = t.x + dx[i], ny = t.y + dy[i], ns = t.st;
                if(nx < 0 || nx >= n || ny < 0 || ny >= m || grid[nx][ny] == '#')
                    continue;

                char ch = grid[nx][ny];
                //钥匙
                if(ch >= 'a' && ch <= 'f') {
                    ns |= 1 << (ch - 'a');
                    if(ns == onePiece) return d + 1; //集齐所有钥匙, 且路程最短
                }
                //锁
                else if(ch >= 'A' && ch <= 'F') {
                    if(!(ns & (1 << ch - 'A')))  continue;
                }
                if(dist[nx][ny][ns] > d + 1) {
                    q.push({nx, ny, ns});
                    dist[nx][ny][ns] = d + 1;
                }
            }
        }
        return -1;
    }
};

🔰🔰791.自定义字符串排序

https://leetcode.cn/problems/custom-sort-string/

typedef pair<int, char> PII;

class Solution {
public:
    string customSortString(string order, string s) {
        int n = order.size(), m = s.size();

        vector<PII> vSite;
        map<char, int> mp;
        for(int i = 0; i < n; ++i){
            mp[order[i]] = i;
        }

        string res;
        for(int i = 0; i < m; ++i){
            if(!mp[s[i]]) res += s[i];
            else vSite.push_back({mp[s[i]], s[i]});
        }
        sort(vSite.begin(), vSite.end());

        for(auto [a, b] : vSite) res += b;

        return res;
    }
};

💤🔰🔰647.回文子串

https://leetcode.cn/problems/palindromic-substrings/

💤🔰🔰🔰6236.不重叠回文子字符串的最大数目

https://leetcode.cn/problems/maximum-number-of-non-overlapping-palindrome-substrings/

🔰🔰🔰805.数组的均值分割

https://leetcode.cn/problems/split-array-with-same-average/

枚举二进制状态, 超时

class Solution {
public:
    bool splitArraySameAverage(vector<int>& nums) {
        int n = nums.size();
        int S = 0, r = (1 << n) - 1;
        for(int i = 0; i < n; ++i) S += nums[i];
        for(int i = 1; i < r; ++i) { //枚举状态
            int n1 = 0, S1 = 0;
            for(int j = 0; j < n; ++j) {
                if((i >> j) & 1) {
                    ++n1;
                    S1 += nums[j];
                }
            }
            if(n1*S == n*S1) return true;
        }

        return false;
    }
};

折半搜索 / 动态规划 进行优化

>>官方题解

折半搜索
image
image

class Solution {
public:
    bool splitArraySameAverage(vector<int>& nums) {
        int n = nums.size();
        if(n == 1) return false;

        int sr = 0, s = 0, mid = n>>1;
        for(int x : nums) s += x;
        for(int &x : nums) x = x * n - s;
        for(int i = mid; i < n; ++i) sr += nums[i];

        unordered_set<int> left;
        for(int i = 1; i < (1<<mid); ++i) { //枚举状态
            int s1 = 0;
            for(int j = 0; j < mid; ++j)
                if((i >> j) & 1)
                    s1 += nums[j];

            if(s1 == 0) return true;
            left.emplace(s1);
        }

        for(int i = 1; i < (1<<(n-mid)); ++i) {
            int s2 = 0;
            for(int j = 0; j < n-mid; ++j)
                if((i >> j) & 1)
                    s2 += nums[j+mid];

            if(s2 == 0 || (s2 != sr && left.count(-s2)))
                return true;
        }

        return false;
    }
};

💤动态规划


STL accumulate使用说明

C++ STL accumulate 使用说明

STL unorderedset emplace / find 的用法

unorderedset

🔰1710.卡车上的最大单元数

https://leetcode.cn/problems/maximum-units-on-a-truck/
简单模拟

class Solution {
public:
    int maximumUnits(vector<vector<int>>& boxTypes, int truckSize) {
        int n = boxTypes.size();
        sort(boxTypes.begin(), boxTypes.end(), 
            [&](const vector<int>& a, const vector<int>& b){ 
                return a[1] > b[1];
            });
        int i = 0, s = 0;
        while(i < n){
            int _min = min(boxTypes[i][0], truckSize);
            s += _min*boxTypes[i][1];
            truckSize -= _min;
            if(truckSize == 0) return s;
            ++i;
        }
        return s;
    }
};

🔰🔰792. 匹配子序列的单词数

https://leetcode.cn/problems/number-of-matching-subsequences/submissions/

class Solution {
public:
    int numMatchingSubseq(string s, vector<string>& words) {
        vector<queue<string>> str(26);
        int n = s.size(), m = words.size();
        for(int i = 0; i < m; ++i) str[words[i][0]-'a'].emplace(words[i]);

        int ans = 0;
        for(int i = 0; i < n; ++i) {
            queue<string>& q = str[s[i]-'a'];
            for(int j = q.size(); j; --j) {
                string t = q.front();
                q.pop();
                if(t.size() == 1) ++ans;
                else str[t[1]-'a'].emplace(t.substr(1));
            }
        }
        return ans;
    }
};

🔰🔰🔰891.子序列宽度之和

https://leetcode.cn/problems/sum-of-subsequence-widths/

0x3f 的题解
image
image

class Solution {
public:
    const int MOD = 1e9+7;
    int sumSubseqWidths(vector<int>& nums) {
        int n = nums.size();
        long long res = 0L, a[n];
        sort(nums.begin(), nums.end());
        a[0] = 1;
        for(int i = 1; i < n; ++i){
            a[i] = (a[i-1]*2)%MOD;
        }
        for(int i = 0; i < n; ++i) {
            res += (a[i] - a[n-1-i]) * nums[i] % MOD;
        }
        return (res%MOD+MOD)%MOD;
    }

    // long long pow(int x, int n){
    //     long long res = 1L;
    //     while(n)
    //     {
    //         if(n & 1) res = (res*x)%MOD;
    //         x = (x*x)%MOD;
    //         n >>= 1;
    //     }
    //     return res;
    // }
};

🔰🔰799.香槟塔

https://leetcode.cn/problems/champagne-tower/

class Solution {
public:
    double champagneTower(int v, int n, int m) {
        double h[110][110];
        memset(h, 0, sizeof(h));
        h[0][0] = v;
        for(int i = 0; i <= n; ++i) {
            for(int j = 0; j <= i; ++j) {
                if(h[i][j] < 1) continue;
                h[i+1][j] += (h[i][j] - 1)/2;
                h[i+1][j+1] += (h[i][j] - 1)/2;
            }
        }
        return h[n][m] < 1 ? h[n][m] : 1;
    }
};

🔰🔰6242.二叉搜索树最近节点查询

https://leetcode.cn/problems/closest-nodes-queries-in-a-binary-search-tree/

先得到中序遍历的序列, 再二分

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    void mid_build(TreeNode* root, vector<int>& a) {
        if(!root) return ;
        mid_build(root->left, a);
        a.push_back(root->val);
        mid_build(root->right, a);
    }
    
    // 大于等于当前数的最小值
    int find_left(vector<int>& a, int l, int r, int x) {
        int ll = l, rr = r;
        while(ll < rr) {
            int mid = (ll + rr) >> 1;
            if(x <= a[mid]) rr = mid;
            else ll = mid + 1;
        }
        return a[ll] >= x ? a[ll] : -1;
    }
    
    // 小于等于当前数的最大值
    int find_right(vector<int>& a, int l, int r, int x) {
        int ll = l, rr = r;
        while(ll < rr) {
            int mid = (ll + rr + 1) >> 1;
            if(x < a[mid]) rr = mid - 1;
            else ll = mid;
        }
        return a[rr] <= x ? a[rr] : -1;
    }
    
    vector<vector<int>> closestNodes(TreeNode* root, vector<int>& queries) {
        vector<int> a;
        mid_build(root, a);
        
        vector<vector<int>> res;
        for(auto x : queries) {
            int l = find_left(a, 0, a.size()-1, x);
            int r = find_right(a, 0, a.size()-1, x);
            res.push_back({r, l});
        }
        
        return res;
    }
};
posted @ 2022-11-20 20:43  泥烟  阅读(71)  评论(0编辑  收藏  举报