力扣OJ(1601-2000)

目录

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

1611. 使整数变为 0 的最少操作次数

1612. 检查两棵二叉表达式树是否等价

1621. 大小为 K 的不重叠线段的数目

1631. 最小体力消耗路径

1632. 矩阵转换后的秩

1634. 求两个多项式链表的和

1641. 统计字典序元音字符串的数目

1643. 第 K 条最小指令

1644. 二叉树的最近公共祖先 II

1650. 二叉树的最近公共祖先 III

1657. 确定两个字符串是否接近

1658. 将 x 减到 0 的最小操作数

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

1663. 具有给定数值的最小字符串

1664. 生成平衡数组的方案数

1666. 改变二叉树的根节点

1668. 最大重复子字符串

1669. 合并两个链表

1676. 二叉树的最近公共祖先 IV

1682. 最长回文子序列 II

1684. 统计一致字符串的数目

1686. 石子游戏 VI

1690. 石子游戏 VII

1696. 跳跃游戏 VI

1697. 检查边长度限制的路径是否存在

1700. 无法吃午餐的学生数量

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

1704. 判断字符串的两半是否相似

1724. 检查边长度限制的路径是否存在 II

1732. 找到最高海拔

1735. 生成乘积数组的方案数

1740. 找到二叉树中的距离

1742. 盒子中小球的最大数量

1752. 检查数组是否经排序和轮转得到

1753. 移除石子的最大得分

1766. 互质树

1768. 交替合并字符串

1773. 统计匹配检索规则的物品数量

1780. 判断一个数字是否可以表示成三的幂的和

1785. 构成特定和需要添加的最少元素

1793. 好子数组的最大分数

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

1799. N 次操作后的最大分数和

1801. 积压订单中的订单总数

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

1803. 统计异或值在范围内的数对有多少

1804. 实现 Trie (前缀树) II

1805. 字符串中不同整数的数目

1806. 还原排列的最少操作步数

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

1808. 好因子的最大数目

1812. 判断国际象棋棋盘中一个格子的颜色

1813. 句子相似性 III

1814. 统计一个数组中好对子的数目

1815. 得到新鲜甜甜圈的最多组数

1817. 查找用户活跃分钟数

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

1822. 数组元素积的符号

1823. 找出游戏的获胜者

1824. 最少侧跳次数(DP)

1825. 求出 MK 平均值

1827. 最少操作使数组递增

1828. 统计一个圆中点的数目

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

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

1852. 每个子数组的数字种类数

1862. 向下取整数对和

1863. 找出所有子集的异或总和再求和

1866. 恰有 K 根木棍可以看到的排列数目

1872. 石子游戏 VIII

1874. 两个数组的最小乘积和

1884. 鸡蛋掉落-两枚鸡蛋

1885. 统计数对

1901. 寻找峰值 II

1902. 给定二叉搜索树的插入顺序求深度

1908. Nim 游戏 II

1911. 最大子序列交替和

1922. 统计好数字的数目

1927. 求和游戏

1944. 队列中可以看到的人数

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

1969. 数组元素的最小非零乘积

1971. 寻找图中是否存在路径

1973. 值等于子节点值之和的节点数量

1976. 到达目的地的方案数

1979. 找出数组的最大公约数

1985. 找出数组中的第 K 大整数

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

1992. 找到所有的农场组

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

1998. 数组的最大公因数排序

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


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

二叉树

1611. 使整数变为 0 的最少操作次数

九连环

1612. 检查两棵二叉表达式树是否等价

二叉树

1621. 大小为 K 的不重叠线段的数目

组合

1631. 最小体力消耗路径

BFS

1632. 矩阵转换后的秩

并查集

1634. 求两个多项式链表的和

单链表

1641. 统计字典序元音字符串的数目

组合

1643. 第 K 条最小指令

全排列

1644. 二叉树的最近公共祖先 II

LCA

1650. 二叉树的最近公共祖先 III

LCA

1652. 拆炸弹

循环数组

1657. 确定两个字符串是否接近

如果可以使用以下操作从一个字符串得到另一个字符串,则认为两个字符串 接近 :

  • 操作 1:交换任意两个 现有 字符。
    • 例如,abcde -> aecdb
  • 操作 2:将一个 现有 字符的每次出现转换为另一个 现有 字符,并对另一个字符执行相同的操作。
    • 例如,aacabb -> bbcbaa(所有 a 转化为 b ,而所有的 b 转换为 a )

你可以根据需要对任意一个字符串多次使用这两种操作。

给你两个字符串,word1 和 word2 。如果 word1  word2 接近 ,就返回 true ;否则,返回 false 

示例 1:

输入:word1 = "abc", word2 = "bca"
输出:true
解释:2 次操作从 word1 获得 word2 。
执行操作 1:"abc" -> "acb"
执行操作 1:"acb" -> "bca"

示例 2:

输入:word1 = "a", word2 = "aa"
输出:false
解释:不管执行多少次操作,都无法从 word1 得到 word2 ,反之亦然。

示例 3:

输入:word1 = "cabbba", word2 = "abbccc"
输出:true
解释:3 次操作从 word1 获得 word2 。
执行操作 1:"cabbba" -> "caabbb"
执行操作 2:"caabbb" -> "baaccc"
执行操作 2:"baaccc" -> "abbccc"

示例 4:

输入:word1 = "cabbba", word2 = "aabbss"
输出:false
解释:不管执行多少次操作,都无法从 word1 得到 word2 ,反之亦然。

