当前位置:首页 > 技术 > 正文内容

LeetCode 算法题解精编(题号 1601 至 2000)

访客 技术 2026年8月22日 1

目录

  • 1602. 二叉树中最近的右侧节点
  • 1611. 整数归零的最少操作步数
  • 1612. 二叉表达式树等价判定
  • 1621. K 条不重叠线段的计数
  • 1625. 旋转与累加后的字典序最小字符串
  • 1631. 路径最小体力消耗
  • 1632. 矩阵秩变换
  • 1634. 多项式链表求和
  • 1641. 字典序元音字符串计数
  • 1643. 第 K 小的指令序列
  • 1644. 带父指针的二叉树最近公共祖先
  • 1650. 带子节点指针的二叉树最近公共祖先
  • 1652. 炸弹解密
  • 1653. 字符串平衡的最小删除量
  • 1657. 字符串接近性判定
  • 1658. 将 x 归零的最少操作
  • 1662. 字符串数组等价检查
  • 1663. 给定数值的最小字典序字符串
  • 1664. 平衡数组方案数
  • 1666. 二叉树换根
  • 1668. 最大重复子串
  • 1669. 链表区间合并
  • 1673. 最具竞争力的子序列
  • 1676. 多节点二叉树最近公共祖先
  • 1680. 连续二进制拼接
  • 1682. 回文子序列计数 II
  • 1684. 一致字符串计数
  • 1686. 石子游戏 VI
  • 1690. 石子游戏 VII
  • 1696. 跳跃游戏 VI
  • 1697. 边长限制下的路径可达性
  • 1700. 无法吃午餐的学生数
  • 1702. 修改后的最大二进制串
  • 1704. 字符串两半相似性
  • 1705. 最多吃掉的苹果数
  • 1724. 边长限制下的路径可达性 II
  • 1732. 最高海拔
  • 1735. 乘积数组方案数
  • 1738. 第 K 大异或坐标值
  • 1740. 二叉树中两节点距离
  • 1742. 盒中小球的最大数量
  • 1752. 数组排序与轮转检查
  • 1753. 移除石子的最大得分
  • 1766. 互质树
  • 1768. 交替合并字符串
  • 1773. 按规则匹配的物品计数
  • 1780. 三的幂和表示判定
  • 1785. 达到目标和的最少元素
  • 1793. 好子数组的最大分数
  • 1796. 字符串中第二大的数字
  • 1799. N 次操作后的最大得分
  • 1801. 积压订单总数
  • 1802. 有界数组指定下标最大值
  • 1803. 异或值在范围内的数对计数
  • 1804. 前缀树实现 II
  • 1805. 字符串中不同整数计数
  • 1806. 还原排列的最少步数
  • 1807. 替换字符串中的括号内容
  • 1808. 好因子的最大数目
  • 1812. 棋盘格子颜色判定
  • 1813. 句子相似性 III
  • 1814. 好对子计数
  • 1815. 新鲜甜甜圈最多组数
  • 1817. 用户活跃分钟数
  • 1819. 序列中不同最大公约数计数
  • 1822. 数组元素积的符号
  • 1823. 游戏获胜者
  • 1824. 最少侧跳次数
  • 1825. MK 平均值
  • 1827. 数组递增的最少操作
  • 1828. 圆内点计数
  • 1830. 字符串有序的最少操作
  • 1835. 所有数对按位与的异或和
  • 1848. 目标元素最小距离
  • 1852. 子数组数字种类数
  • 1862. 向下取整的数对和
  • 1863. 子集异或总和求和
  • 1866. 恰好 K 根木棍可见的排列数
  • 1872. 石子游戏 VIII
  • 1874. 两数组最小乘积和
  • 1883. 准时到达的最小跳过休息次数
  • 1884. 两枚鸡蛋掉落
  • 1885. 数对统计
  • 1901. 二维峰值查找
  • 1902. 由插入顺序求二叉搜索树深度
  • 1908. Nim 游戏 II
  • 1911. 最大交替子序列和
  • 1916. 蚁群筑房顺序统计
  • 1922. 好数字计数
  • 1927. 求和博弈
  • 1944. 队列中可见人数
  • 1953. 最大工作周数
  • 1954. 收集足够苹果的最小周长
  • 1969. 最小非零乘积
  • 1971. 图中路径存在性
  • 1973. 值等于子节点和的节点
  • 1976. 到达目的地方案数
  • 1979. 数组最大公约数
  • 1982. 从子集和还原数组
  • 1985. 数组中第 K 大整数
  • 1989. 捉迷藏可捕获最大人数
  • 1992. 农场组查找
  • 1997. 访问完所有房间的第一天
  • 1998. 数组最大公因数排序
  • 1999. 仅由两个数字组成的最小倍数