提示:

  • 1 <= word1.length, word2.length <= 105
  • word1 和 word2 仅包含小写英文字母
class Solution {
public:
	bool closeStrings(string word1, string word2) {
		auto v1 = cal(word1);
		auto v2 = cal(word2);
		for (int i = 0; i < v1.size(); i++) {
			if (v1[i] == 0 && v2[i] != 0)return false;
			if (v1[i] != 0 && v2[i] == 0)return false;
		}
		sort(v1.begin(), v1.end());
		sort(v2.begin(), v2.end());
		return v1 == v2;
	}
	vector<int> cal(string s) {
		map<char, int>m;
		for (auto c : s) {
			m[c]++;
		}
		vector<int>ans;
		for (char c = 'a'; c <= 'z'; c++)ans.push_back(m[c]);
		return ans;
	}
};

1658. 将 x 减到 0 的最小操作数

搜索

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

水题

1663. 具有给定数值的最小字符串

水题

1664. 生成平衡数组的方案数

水题

1666. 改变二叉树的根节点

二叉树

1668. 最大重复子字符串

KMP

1669. 合并两个链表

链表

1673. 找出最具竞争力的子序列

单调栈

1676. 二叉树的最近公共祖先 IV

LCA

1682. 最长回文子序列 II

高维DP

1684. 统计一致字符串的数目

水题

1686. 石子游戏 VI

公开游戏

1690. 石子游戏 VII

公开游戏

1696. 跳跃游戏 VI

数列DP

1697. 检查边长度限制的路径是否存在

并查集

1700. 无法吃午餐的学生数量

rust

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

给你一个二进制字符串 binary ,它仅有 0 或者 1 组成。你可以使用下面的操作任意次对它进行修改:

  • 操作 1 :如果二进制串包含子字符串 "00" ,你可以用 "10" 将其替换。
    • 比方说, "00010" -> "10010"
  • 操作 2 :如果二进制串包含子字符串 "10" ,你可以用 "01" 将其替换。
    • 比方说, "00010" -> "00001"

请你返回执行上述操作任意次以后能得到的 最大二进制字符串 。如果二进制字符串 x 对应的十进制数字大于二进制字符串 y 对应的十进制数字,那么我们称二进制字符串 x 大于二进制字符串 y 

示例 1:

输入:binary = "000110"
输出:"111011"
解释:一个可行的转换为:
"000110" -> "000101" 
"000101" -> "100101" 
"100101" -> "110101" 
"110101" -> "110011" 
"110011" -> "111011"

示例 2:

输入:binary = "01"
输出:"01"
解释:"01" 没办法进行任何转换。

提示:

  • 1 <= binary.length <= 105
  • binary 仅包含 '0' 和 '1' 。
class Solution {
public:
    string maximumBinaryString(string binary) {
        string ans="";
        int n=0;
        bool flag=false;
        for(auto c:binary){
            if(c=='0')flag=true;
            if(flag && c=='1')n++;
            ans+='1';
        }
        if(flag)ans[ans.length()-n-1]='0';
        return ans;
    }
};

1704. 判断字符串的两半是否相似

水题

1724. 检查边长度限制的路径是否存在 II

并查集

1732. 找到最高海拔

水题

1735. 生成乘积数组的方案数

组合数

1738. 找出第 K 大的异或坐标值

给你一个二维矩阵 matrix 和一个整数 k ,矩阵大小为 m x n 由非负整数组成。

矩阵中坐标 (a, b) 的  可由对所有满足 0 <= i <= a < m 且 0 <= j <= b < n 的元素 matrix[i][j]下标从 0 开始计数)执行异或运算得到。

请你找出 matrix 的所有坐标中第 k 大的值(k 的值从 1 开始计数)。

示例 1:

输入:matrix = [[5,2],[1,6]], k = 1
输出:7
解释:坐标 (0,1) 的值是 5 XOR 2 = 7 ,为最大的值。

示例 2:

输入:matrix = [[5,2],[1,6]], k = 2
输出:5
解释:坐标 (0,0) 的值是 5 = 5 ,为第 2 大的值。

示例 3:

输入:matrix = [[5,2],[1,6]], k = 3
输出:4
解释:坐标 (1,0) 的值是 5 XOR 1 = 4 ,为第 3 大的值。

示例 4:

输入:matrix = [[5,2],[1,6]], k = 4
输出:0
解释:坐标 (1,1) 的值是 5 XOR 2 XOR 1 XOR 6 = 0 ,为第 4 大的值。

提示:

  • m == matrix.length
  • n == matrix[i].length
  • 1 <= m, n <= 1000
  • 0 <= matrix[i][j] <= 106
  • 1 <= k <= m * n
class Solution {
public:
    int kthLargestValue(vector<vector<int>>& matrix, int k) {
        vector<int>v;
        for (int i = 0; i < matrix.size(); i++) {
            for (int j = 0; j < matrix[0].size(); j++) {
                if (i)matrix[i][j] ^= matrix[i - 1][j];
                if (j)matrix[i][j] ^= matrix[i][j-1];
                if (i&&j)matrix[i][j] ^= matrix[i-1][j - 1];
                v.push_back(matrix[i][j]);
            }
        }
        sort(v.begin(), v.end());
        return v[v.size() - k];
    }
};

1740. 找到二叉树中的距离

二叉树

1742. 盒子中小球的最大数量