1602. 二叉树中最近的右侧节点

标签:二叉树

1611. 整数归零的最少操作步数

标签:九连环

1612. 二叉表达式树等价判定

标签:二叉树

1621. K 条不重叠线段的计数

标签:组合数学

1625. 旋转与累加后的字典序最小字符串

给定一个偶数长度、仅含数字 0-9 的字符串 s,以及两个整数 ab。允许执行以下两种操作任意次:

  • 累加操作:将 a 加到所有奇数下标(0-based)的数字上,超过 9 则取模 10。
  • 轮转操作:将字符串向右轮转 b 位。

求能得到的字典序最小的字符串。

示例:

输入:s = "5525", a = 9, b = 2
输出:"2050"
输入:s = "74", a = 5, b = 1
输出:"24"
输入:s = "0011", a = 4, b = 2
输出:"0011"

采用 BFS 遍历所有可达状态,记录已访问字符串防止重复:

class Solution {
public:
    string findLexSmallestString(string s, int a, int b) {
        queue<string> bfsQueue;
        unordered_set<string> seen;
        bfsQueue.push(s);
        seen.insert(s);
        string best = s;
        
        while (!bfsQueue.empty()) {
            string cur = bfsQueue.front();
            bfsQueue.pop();
            if (cur < best) best = cur;
            
            // 累加操作
            string nxt = cur;
            for (int i = 1; i < (int)nxt.size(); i += 2) {
                nxt[i] = (nxt[i] - '0' + a) % 10 + '0';
            }
            if (seen.find(nxt) == seen.end()) {
                seen.insert(nxt);
                bfsQueue.push(nxt);
            }
            
            // 轮转操作
            int n = cur.size();
            string rot = cur.substr(n - b) + cur.substr(0, n - b);
            if (seen.find(rot) == seen.end()) {
                seen.insert(rot);
                bfsQueue.push(rot);
            }
        }
        return best;
    }
};

1631. 路径最小体力消耗

标签:广度优先搜索

1632. 矩阵秩变换

标签:并查集

1634. 多项式链表求和

标签:单链表

1641. 字典序元音字符串计数

标签:组合数学

1643. 第 K 小的指令序列

标签:全排列

1644. 带父指针的二叉树最近公共祖先

标签:最近公共祖先

1650. 带子节点指针的二叉树最近公共祖先

标签:最近公共祖先

1652. 炸弹解密

标签:循环数组

1653. 字符串平衡的最小删除量

给定仅含字符 'a''b' 的字符串 s。平衡的定义:不存在 i < j 使得 s[i]='b's[j]='a'。返回使字符串平衡的最少删除次数。

示例:

输入:s = "aababbab"
输出:2
输入:s = "bbaaaaabb"
输出:2

使用前缀统计 'b' 数量和后缀统计 'a' 数量,枚举分割点:

class Solution {
public:
    int minimumDeletions(string s) {
        int n = s.size();
        vector<int> bBefore(n + 1, 0);
        vector<int> aAfter(n + 1, 0);
        
        for (int i = 0; i < n; i++)
            bBefore[i + 1] = bBefore[i] + (s[i] == 'b');
        for (int i = n - 1; i >= 0; i--)
            aAfter[i] = aAfter[i + 1] + (s[i] == 'a');
        
        int minCost = n;
        for (int i = 0; i <= n; i++)
            minCost = min(minCost, bBefore[i] + aAfter[i]);
        return minCost;
    }
};

1657. 字符串接近性判定

两种操作可将一个字符串变换为另一个:(1) 交换任意两个现有字符的位置;(2) 将某字符的全部出现与另一现有字符的全部出现互换。判断 word1word2 是否接近。