水题

1752. 检查数组是否经排序和轮转得到

水题

1753. 移除石子的最大得分

你正在玩一个单人游戏,面前放置着大小分别为 a​​​​​​、b 和 c​​​​​​ 的 三堆 石子。

每回合你都要从两个 不同的非空堆 中取出一颗石子,并在得分上加 1 分。当存在 两个或更多 的空堆时,游戏停止。

给你三个整数 a 、b 和 c ,返回可以得到的 最大分数 。

示例 1:

输入:a = 2, b = 4, c = 6
输出:6
解释:石子起始状态是 (2, 4, 6) ,最优的一组操作是:
- 从第一和第三堆取,石子状态现在是 (1, 4, 5)
- 从第一和第三堆取,石子状态现在是 (0, 4, 4)
- 从第二和第三堆取,石子状态现在是 (0, 3, 3)
- 从第二和第三堆取,石子状态现在是 (0, 2, 2)
- 从第二和第三堆取,石子状态现在是 (0, 1, 1)
- 从第二和第三堆取,石子状态现在是 (0, 0, 0)
总分:6 分 。

示例 2:

输入:a = 4, b = 4, c = 6
输出:7
解释:石子起始状态是 (4, 4, 6) ,最优的一组操作是:
- 从第一和第二堆取,石子状态现在是 (3, 3, 6)
- 从第一和第三堆取,石子状态现在是 (2, 3, 5)
- 从第一和第三堆取,石子状态现在是 (1, 3, 4)
- 从第一和第三堆取,石子状态现在是 (0, 3, 3)
- 从第二和第三堆取,石子状态现在是 (0, 2, 2)
- 从第二和第三堆取,石子状态现在是 (0, 1, 1)
- 从第二和第三堆取,石子状态现在是 (0, 0, 0)
总分:7 分 。

示例 3:

输入:a = 1, b = 8, c = 8
输出:8
解释:最优的一组操作是连续从第二和第三堆取 8 回合,直到将它们取空。
注意,由于第二和第三堆已经空了,游戏结束,不能继续从第一堆中取石子。

提示:

  • 1 <= a, b, c <= 105
class Solution {
public:
    int maximumScore(int a, int b, int c) {
        if(a<b)a^=b^=a^=b;
        if(a<c)a^=c^=a^=c;
        if(a>b+c)return b+c;
        return (a+b+c)/2;
    }
};

1766. 互质树

DP

1768. 交替合并字符串

水题


 

1773. 统计匹配检索规则的物品数量

给你一个数组 items ,其中 items[i] = [typei, colori, namei] ,描述第 i 件物品的类型、颜色以及名称。

另给你一条由两个字符串 ruleKey 和 ruleValue 表示的检索规则。

如果第 i 件物品能满足下述条件之一,则认为该物品与给定的检索规则 匹配 :

  • ruleKey == "type" 且 ruleValue == typei 。
  • ruleKey == "color" 且 ruleValue == colori 。
  • ruleKey == "name" 且 ruleValue == namei 。

统计并返回 匹配检索规则的物品数量 。

示例 1:

输入:items = [["phone","blue","pixel"],["computer","silver","lenovo"],["phone","gold","iphone"]], ruleKey = "color", ruleValue = "silver"
输出:1
解释:只有一件物品匹配检索规则,这件物品是 ["computer","silver","lenovo"] 。

示例 2:

输入:items = [["phone","blue","pixel"],["computer","silver","phone"],["phone","gold","iphone"]], ruleKey = "type", ruleValue = "phone"
输出:2
解释:只有两件物品匹配检索规则,这两件物品分别是 ["phone","blue","pixel"] 和 ["phone","gold","iphone"] 。注意,["computer","silver","phone"] 未匹配检索规则。

提示:

  • 1 <= items.length <= 104
  • 1 <= typei.length, colori.length, namei.length, ruleValue.length <= 10
  • ruleKey 等于 "type""color" 或 "name"
  • 所有字符串仅由小写字母组成
class Solution {
public:
	int countMatches(vector<vector<string>>& items, string ruleKey, string ruleValue) {
		int k = 0, ans = 0;
		if (ruleKey == "color")k = 1;
		if (ruleKey == "name")k = 2;
		for (auto& v : items)if (v[k] == ruleValue)ans++;
		return ans;
	}
};

1780. 判断一个数字是否可以表示成三的幂的和

数论

1785. 构成特定和需要添加的最少元素

给你一个整数数组 nums ,和两个整数 limit 与 goal 。数组 nums 有一条重要属性:abs(nums[i]) <= limit 。

返回使数组元素总和等于 goal 所需要向数组中添加的 最少元素数量 ,添加元素 不应改变 数组中 abs(nums[i]) <= limit 这一属性。

注意,如果 x >= 0 ,那么 abs(x) 等于 x ;否则,等于 -x 。

示例 1:

输入:nums = [1,-1,1], limit = 3, goal = -4
输出:2
解释:可以将 -2 和 -3 添加到数组中,数组的元素总和变为 1 - 1 + 1 - 2 - 3 = -4 。

示例 2:

输入:nums = [1,-10,9,1], limit = 100, goal = 0
输出:1

提示:

  • 1 <= nums.length <= 105
  • 1 <= limit <= 106
  • -limit <= nums[i] <= limit
  • -109 <= goal <= 109