示例:

输入:word1 = "abc", word2 = "bca"
输出:true
输入:word1 = "a", word2 = "aa"
输出:false
输入:word1 = "cabbba", word2 = "abbccc"
输出:true

核心条件:两字符串长度相等、出现的字符集相同、频率的多重集相同。

class Solution {
public:
    bool closeStrings(string w1, string w2) {
        if (w1.size() != w2.size()) return false;
        int cnt1[26] = {0}, cnt2[26] = {0};
        for (char c : w1) cnt1[c - 'a']++;
        for (char c : w2) cnt2[c - 'a']++;
        
        for (int i = 0; i < 26; i++)
            if ((cnt1[i] > 0) != (cnt2[i] > 0)) return false;
        
        sort(cnt1, cnt1 + 26);
        sort(cnt2, cnt2 + 26);
        for (int i = 0; i < 26; i++)
            if (cnt1[i] != cnt2[i]) return false;
        return true;
    }
};

1658. 将 x 归零的最少操作

标签:搜索

1662. 字符串数组等价检查

标签:基础题

1663. 给定数值的最小字典序字符串

标签:基础题

1664. 平衡数组方案数

标签:基础题

1666. 二叉树换根

标签:二叉树

1668. 最大重复子串

标签:KMP 算法

1669. 链表区间合并

标签:链表

1673. 最具竞争力的子序列

标签:单调栈

1676. 多节点二叉树最近公共祖先

标签:最近公共祖先

1680. 连续二进制拼接

标签:位运算

1682. 回文子序列计数 II

标签:高维动态规划

1684. 一致字符串计数

标签:基础题

1686. 石子游戏 VI

标签:博弈论

1690. 石子游戏 VII

标签:博弈论

1696. 跳跃游戏 VI

标签:数列动态规划

1697. 边长限制下的路径可达性

标签:并查集

1700. 无法吃午餐的学生数

标签:队列模拟

1702. 修改后的最大二进制串

给定仅含 '0''1' 的二进制串,允许以下操作:(1) 将子串 "00" 替换为 "10";(2) 将子串 "10" 替换为 "01"。求能得到的最大二进制串。

示例:

输入:binary = "000110"
输出:"111011"
输入:binary = "01"
输出:"01"

关键观察:所有零最终可汇聚为一个零,其位置由首个零之后的 1 的数量决定。该零应放在首个零后连续 1 的末尾处。

class Solution {
public:
    string maximumBinaryString(string binary) {
        int len = binary.size();
        int onesAfterFirstZero = 0;
        bool hasZero = false;
        
        for (char ch : binary) {
            if (ch == '0') hasZero = true;
            else if (hasZero) onesAfterFirstZero++;
        }
        
        if (!hasZero) return binary;
        
        string result(len, '1');
        result[len - 1 - onesAfterFirstZero] = '0';
        return result;
    }
};

1704. 字符串两半相似性

标签:基础题

1705. 最多吃掉的苹果数

标签:优先队列

1724. 边长限制下的路径可达性 II

标签:并查集

1732. 最高海拔

标签:基础题

1735. 乘积数组方案数

标签:组合数学

1738. 第 K 大异或坐标值

给定 m×n 非负整数矩阵,坐标 (r,c) 的值为左上角子矩阵所有元素的异或。求所有坐标值中第 K 大的值。

示例:

输入:matrix = [[5,2],[1,6]], k = 1
输出:7
输入:matrix = [[5,2],[1,6]], k = 2
输出:5

利用二维异或前缀和,然后用 nth_element 快速选择第 K 大:

class Solution {
public:
    int kthLargestValue(vector<vector<int>>& mat, int k) {
        int rows = mat.size(), cols = mat[0].size();
        vector<int> xors;
        xors.reserve(rows * cols);
        
        for (int r = 0; r < rows; r++) {
            for (int c = 0; c < cols; c++) {
                if (r > 0) mat[r][c] ^= mat[r - 1][c];
                if (c > 0) mat[r][c] ^= mat[r][c - 1];
                if (r > 0 && c > 0) mat[r][c] ^= mat[r - 1][c - 1];
                xors.push_back(mat[r][c]);
            }
        }
        
        nth_element(xors.begin(), xors.begin() + k - 1, xors.end(), greater<int>());
        return xors[k - 1];
    }
};