class Solution {
public:
	int minElements(vector<int>& nums, int limit, int goal) {
		return (abs(GetVecSum(nums) - goal) + limit - 1) / limit;
	}
};

1793. 好子数组的最大分数

双指针

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

水题

1799. N 次操作后的最大分数和

状态压缩DP

1801. 积压订单中的订单总数

给你一个二维整数数组 orders ,其中每个 orders[i] = [pricei, amounti, orderTypei] 表示有 amounti 笔类型为 orderTypei 、价格为 pricei 的订单。

订单类型 orderTypei 可以分为两种:

0 表示这是一批采购订单 buy
1 表示这是一批销售订单 sell
注意,orders[i] 表示一批共计 amounti 笔的独立订单,这些订单的价格和类型相同。对于所有有效的 i ,由 orders[i] 表示的所有订单提交时间均早于 orders[i+1] 表示的所有订单。

存在由未执行订单组成的 积压订单 。积压订单最初是空的。提交订单时,会发生以下情况:

如果该订单是一笔采购订单 buy ,则可以查看积压订单中价格 最低 的销售订单 sell 。如果该销售订单 sell 的价格 低于或等于 当前采购订单 buy 的价格,则匹配并执行这两笔订单,并将销售订单 sell 从积压订单中删除。否则,采购订单 buy 将会添加到积压订单中。
反之亦然,如果该订单是一笔销售订单 sell ,则可以查看积压订单中价格 最高 的采购订单 buy 。如果该采购订单 buy 的价格 高于或等于 当前销售订单 sell 的价格,则匹配并执行这两笔订单,并将采购订单 buy 从积压订单中删除。否则,销售订单 sell 将会添加到积压订单中。
输入所有订单后,返回积压订单中的 订单总数 。由于数字可能很大,所以需要返回对 109 + 7 取余的结果。

示例 1:


输入:orders = [[10,5,0],[15,2,1],[25,1,1],[30,4,0]]
输出:6
解释:输入订单后会发生下述情况:
- 提交 5 笔采购订单,价格为 10 。没有销售订单,所以这 5 笔订单添加到积压订单中。
- 提交 2 笔销售订单,价格为 15 。没有采购订单的价格大于或等于 15 ,所以这 2 笔订单添加到积压订单中。
- 提交 1 笔销售订单,价格为 25 。没有采购订单的价格大于或等于 25 ,所以这 1 笔订单添加到积压订单中。
- 提交 4 笔采购订单,价格为 30 。前 2 笔采购订单与价格最低(价格为 15)的 2 笔销售订单匹配,从积压订单中删除这 2 笔销售订单。第 3 笔采购订单与价格最低的 1 笔销售订单匹配,销售订单价格为 25 ,从积压订单中删除这 1 笔销售订单。积压订单中不存在更多销售订单,所以第 4 笔采购订单需要添加到积压订单中。
最终,积压订单中有 5 笔价格为 10 的采购订单,和 1 笔价格为 30 的采购订单。所以积压订单中的订单总数为 6 。
示例 2:


输入:orders = [[7,1000000000,1],[15,3,0],[5,999999995,0],[5,1,1]]
输出:999999984
解释:输入订单后会发生下述情况:
- 提交 109 笔销售订单,价格为 7 。没有采购订单,所以这 109 笔订单添加到积压订单中。
- 提交 3 笔采购订单,价格为 15 。这些采购订单与价格最低(价格为 7 )的 3 笔销售订单匹配,从积压订单中删除这 3 笔销售订单。
- 提交 999999995 笔采购订单,价格为 5 。销售订单的最低价为 7 ,所以这 999999995 笔订单添加到积压订单中。
- 提交 1 笔销售订单,价格为 5 。这笔销售订单与价格最高(价格为 5 )的 1 笔采购订单匹配,从积压订单中删除这 1 笔采购订单。
最终,积压订单中有 (1000000000-3) 笔价格为 7 的销售订单,和 (999999995-1) 笔价格为 5 的采购订单。所以积压订单中的订单总数为 1999999991 ,等于 999999984 % (109 + 7) 。
 

提示:

1 <= orders.length <= 105
orders[i].length == 3
1 <= pricei, amounti <= 109
orderTypei 为 0 或 1

class Solution {
public:
	int getNumberOfBacklogOrders(vector<vector<int>>& orders) {
		long long ans = 0;
		priority_queue<vector<int>>q0, q1;
		for (auto vi : orders) {
			if (vi[2] == 0)q0.push(vi);
			else {
				vi[0] *= -1;
				q1.push(vi);
			}
			ans += vi[1];
			while (!q0.empty() && !q1.empty()) {
				if (q0.top()[0] + q1.top()[0] < 0)break;
				int m = min(q0.top()[1], q1.top()[1]);
				ans -= m * 2;
				auto v0 = q0.top(), v1 = q1.top();
				q0.pop(), q1.pop();
				v0[1] -= m, v1[1] -= m;
				if (v0[1])q0.push(v0);
				if (v1[1])q1.push(v1);
			}
		}
		return ans % 1000000007;
	}
};

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

二分法

1803. 统计异或值在范围内的数对有多少

JS

1804. 实现 Trie (前缀树) II

前缀树

1805. 字符串中不同整数的数目

水题

1806. 还原排列的最少操作步数

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

水题

1808. 好因子的最大数目

调整法

1812. 判断国际象棋棋盘中一个格子的颜色

给你一个坐标 coordinates ,它是一个字符串,表示国际象棋棋盘中一个格子的坐标。下图是国际象棋棋盘示意图。

如果所给格子的颜色是白色,请你返回 true,如果是黑色,请返回 false 。

给定坐标一定代表国际象棋棋盘上一个存在的格子。坐标第一个字符是字母,第二个字符是数字。

示例 1:

输入:coordinates = "a1"
输出:false
解释:如上图棋盘所示,"a1" 坐标的格子是黑色的,所以返回 false 。

示例 2:

输入:coordinates = "h3"
输出:true
解释:如上图棋盘所示,"h3" 坐标的格子是白色的,所以返回 true 。

示例 3:

输入:coordinates = "c7"
输出:false

提示:

  • coordinates.length == 2
  • 'a' <= coordinates[0] <= 'h'
  • '1' <= coordinates[1] <= '8'

class Solution {
public:
    bool squareIsWhite(string s) {
        return (s[0]+s[1])%2;
    }
};

1813. 句子相似性 III

水题

1814. 统计一个数组中好对子的数目

水题

1815. 得到新鲜甜甜圈的最多组数

模拟退火

1817. 查找用户活跃分钟数

给你用户在 LeetCode 的操作日志,和一个整数 k 。日志用一个二维整数数组 logs 表示,其中每个 logs[i] = [IDi, timei] 表示 ID 为 IDi 的用户在 timei 分钟时执行了某个操作。

多个用户 可以同时执行操作,单个用户可以在同一分钟内执行 多个操作 。

指定用户的 用户活跃分钟数(user active minutes,UAM) 定义为用户对 LeetCode 执行操作的 唯一分钟数 。 即使一分钟内执行多个操作,也只能按一分钟计数。

请你统计用户活跃分钟数的分布情况,统计结果是一个长度为 k 且 下标从 1 开始计数 的数组 answer ,对于每个 j(1 <= j <= k),answer[j] 表示 用户活跃分钟数 等于 j 的用户数。

返回上面描述的答案数组 answer 。

示例 1:

输入:logs = [[0,5],[1,2],[0,2],[0,5],[1,3]], k = 5
输出:[0,2,0,0,0]
解释:
ID=0 的用户执行操作的分钟分别是:5 、2 和 5 。因此,该用户的用户活跃分钟数为 2(分钟 5 只计数一次)
ID=1 的用户执行操作的分钟分别是:2 和 3 。因此,该用户的用户活跃分钟数为 2
2 个用户的用户活跃分钟数都是 2 ,answer[2] 为 2 ,其余 answer[j] 的值都是 0
示例 2:

输入:logs = [[1,1],[2,2],[2,3]], k = 4
输出:[1,1,0,0]
解释:
ID=1 的用户仅在分钟 1 执行单个操作。因此,该用户的用户活跃分钟数为 1
ID=2 的用户执行操作的分钟分别是:2 和 3 。因此,该用户的用户活跃分钟数为 2
1 个用户的用户活跃分钟数是 1 ,1 个用户的用户活跃分钟数是 2 
因此,answer[1] = 1 ,answer[2] = 1 ,其余的值都是 0
 

提示:

1 <= logs.length <= 104
0 <= IDi <= 109
1 <= timei <= 105
k 的取值范围是 [用户的最大用户活跃分钟数, 105]

class Solution {
public:
    vector<int> findingUsersActiveMinutes(vector<vector<int>>& logs, int k) {
        map<int,set<int>>m;
        for(auto &v:logs){
            m[v[0]].insert(v[1]);
        }
        vector<int>v(k,0);
        for(auto &p:m){
            v[p.second.size()-1]++;
        }
        return v;
    }
};

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

欧几里得算法

1822. 数组元素积的符号

已知函数 signFunc(x) 将会根据 x 的正负返回特定值:

  • 如果 x 是正数,返回 1 。
  • 如果 x 是负数,返回 -1 。
  • 如果 x 是等于 0 ,返回 0 。

给你一个整数数组 nums 。令 product 为数组 nums 中所有元素值的乘积。

返回 signFunc(product) 。

示例 1:

输入:nums = [-1,-2,-3,-4,3,2,1]
输出:1
解释:数组中所有值的乘积是 144 ,且 signFunc(144) = 1

示例 2:

输入:nums = [1,5,0,2,-3]
输出:0
解释:数组中所有值的乘积是 0 ,且 signFunc(0) = 0

示例 3:

输入:nums = [-1,1,-1,1,-1]
输出:-1
解释:数组中所有值的乘积是 -1 ,且 signFunc(-1) = -1

提示:

  • 1 <= nums.length <= 1000
  • -100 <= nums[i] <= 100
class Solution {
public:
    int arraySign(vector<int>& nums) {
        int ans=0;
        for(auto n:nums){
            if(!n)return 0;
            if(n<0)ans++;
        }
        return 1-ans%2*2;
    }
};

1823. 找出游戏的获胜者

rust

1824. 最少侧跳次数(DP)

给你一个长度为 n 的 3 跑道道路 ,它总共包含 n + 1 个 点 ,编号为 0 到 n 。一只青蛙从 0 号点第二条跑道 出发 ,它想要跳到点 n 处。然而道路上可能有一些障碍。

给你一个长度为 n + 1 的数组 obstacles ,其中 obstacles[i] (取值范围从 0 到 3)表示在点 i 处的 obstacles[i] 跑道上有一个障碍。如果 obstacles[i] == 0 ,那么点 i 处没有障碍。任何一个点的三条跑道中 最多有一个 障碍。