1740. 二叉树中两节点距离

标签:二叉树

1742. 盒中小球的最大数量

标签:基础题

1752. 数组排序与轮转检查

标签:基础题

1753. 移除石子的最大得分

有三堆石子,大小分别为 abc。每回合从两个不同的非空堆各取一颗石子得 1 分,当有两个或更多空堆时停止。求最大分数。

示例:

输入:a = 2, b = 4, c = 6
输出:6
输入:a = 4, b = 4, c = 6
输出:7
输入:a = 1, b = 8, c = 8
输出:8

若最大堆 ≥ 其余两堆之和,则答案为两小堆之和;否则答案为总数的一半(向下取整)。

class Solution {
public:
    int maximumScore(int a, int b, int c) {
        vector<int> piles = {a, b, c};
        sort(piles.begin(), piles.end());
        int biggest = piles[2];
        int rest = piles[0] + piles[1];
        if (biggest >= rest) return rest;
        return (a + b + c) / 2;
    }
};

1766. 互质树

标签:动态规划

1768. 交替合并字符串

标签:基础题

1773. 按规则匹配的物品计数

每件物品有类型、颜色、名称三个属性。给定规则键 ruleKey 和规则值 ruleValue,统计匹配的物品数。

示例:

输入:items = [["phone","blue","pixel"],["computer","silver","lenovo"],["phone","gold","iphone"]], ruleKey = "color", ruleValue = "silver"
输出:1
输入:items = [["phone","blue","pixel"],["computer","silver","phone"],["phone","gold","iphone"]], ruleKey = "type", ruleValue = "phone"
输出:2
class Solution {
public:
    int countMatches(vector<vector<string>>& items, string ruleKey, string ruleValue) {
        int col = (ruleKey == "type") ? 0 : (ruleKey == "color") ? 1 : 2;
        int cnt = 0;
        for (const auto& item : items)
            if (item[col] == ruleValue) cnt++;
        return cnt;
    }
};

1780. 三的幂和表示判定

标签:数论

1785. 达到目标和的最少元素

给定数组 nums、上限 limit 和目标 goal,每个元素绝对值不超过 limit。求最少需要添加多少个绝对值不超过 limit 的元素使总和等于 goal

示例:

输入:nums = [1,-1,1], limit = 3, goal = -4
输出:2
输入:nums = [1,-10,9,1], limit = 100, goal = 0
输出:1
class Solution {
public:
    int minElements(vector<int>& nums, int limit, int goal) {
        long long total = 0;
        for (int x : nums) total += x;
        long long diff = abs(total - goal);
        return (diff + limit - 1) / limit;
    }
};

1793. 好子数组的最大分数

标签:双指针

1796. 字符串中第二大的数字

标签:基础题

1799. N 次操作后的最大得分

标签:状态压缩动态规划

1801. 积压订单总数

订单数组 orders[i] = [price, amount, type],type=0 为采购、type=1 为销售。采购单与积压中最低价销售单匹配(采购价 ≥ 销售价),反之同理。返回最终积压订单总数对 1e9+7 取余。

示例:

输入:orders = [[10,5,0],[15,2,1],[25,1,1],[30,4,0]]
输出:6
输入:orders = [[7,1000000000,1],[15,3,0],[5,999999995,0],[5,1,1]]
输出:999999984

使用两个有序映射分别维护采购和销售积压:

class Solution {
public:
    int getNumberOfBacklogOrders(vector<vector<int>>& orders) {
        const int MOD = 1e9 + 7;
        long long total = 0;
        map<int, long long> buys, sells;
        
        for (auto& o : orders) {
            int price = o[0], amt = o[1], type = o[2];
            total += amt;
            
            if (type == 0) {
                while (amt > 0 && !sells.empty() && sells.begin()->first <= price) {
                    auto it = sells.begin();
                    long long matched = min((long long)amt, it->second);
                    amt -= matched;
                    it->second -= matched;
                    total -= 2 * matched;
                    if (it->second == 0) sells.erase(it);
                }
                if (amt > 0) buys[price] += amt;
            } else {
                while (amt > 0 && !buys.empty() && buys.rbegin()->first >= price) {
                    auto it = prev(buys.end());
                    long long matched = min((long long)amt, it->second);
                    amt -= matched;
                    it->second -= matched;
                    total -= 2 * matched;
                    if (it->second == 0) buys.erase(it);
                }
                if (amt > 0) sells[price] += amt;
            }
        }
        return ((total % MOD) + MOD) % MOD;
    }
};