比方说,如果 obstacles[2] == 1 ,那么说明在点 2 处跑道 1 有障碍。
这只青蛙从点 i 跳到点 i + 1 且跑道不变的前提是点 i + 1 的同一跑道上没有障碍。为了躲避障碍,这只青蛙也可以在 同一个 点处 侧跳 到 另外一条 跑道(这两条跑道可以不相邻),但前提是跳过去的跑道该点处没有障碍。

比方说,这只青蛙可以从点 3 处的跑道 3 跳到点 3 处的跑道 1 。
这只青蛙从点 0 处跑道 2 出发,并想到达点 n 处的 任一跑道 ,请你返回 最少侧跳次数 。

注意:点 0 处和点 n 处的任一跑道都不会有障碍。

示例 1:


输入:obstacles = [0,1,2,3,0]
输出:2 
解释:最优方案如上图箭头所示。总共有 2 次侧跳(红色箭头)。
注意,这只青蛙只有当侧跳时才可以跳过障碍(如上图点 2 处所示)。
示例 2:


输入:obstacles = [0,1,1,3,3,0]
输出:0
解释:跑道 2 没有任何障碍,所以不需要任何侧跳。
示例 3:


输入:obstacles = [0,2,1,0,3,0]
输出:2
解释:最优方案如上图所示。总共有 2 次侧跳。
 

提示:

obstacles.length == n + 1
1 <= n <= 5 * 105
0 <= obstacles[i] <= 3
obstacles[0] == obstacles[n] == 0


class Solution {
public:
    int minSideJumps(const vector<int>& ob) {
        vector<int>ans(3, 0);
        for (int i = ob.size() - 2; i >= 0; i--) {
            int flag = 0;
            int k=INT_MAX;
            for (int j = 1; j <= 3; j++) {
                if (ob[i] == j) {
                    ans[j - 1] = -1;
                }
                else if (ob[i + 1] == j)flag = j;
                else k = min(k,ans[j - 1]);
            }
            if (flag)ans[flag - 1] = k+1;
        }
        return ans[1];
    }
};

1825. 求出 MK 平均值

给你两个整数 m 和 k ,以及数据流形式的若干整数。你需要实现一个数据结构,计算这个数据流的 MK 平均值 。

MK 平均值 按照如下步骤计算:

如果数据流中的整数少于 m 个,MK 平均值 为 -1 ,否则将数据流中最后 m 个元素拷贝到一个独立的容器中。
从这个容器中删除最小的 k 个数和最大的 k 个数。
计算剩余元素的平均值,并 向下取整到最近的整数 。
请你实现 MKAverage 类:

MKAverage(int m, int k) 用一个空的数据流和两个整数 m 和 k 初始化 MKAverage 对象。
void addElement(int num) 往数据流中插入一个新的元素 num 。
int calculateMKAverage() 对当前的数据流计算并返回 MK 平均数 ,结果需 向下取整到最近的整数 。
 

示例 1:

输入:
["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]

解释:
MKAverage obj = new MKAverage(3, 1); 
obj.addElement(3);        // 当前元素为 [3]
obj.addElement(1);        // 当前元素为 [3,1]
obj.calculateMKAverage(); // 返回 -1 ,因为 m = 3 ,但数据流中只有 2 个元素
obj.addElement(10);       // 当前元素为 [3,1,10]
obj.calculateMKAverage(); // 最后 3 个元素为 [3,1,10]
                          // 删除最小以及最大的 1 个元素后,容器为 [3]
                          // [3] 的平均值等于 3/1 = 3 ,故返回 3
obj.addElement(5);        // 当前元素为 [3,1,10,5]
obj.addElement(5);        // 当前元素为 [3,1,10,5,5]
obj.addElement(5);        // 当前元素为 [3,1,10,5,5,5]
obj.calculateMKAverage(); // 最后 3 个元素为 [5,5,5]
                          // 删除最小以及最大的 1 个元素后,容器为 [5]
                          // [5] 的平均值等于 5/1 = 5 ,故返回 5
 

提示:

3 <= m <= 105
1 <= k*2 < m
1 <= num <= 105
addElement 与 calculateMKAverage 总操作次数不超过 105 次。

template<typename T>
vector<T> queToVec(queue<T>q)
{
	vector<T>v;
	while (!q.empty())v.push_back(q.front()), q.pop();
	return v;
}
template<typename T,typename T2>
void delOnlyOne(T &x, T2 n)
{
	auto it = x.find(n);
	if (it != x.end())x.erase(it);
}

class MKAverage {
public:
	MKAverage(int m, int k) {
		this->m = m;
		this->k = k;
		while (!q.empty())q.pop();
		sum2 = 0;
	}

	void addElement(int num) {
		if (q.size() < m - 1) {
			q.push(num);
			return;
		}
		if (q.size() == m - 1) {
			q.push(num);
			auto v = queToVec(q);
			sort(v.begin(), v.end());
			for (int i = 0; i < k; i++)s1.insert(v[i]);
			for (int i = k; i < m - k; i++)s2.insert(v[i]), sum2 += v[i];
			for (int i = m-k; i < m; i++)s3.insert(v[i]);
			return;
		}
		del(q.front());
		q.pop();
		q.push(num);
		push(num);
	}

	int calculateMKAverage() {
		if (q.size() < m)return -1;
		return sum2 / (m - k * 2);
	}
private:
	void del(int x)
	{
		int flag;
		if (x < *s2.begin())delOnlyOne(s1, x), flag = 1;
		else if (x < *s3.begin())delOnlyOne(s2, x), flag = 2, sum2 -= x;
		else delOnlyOne(s3, x), flag = 3;
		if (flag < 3)s2.insert(*s3.begin()), sum2+= *s3.begin(),s3.erase(s3.begin());
		if (flag < 2)s1.insert(*s2.begin()), sum2-= *s2.begin(),s2.erase(s2.begin());
	}
	void push(int x)
	{
		s1.insert(x);
		s2.insert(*s1.rbegin()), sum2 += *s1.rbegin(), s1.erase(--s1.end());
		s3.insert(*s2.rbegin()), sum2-= *s2.rbegin(),s2.erase(--s2.end());
	}
	queue<int>q;
	multiset<int>s1, s2, s3;
	int m, k,sum2;
};

1827. 最少操作使数组递增

给你一个整数数组 nums (下标从 0 开始)。每一次操作中,你可以选择数组中一个元素,并将它增加 1 。

  • 比方说,如果 nums = [1,2,3] ,你可以选择增加 nums[1] 得到 nums = [1,3,3] 。

请你返回使 nums 严格递增 的 最少 操作次数。

我们称数组 nums 是 严格递增的 ,当它满足对于所有的 0 <= i < nums.length - 1 都有 nums[i] < nums[i+1] 。一个长度为 1 的数组是严格递增的一种特殊情况。

示例 1:

输入:nums = [1,1,1]
输出:3
解释:你可以进行如下操作:
1) 增加 nums[2] ,数组变为 [1,1,2] 。
2) 增加 nums[1] ,数组变为 [1,2,2] 。
3) 增加 nums[2] ,数组变为 [1,2,3] 。