1802. 有界数组指定下标最大值

标签:二分查找

1803. 异或值在范围内的数对计数

标签:字典树

1804. 前缀树实现 II

标签:前缀树

1805. 字符串中不同整数计数

标签:基础题

1806. 还原排列的最少步数

标签:群论

1807. 替换字符串中的括号内容

标签:基础题

1808. 好因子的最大数目

标签:调整法

1812. 棋盘格子颜色判定

给定国际象棋棋盘坐标(如 "a1"),白色返回 true,黑色返回 false

国际象棋棋盘

示例:

输入:coordinates = "a1"
输出:false
输入:coordinates = "h3"
输出:true
class Solution {
public:
    bool squareIsWhite(string coord) {
        int col = coord[0] - 'a';
        int row = coord[1] - '1';
        return (col + row) % 2 == 1;
    }
};

1813. 句子相似性 III

标签:基础题

1814. 好对子计数

标签:基础题

1815. 新鲜甜甜圈最多组数

标签:模拟退火

1817. 用户活跃分钟数

给定用户操作日志 logs[i] = [ID, time],用户活跃分钟数 UAM 为该用户执行操作的不同分钟数。统计 UAM 分布:answer[j] 表示 UAM 等于 j 的用户数。

示例:

输入:logs = [[0,5],[1,2],[0,2],[0,5],[1,3]], k = 5
输出:[0,2,0,0,0]
输入:logs = [[1,1],[2,2],[2,3]], k = 4
输出:[1,1,0,0]
class Solution {
public:
    vector<int> findingUsersActiveMinutes(vector<vector<int>>& logs, int k) {
        unordered_map<int, unordered_set<int>> userTimes;
        for (auto& log : logs)
            userTimes[log[0]].insert(log[1]);
        
        vector<int> result(k, 0);
        for (auto& [uid, times] : userTimes) {
            int uam = times.size();
            if (uam >= 1 && uam <= k)
                result[uam - 1]++;
        }
        return result;
    }
};

1819. 序列中不同最大公约数计数

标签:欧几里得算法

1822. 数组元素积的符号

定义 signFunc(x):正数返回 1,负数返回 -1,零返回 0。求数组所有元素乘积的符号函数值。

示例:

输入:nums = [-1,-2,-3,-4,3,2,1]
输出:1
输入:nums = [1,5,0,2,-3]
输出:0
输入:nums = [-1,1,-1,1,-1]
输出:-1
class Solution {
public:
    int arraySign(vector<int>& nums) {
        int negCount = 0;
        for (int x : nums) {
            if (x == 0) return 0;
            if (x < 0) negCount++;
        }
        return (negCount % 2 == 0) ? 1 : -1;
    }
};

1823. 游戏获胜者

标签:约瑟夫问题

1824. 最少侧跳次数

3 跑道道路上青蛙从第 2 跑道出发,每个点最多一个障碍。青蛙可沿跑道前进或侧跳到无障碍的跑道。求到达终点的最少侧跳次数。

示例:

输入:obstacles = [0,1,2,3,0]
输出:2
输入:obstacles = [0,1,1,3,3,0]
输出:0
输入:obstacles = [0,2,1,0,3,0]
输出:2

动态规划:dp[lane] 表示到达当前位置各跑道的最少侧跳次数,逐点转移。

class Solution {
public:
    int minSideJumps(vector<int>& obstacles) {
        int n = obstacles.size();
        vector<int> dp = {1, 0, 1}; // lane 0,1,2
        
        for (int i = 1; i < n; i++) {
            for (int lane = 0; lane < 3; lane++) {
                if (obstacles[i] == lane + 1) dp[lane] = INT_MAX;
            }
            for (int lane = 0; lane < 3; lane++) {
                if (obstacles[i] == lane + 1) continue;
                for (int other = 0; other < 3; other++) {
                    if (obstacles[i] == other + 1) continue;
                    dp[lane] = min(dp[lane], dp[other] + 1);
                }
            }
        }
        return min(dp[0], min(dp[1], dp[2]));
    }
};