示例 2:

输入:nums = [1,5,2,4,1]
输出:14

示例 3:

输入:nums = [8]
输出:0

提示:

  • 1 <= nums.length <= 5000
  • 1 <= nums[i] <= 104
class Solution {
public:
	int minOperations(vector<int>& nums) {
		int ans = 0;
		for (int i = 1; i < nums.size(); i++)
			if (nums[i] <= nums[i - 1])ans += nums[i - 1] - nums[i]+1, nums[i] = nums[i - 1] + 1;
		return ans;
	}
};

1828. 统计一个圆中点的数目

水题

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

字典序

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

贡献法

1852. 每个子数组的数字种类数

给你一个整数数组 nums与一个整数 k,请你构造一个长度 n-k+1 的数组 ans,这个数组第i个元素 ans[i] 是每个长度为k的子数组 nums[i:i+k-1] = [nums[i], nums[i+1], ..., nums[i+k-1]]中数字的种类数。

返回这个数组 ans

示例 1:

输入: nums = [1,2,3,2,2,1,3], k = 3
输出: [3,2,2,2,3]
解释:每个子数组的数字种类计算方法如下:
- nums[0:2] = [1,2,3] 所以 ans[0] = 3
- nums[1:3] = [2,3,2] 所以 ans[1] = 2
- nums[2:4] = [3,2,2] 所以 ans[2] = 2
- nums[3:5] = [2,2,1] 所以 ans[3] = 2
- nums[4:6] = [2,1,3] 所以 ans[4] = 3

示例 2:

输入: nums = [1,1,1,1,2,3,4], k = 4
输出: [1,2,3,4]
解释: 每个子数组的数字种类计算方法如下:
- nums[0:3] = [1,1,1,1] 所以 ans[0] = 1
- nums[1:4] = [1,1,1,2] 所以 ans[1] = 2
- nums[2:5] = [1,1,2,3] 所以 ans[2] = 3
- nums[3:6] = [1,2,3,4] 所以 ans[3] = 4

提示:

  • 1 <= k <= nums.length <= 105
  • 1 <= nums[i] <= 105
class Solution {
public:
    vector<int> distinctNumbers(vector<int>& nums, int k) {
        map<int,int>m;
        int s=0;
        vector<int>ans;
        for(int i=0;i<k;i++){
            if(++m[nums[i]]==1)s++;
        }
        ans.push_back(s);
        for(int i=k;i<nums.size();i++){
            if(++m[nums[i]]==1)s++;
            if(--m[nums[i-k]]==0)s--;
            ans.push_back(s);
        }
        return ans;
    }
};

1862. 向下取整数对和

数论

1863. 找出所有子集的异或总和再求和

贡献法

1866. 恰有 K 根木棍可以看到的排列数目

组合

1872. 石子游戏 VIII

公开游戏

1874. 两个数组的最小乘积和

给定两个长度相等的数组ab,它们的乘积和为数组中所有的a[i] * b[i]之和,其中0 <= i < a.length

  • 比如a = [1,2,3,4]b = [5,2,3,1]时,它们的乘积和1*5 + 2*2 + 3*3 + 4*1 = 22

现有两个长度都为n的数组nums1nums2,你可以以任意顺序排序nums1,请返回它们的最小乘积和

示例 1:

输入: nums1 = [5,3,4,2], nums2 = [4,2,2,5]
输出: 40
解释: 将 num1 重新排列为 [3,5,4,2] 后,可由 [3,5,4,2] 和 [4,2,2,5] 得到最小乘积和 3*4 + 5*2 + 4*2 + 2*5 = 40。

示例 2:

输入: nums1 = [2,1,4,5,7], nums2 = [3,2,4,8,6]
输出: 65
解释: 将 num1 重新排列为 [5,7,4,1,2] 后,可由 [5,7,4,1,2] 和 [3,2,4,8,6] 得到最小乘积和 5*3 + 7*2 + 4*4 + 1*8 + 2*6 = 65。

提示:

  • n == nums1.length == nums2.length
  • 1 <= n <= 105
  • 1 <= nums1[i], nums2[i] <= 100
class Solution {
public:
	int minProductSum(vector<int>&v1,vector<int>&v2) {
		sort(v1.begin(), v1.end());
		sort(v2.begin(), v2.end());
		int ans = 0;
		for (int i = 0; i < v1.size(); i++)ans += v1[i] * v2[v1.size() - 1 - i];
		return ans;
	}
};

1883. 准时抵达会议现场的最小跳过休息次数

二维DP

1884. 鸡蛋掉落-两枚鸡蛋

单人决策

1885. 统计数对

双指针

1901. 寻找峰值 II

二分法

1902. 给定二叉搜索树的插入顺序求深度

红黑树

1908. Nim 游戏 II

博弈

1911. 最大子序列交替和

数列DP

1916. 统计为蚁群构筑房间的不同顺序

组合​​​​​​​

1922. 统计好数字的数目

快速幂

1927. 求和游戏

公开游戏

1944. 队列中可以看到的人数

单调栈

1953. 你可以工作的最大周数

贪心​​​​​​​

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

水题

1969. 数组元素的最小非零乘积

快速幂

1971. 寻找图中是否存在路径

BFS

1973. 值等于子节点值之和的节点数量

二叉树

1976. 到达目的地的方案数

最短路

1979. 找出数组的最大公约数

欧几里得

1985. 找出数组中的第 K 大整数

给你一个字符串数组 nums 和一个整数 k 。nums 中的每个字符串都表示一个不含前导零的整数。

返回 nums 中表示第 k 大整数的字符串。

注意:重复的数字在统计时会视为不同元素考虑。例如,如果 nums 是 ["1","2","2"],那么 "2" 是最大的整数,"2" 是第二大的整数,"1" 是第三大的整数。

示例 1:

输入:nums = ["3","6","7","10"], k = 4
输出:"3"
解释:
nums 中的数字按非递减顺序排列为 ["3","6","7","10"]
其中第 4 大整数是 "3"

示例 2:

输入:nums = ["2","21","12","1"], k = 3
输出:"2"
解释:
nums 中的数字按非递减顺序排列为 ["1","2","12","21"]
其中第 3 大整数是 "2"

示例 3:

输入:nums = ["0","0"], k = 2
输出:"0"
解释:
nums 中的数字按非递减顺序排列为 ["0","0"]
其中第 2 大整数是 "0"

提示:

  • 1 <= k <= nums.length <= 104
  • 1 <= nums[i].length <= 100
  • nums[i] 仅由数字组成
  • nums[i] 不含任何前导零
class Solution {
public:
	string kthLargestNumber(vector<string>& nums, int k) {
		map<int, vector<string>>m;
		for (auto &s : nums)m[s.length()].push_back(s);
		k = nums.size() - k;
		for (auto &mi : m) {
			if (mi.second.size() <= k) {
				k -= mi.second.size();
			}
			else {
				sort(mi.second.begin(), mi.second.end());
				return mi.second[k];
			}
		}
		return "";
	}
};

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

双指针、多指针

1992. 找到所有的农场组

并查集

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

数列DP​​​​​​​

1998. 数组的最大公因数排序

因式分解

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

给你三个整数, kdigit1和 digit2, 你想要找到满足以下条件的 最小 整数:

  • 大于k 且是 k 的倍数
  • 仅由digit1 和 digit2 组成,即 每一位数 均是 digit1 或 digit2

请你返回 最小的满足这两个条件的整数,如果不存在这样的整数,或者最小的满足这两个条件的整数不在32位整数范围(0~231-1),就返回 -1 。

示例 1:

输入:k = 2, digit1 = 0, digit2 = 2
输出:20
解释:
20 是第一个仅有数字0和2组成的,比2大且是2的倍数的整数。

示例 2:

输入:k = 3, digit1 = 4, digit2 = 2
输出:24
解释:
24 是第一个仅有数字 2 和 4 组成的,比 3 大且是 3 的倍数的整数。

示例 3:

输入:k = 2, digit1 = 0, digit2 = 0
输出:-1
解释:
不存在仅由 0 组成的比 2 大且是 2 的倍数的整数,因此返回 -1 。

提示:

  • 1 <= k <= 1000
  • 0 <= digit1 <= 9
  • 0 <= digit2 <= 9
class Solution {
public:
	int findInteger(int k, int digit1, int digit2) {
		if (digit1 > digit2)digit1 ^= digit2 ^= digit1 ^= digit2;
		vector<long long>v{ 0 };
		while (!v.empty())
		{
			vector<long long>v2;
			for (auto vi : v) {
				long long x = vi * 10 + digit1;				
				if (x <= INT_MAX) {
					if (x > k && x % k == 0)return x;
					if(x)v2.push_back(x);
				}
				x = vi * 10 + digit2;
				if (x <= INT_MAX) {
					if (x > k && x % k == 0)return x;
					if (x)v2.push_back(x);
				}
			}
			v = v2;
		}
		return -1;
	}
};

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值