1825. MK 平均值

维护数据流,计算最后 m 个元素去掉最小 k 个和最大 k 个后的平均值(向下取整)。

示例:

输入:["MKAverage","addElement","addElement","calculateMKAverage","addElement","calculateMKAverage","addElement","addElement","addElement","calculateMKAverage"]
     [[3,1],[3],[1],[],[10],[],[5],[5],[5],[]]
输出:[null,null,null,-1,null,3,null,null,null,5]

使用三个 multiset 分别维护最小 k 个、中间 m-2k 个、最大 k 个元素,配合队列维护滑动窗口。

class MKAverage {
    int windowSize, trimCount;
    queue<int> dataQueue;
    multiset<int> lower, middle, upper;
    long long middleSum = 0;

public:
    MKAverage(int m, int k) : windowSize(m), trimCount(k) {}

    void addElement(int num) {
        if ((int)dataQueue.size() < windowSize - 1) {
            dataQueue.push(num);
            return;
        }
        if ((int)dataQueue.size() == windowSize - 1) {
            dataQueue.push(num);
            vector<int> tmp;
            queue<int> cq = dataQueue;
            while (!cq.empty()) { tmp.push_back(cq.front()); cq.pop(); }
            sort(tmp.begin(), tmp.end());
            for (int i = 0; i < trimCount; i++) lower.insert(tmp[i]);
            for (int i = trimCount; i < windowSize - trimCount; i++) {
                middle.insert(tmp[i]);
                middleSum += tmp[i];
            }
            for (int i = windowSize - trimCount; i < windowSize; i++) upper.insert(tmp[i]);
            return;
        }
        int oldest = dataQueue.front();
        dataQueue.pop();
        removeVal(oldest);
        dataQueue.push(num);
        insertVal(num);
    }

    int calculateMKAverage() {
        if ((int)dataQueue.size() < windowSize) return -1;
        return middleSum / (windowSize - 2 * trimCount);
    }

private:
    void removeVal(int v) {
        int origin;
        if (v < *middle.begin()) { lower.erase(lower.find(v)); origin = 1; }
        else if (v < *upper.begin()) { middle.erase(middle.find(v)); middleSum -= v; origin = 2; }
        else { upper.erase(upper.find(v)); origin = 3; }
        if (origin <= 2) {
            int x = *upper.begin();
            middle.insert(x); middleSum += x;
            upper.erase(upper.begin());
        }
        if (origin <= 1) {
            int x = *middle.begin();
            lower.insert(x); middleSum -= x;
            middle.erase(middle.begin());
        }
    }

    void insertVal(int v) {
        lower.insert(v);
        int x = *lower.rbegin();
        middle.insert(x); middleSum += x;
        lower.erase(prev(lower.end()));
        x = *middle.rbegin();
        upper.insert(x); middleSum -= x;
        middle.erase(prev(middle.end()));
    }
};

1827. 数组递增的最少操作

每次操作可将一个元素加 1,求使数组严格递增的最少操作次数。

示例:

输入:nums = [1,1,1]
输出:3
输入:nums = [1,5,2,4,1]
输出:14
输入:nums = [8]
输出:0
class Solution {
public:
    int minOperations(vector<int>& nums) {
        int ops = 0;
        for (int i = 1; i < (int)nums.size(); i++) {
            if (nums[i] <= nums[i - 1]) {
                int diff = nums[i - 1] - nums[i] + 1;
                ops += diff;
                nums[i] += diff;
            }
        }
        return ops;
    }
};

1828. 圆内点计数

标签:基础题

1830. 字符串有序的最少操作

标签:字典序排列

1835. 所有数对按位与的异或和

标签:贡献法

1848. 目标元素最小距离

给定数组 nums、目标值 target 和起始下标 start,找满足 nums[i] == targetabs(i - start) 最小的下标,返回该绝对值。

示例:

输入:nums = [1,2,3,4,5], target = 5, start = 3
输出:1
输入:nums = [1], target = 1, start = 0
输出:0
输入:nums = [1,1,1,1,1,1,1,1,1,1], target = 1, start = 0
输出:0
class Solution {
public:
    int getMinDistance(vector<int>& nums, int target, int start) {
        int best = INT_MAX;
        for (int i = 0; i < (int)nums.size(); i++) {
            if (nums[i] == target)
                best = min(best, abs(i - start));
        }
        return best;
    }
};

1852. 子数组数字种类数

给定数组 nums 和窗口长度 k,求每个长度为 k 的子数组中不同数字的个数。

示例:

输入:nums = [1,2,3,2,2,1,3], k = 3
输出:[3,2,2,2,3]
输入:nums = [1,1,1,1,2,3,4], k = 4
输出:[1,2,3,4]

滑动窗口配合哈希表统计频次:

class Solution {
public:
    vector<int> distinctNumbers(vector<int>& nums, int k) {
        unordered_map<int, int> freq;
        int distinct = 0;
        vector<int> result;
        
        for (int i = 0; i < (int)nums.size(); i++) {
            if (freq[nums[i]] == 0) distinct++;
            freq[nums[i]]++;
            
            if (i >= k) {
                freq[nums[i - k]]--;
                if (freq[nums[i - k]] == 0) distinct--;
            }
            if (i >= k - 1) result.push_back(distinct);
        }
        return result;
    }
};

1861. 旋转盒子

标签:双指针

1862. 向下取整的数对和

标签:数论

1863. 子集异或总和求和

标签:贡献法

1866. 恰好 K 根木棍可见的排列数

标签:组合数学

1871. 跳跃游戏 VII

标签:广度优先搜索

1872. 石子游戏 VIII

标签:博弈论

1874. 两数组最小乘积和

给定两个等长数组 nums1nums2,可任意重排 nums1,求最小乘积和。

示例:

输入:nums1 = [5,3,4,2], nums2 = [4,2,2,5]
输出:40
输入:nums1 = [2,1,4,5,7], nums2 = [3,2,4,8,6]
输出:65

排序后交叉配对(升序 × 降序)可得最小乘积和。

class Solution {
public:
    int minProductSum(vector<int>& nums1, vector<int>& nums2) {
        sort(nums1.begin(), nums1.end());
        sort(nums2.rbegin(), nums2.rend());
        int total = 0;
        for (int i = 0; i < (int)nums1.size(); i++)
            total += nums1[i] * nums2[i];
        return total;
    }
};

1883. 准时到达的最小跳过休息次数

标签:二维动态规划

1884. 两枚鸡蛋掉落

标签:决策优化

1885. 数对统计

标签:双指针

1901. 二维峰值查找

标签:二分查找

1902. 由插入顺序求二叉搜索树深度

标签:平衡搜索树

1908. Nim 游戏 II

标签:博弈论

1911. 最大交替子序列和

标签:数列动态规划

1916. 蚁群筑房顺序统计

标签:组合数学

1922. 好数字计数

标签:快速幂

1927. 求和博弈

标签:博弈论

1944. 队列中可见人数

标签:单调栈

1953. 最大工作周数

标签:贪心算法

1954. 收集足够苹果的最小周长

标签:基础题

1969. 最小非零乘积

标签:快速幂

1971. 图中路径存在性

标签:广度优先搜索

1973. 值等于子节点和的节点

标签:二叉树

1976. 到达目的地方案数

标签:最短路径

1979. 数组最大公约数

标签:欧几里得算法

1982. 从子集和还原数组

标签:组合问题

1985. 数组中第 K 大整数

给定字符串数组 nums,每个字符串表示一个无前导零的非负整数,返回第 K 大的整数字符串。重复数字视为不同元素。

示例:

输入:nums = ["3","6","7","10"], k = 4
输出:"3"
输入:nums = ["2","21","12","1"], k = 3
输出:"2"
输入:nums = ["0","0"], k = 2
输出:"0"

按字符串长度为第一关键字、字典序为第二关键字排序:

class Solution {
public:
    string kthLargestNumber(vector<string>& nums, int k) {
        auto cmp = [](const string& a, const string& b) {
            if (a.size() != b.size()) return a.size() < b.size();
            return a < b;
        };
        sort(nums.begin(), nums.end(), cmp);
        return nums[nums.size() - k];
    }
};

1989. 捉迷藏可捕获最大人数

标签:多指针

1992. 农场组查找

标签:并查集

1997. 访问完所有房间的第一天

标签:数列动态规划

1998. 数组最大公因数排序

标签:因式分解

1999. 仅由两个数字组成的最小倍数

给定整数 k 和两个数字 digit1digit2,求大于 k 且仅由这两个数字组成的 k 的最小倍数。若不存在或超出 32 位整数范围返回 -1。

示例:

输入:k = 2, digit1 = 0, digit2 = 2
输出:20
输入:k = 3, digit1 = 4, digit2 = 2
输出:24
输入:k = 2, digit1 = 0, digit2 = 0
输出:-1

使用 BFS 按数字位数递增顺序搜索,优先尝试较小的数字:

class Solution {
public:
    int findInteger(int k, int d1, int d2) {
        if (d1 > d2) swap(d1, d2);
        queue<long long> q;
        q.push(0);
        
        while (!q.empty()) {
            long long cur = q.front();
            q.pop();
            
            for (int d : {d1, d2}) {
                long long nxt = cur * 10 + d;
                if (nxt > INT_MAX) continue;
                if (nxt == 0) continue;
                if (nxt > k && nxt % k == 0) return (int)nxt;
                q.push(nxt);
            }
        }
        return -1;
    }
};
标签: LeetCodeC++

相关文章

Linux crontab 详解

1) crontab 是什么cron 是 Linux 的定时任务守护进程;crontab 是用来编辑/查看“按时间周期执行命令”的表(cron table)。常见两类:用户 crontab:每个用户一份(crontab -e 编辑)系统级 crontab / cron.d:可指定执行用户(/etc/crontab、/etc/cron.d/*)2) crontab 时间...

富文本里可以允许的 HTML 属性

一、所有标签默认允许的安全属性(极少)class        (可选)id           (通常建议禁用)title️ 注意:id 容易被滥用做锚点注入,很多系统直接禁用class 允许的话最好只允许固定前缀(如 editor-*)二、a 标签允许属性<a href="" t...

Mac 安装 Node.js 指南

方法一:通过官网安装包(最简单,适合初学者)如果你只是想快速安装并开始使用,这是最直接的方法。访问 Node.js 官网。页面会显示两个版本:LTS (Recommended For Most Users):长期支持版,最稳定。建议选这个。Current:最新特性版,包含最新功能但可能不够稳定。下载 .pkg 安装包并运行。按照安装向导点击“下一步”即可完成。方法二:使用 Homebrew 安装(...

Dom\HTML_NO_DEFAULT_NS 的副作用:自动加闭合标签

在使用Dom\HTMLDocument时,Dom\HTML_NO_DEFAULT_NS 将禁止在解析过程中设置元素的命名空间, 此设置是为了与DOMDocument向后兼容而存在的。当使用它时,已知的一个副作用就是:自动加闭合标签例如 </img> 为什么会这样?当你使用:Dom\HTML_NO_DEFAULT_NS文档会变成 无命名空间模式,此时内部更接近 XML...

Laravel 事件和监听器创建

在 Laravel 中,使用 Artisan 命令创建 Events(事件) 和 Listeners(监听器) 是非常高效的。你可以通过以下几种方式来实现:1. 手动创建单个 Event如果你只想创建一个事件类,可以使用 make:event 命令:Bashphp artisan make:event UserRegistered执行后,文件将生成在 app/Even...

自定义域名解析神器 dnsmasq

什么是 dnsmasq?dnsmasq 是一个轻量级、功能强大的网络服务工具,专为小型和中等规模网络设计。它是一个综合的网络基础设施解决方案[1]。dnsmasq 能做什么?功能说明应用场景DNS 转发与缓存将 DNS 查询转发到上游服务器(ISP、Google DNS 等),并在本地缓存结果加快 DNS 查询速度,减少外部 DNS 流量本地 DNS解析本地网络设备的主机名,无需编辑&n...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。