力扣OJ(2601-3000)

目录

2601. 质数减法运算

2604. 吃掉所有谷子的最短时间

2605. 从两个数字数组里生成最小数字

2607. 使子数组元素和相等

2609. 最长平衡子字符串

2611. 老鼠和奶酪

2614. 对角线上的质数

2617. 网格图中最少访问的格子数

2639. 查询网格图中每一列的宽度

2641. 二叉树的堂兄弟节点 II

2642. 设计可以求最短路径的图类

2644. 找出可整除性得分最大的整数

2645. 构造有效字符串的最少插入数

2652. 倍数求和

2654. 使数组所有元素变成 1 的最少操作次数

2660. 保龄球游戏的获胜者

2661. 找出叠涂元素

2663. 字典序最小的美丽字符串

2670. 找出不同元素数目差数组

2671. 频率跟踪器

2673. 使二叉树所有路径值相等的最小代价

2679. 矩阵中的和

2680. 最大或值

2681. 英雄的力量

2682. 找出转圈游戏输家

2684. 矩阵中移动的最大次数

2696. 删除子串后的字符串最小长度

2697. 字典序最小回文串

2703. 返回传递的参数的长度

2706. 购买两块巧克力

2707. 字符串中的额外字符

2708. 一个小组的最大实力值

2709. 最大公约数遍历

2710. 移除字符串中的尾随零

2717. 半有序排列

2718. 查询后矩阵的和

2719. 统计整数数目

2728. 计算一个环形街道上的房屋数量

2729. 判断一个数是否迷人

2731. 移动机器人

2735. 收集巧克力

2739. 总行驶距离

2740. 找出分区值

2742. 给墙壁刷油漆

2744. 最大字符串配对数目

2745. 构造最长的新字符串

2748. 美丽下标对的数目

2749. 得到整数零需要执行的最少操作数

2760. 最长奇偶子数组

2761. 和等于目标值的质数对

2765. 最长交替子数组

2766. 重新放置石块

2769. 找出最大的可达成数字

2778. 特殊元素平方和

2779. 数组的最大美丽值

2788. 按分隔符拆分字符串

2789. 合并后数组中的最大元素

2798. 满足目标工作时长的员工数目

2802. 找出第 K 个幸运数字

2806. 取整购买后的账户余额

2807. 在链表中插入最大公约数

2808. 使循环数组所有元素相等的最少秒数

2809. 使数组和小于等于 x 的最少时间

2810. 故障键盘

2815. 数组中的最大数对和

2818. 操作使得分最大

2824. 统计和小于目标的下标对数目

2828. 判别首字母缩略词

2829. k-avoiding 数组的最小总和

2831. 找出最长等值子数组

2834. 找出美丽数组的最小和

2839. 判断通过操作能否让字符串相等 I

2840. 判断通过操作能否让字符串相等 II

2842. 统计一个字符串的 k 子序列美丽值最大的数目

2846. 边权重均等查询

2847. 给定数字乘积的最小数字

2855. 使数组成为递增数组的最少右移次数

2859. 计算 K 置位下标对应元素的和

2860. 让所有学生保持开心的分组方法数

2861. 最大合金数

2862. 完全子集的最大元素和

2864. 最大二进制奇数

2865. 美丽塔 I

2866. 美丽塔 II

2867. 统计树中的合法路径数目

2873. 有序三元组中的最大值 I

2874. 有序三元组中的最大值 II

2875. 无限数组的最短子数组

2903. 找出满足差值条件的下标 I

2908. 元素和最小的山形三元组 I

2909. 元素和最小的山形三元组 II

2917. 找出数组中的 K-or 值

2923. 找到冠军 I

2924. 找到冠军 II

2928. 给小朋友们分糖果 I

2929. 给小朋友们分糖果 II

2930. 重新排列后包含指定子字符串的字符串数目

2931. 购买物品的最大开销

2936. 包含相等值数字块的数量

2938. 区分黑球与白球

2941. 子数组的最大 GCD-Sum

2944. 购买水果需要的最少金币数

2951. 找出峰值

2952. 需要添加的硬币的最小数量

2954. 统计感冒序列的数目

2956. 找到两个数组中的公共元素

2960. 统计已测试设备

2961. 双模幂运算

2963. 统计好分割方案的数目

2965. 找出缺失和重复的数字

2970. 统计移除递增子数组的数目 I

2972. 统计移除递增子数组的数目 II

2974. 最小数字游戏

2981. 找出出现至少三次的最长特殊子字符串 I

2982. 找出出现至少三次的最长特殊子字符串 II

2992. 自整除排列的数量

3000. 对角线最长的矩形的面积


2601. 质数减法运算

素数检测

2604. 吃掉所有谷子的最短时间

一条线上有 n 只母鸡和 m 颗谷子。给定两个整数数组 hens 和 grains ,它们的大小分别为 n 和 m ,表示母鸡和谷子的初始位置。

如果一只母鸡和一颗谷子在同一个位置,那么这只母鸡可以吃掉这颗谷子。吃掉一颗谷子的时间可以忽略不计。一只母鸡也可以吃掉多颗谷子。

在 1 秒钟内,一只母鸡可以向左或向右移动 1 个单位。母鸡可以同时且独立地移动。

如果母鸡行动得当,返回吃掉所有谷子的 最短 时间。

示例 1 :

输入:hens = [3,6,7], grains = [2,4,7,9]
输出:2
解释:
母鸡吃掉所有谷子的一种方法如下:
- 第一只母鸡在 1 秒钟内吃掉位置 2 处的谷子。
- 第二只母鸡在 2 秒钟内吃掉位置 4 处的谷子。
- 第三只母鸡在 2 秒钟内吃掉位置 7 和 9 处的谷子。 
所以,需要的最长时间为2秒。 
可以证明,在2秒钟之前,母鸡不能吃掉所有谷子。

示例 2 :

输入:hens = [4,6,109,111,213,215], grains = [5,110,214]
输出:1
解释:
母鸡吃掉所有谷子的一种方法如下:
- 第一只母鸡在 1 秒钟内吃掉位置 5 处的谷子。
- 第四只母鸡在 1 秒钟内吃掉位置 110 处的谷子。
- 第六只母鸡在 1 秒钟内吃掉位置 214 处的谷子。
- 其他母鸡不动。 
所以,需要的最长时间为 1 秒。

提示:

  • 1 <= hens.length, grains.length <= 2*104
  • 0 <= hens[i], grains[j] <= 109
class TimeOk:public Bsearch<int> {
public:
	bool timeok(const vector<int> &hens, const vector<int>& grains, int t) {
		int id = 0;
		this->grains = grains;
		for (int i = 0; i < hens.size(); i++) {
			int t2 = t - abs(hens[i] - grains[id]);
			if (t2 < 0)continue;
			s = hens[i] <= grains[id] ? hens[i] + t : max(hens[i] + t2 / 2, grains[id] + t2);
			id = find(id, int(grains.size())-1);
			if (id >= grains.size())return true;
		}
		return false;
	}
	virtual bool isOk(int x) const //若isOk(x)且!isOk(y)则必有y<x
	{
		return grains[x] > s;
	}
	vector<int> grains;
	int s;
};
class Solution :public Bsearch<long long> {
public:
	int minimumTime(vector<int>& hens, vector<int>& grains) {
		sort(hens.begin(), hens.end());
		sort(grains.begin(), grains.end());
		this->hens = hens;
		this->grains = grains;
        long long high = 2000000000;
		return find(0,high);
	}
	virtual bool isOk(long long x) const //若isOk(x)且!isOk(y)则必有y<x
	{
		return TimeOk().timeok(hens, grains, x);
	}
	vector<int> hens;
	vector<int> grains;
};

2605. 从两个数字数组里生成最小数字

给你两个只包含 1 到 9 之间数字的数组 nums1 和 nums2 ,每个数组中的元素 互不相同 ,请你返回 最小 的数字,两个数组都 至少 包含这个数字的某个数位。

示例 1:

输入:nums1 = [4,1,3], nums2 = [5,7]
输出:15
解释:数字 15 的数位 1 在 nums1 中出现,数位 5 在 nums2 中出现。15 是我们能得到的最小数字。

示例 2:

输入:nums1 = [3,5,2,6], nums2 = [3,1,7]
输出:3
解释:数字 3 的数位 3 在两个数组中都出现了。

提示:

  • 1 <= nums1.length, nums2.length <= 9
  • 1 <= nums1[i], nums2[i] <= 9
  • 每个数组中,元素 互不相同 。
class Solution {
public:
	int minNumber(vector<int>& nums1, vector<int>& nums2) {
		map<int, int>m;
		int min1=123, min2=123;
		for (auto x : nums1)min1 = min(min1, x), m[x]++;
		for (auto x : nums2)min2 = min(min2, x), m[x]++;
		for (auto mi : m)if (mi.second == 2)return mi.first;
		if (min1 > min2)min1 ^= min2 ^= min1 ^= min2;
		return min1 * 10 + min2;
	}
};

2607. 使子数组元素和相等

欧几里得

2609. 最长平衡子字符串

rust

2611. 老鼠和奶酪

有两只老鼠和 n 块不同类型的奶酪,每块奶酪都只能被其中一只老鼠吃掉。

下标为 i 处的奶酪被吃掉的得分为:

如果第一只老鼠吃掉,则得分为 reward1[i] 。
如果第二只老鼠吃掉,则得分为 reward2[i] 。
给你一个正整数数组 reward1 ,一个正整数数组 reward2 ,和一个非负整数 k 。

请你返回第一只老鼠恰好吃掉 k 块奶酪的情况下,最大 得分为多少。

示例 1:

输入:reward1 = [1,1,3,4], reward2 = [4,4,1,1], k = 2
输出:15
解释:这个例子中,第一只老鼠吃掉第 2 和 3 块奶酪(下标从 0 开始),第二只老鼠吃掉第 0 和 1 块奶酪。
总得分为 4 + 4 + 3 + 4 = 15 。
15 是最高得分。
示例 2:

输入:reward1 = [1,1], reward2 = [1,1], k = 2
输出:2
解释:这个例子中,第一只老鼠吃掉第 0 和 1 块奶酪(下标从 0 开始),第二只老鼠不吃任何奶酪。
总得分为 1 + 1 = 2 。
2 是最高得分。
 

提示:

1 <= n == reward1.length == reward2.length <= 105
1 <= reward1[i], reward2[i] <= 1000
0 <= k <= n

class Solution {
public:
    int miceAndCheese(vector<int>& reward1, vector<int>& reward2, int k) {
        Fcheng(reward1,-1);
        reward1=VecAdd(reward1,reward2);
        Fcheng(reward1,-1);
        int s=0;
        for(auto x:reward2)s+=x;
        cout<<reward1.size()<<endl;
        sort(reward1.begin(),reward1.end());
        for(int i=reward1.size()-1;i>=int(reward1.size())-k;i--)s+=reward1[i];
        return s;
    }
};

2614. 对角线上的质数

素数检测

2617. 网格图中最少访问的格子数

线段树

2639. 查询网格图中每一列的宽度

水题

2641. 二叉树的堂兄弟节点 II

二叉树BFS

2642. 设计可以求最短路径的图类

最短路

2644. 找出可整除性得分最大的整数

给你两个下标从 0 开始的整数数组 nums 和 divisors 。

divisors[i] 的 可整除性得分 等于满足 nums[j] 能被 divisors[i] 整除的下标 j 的数量。

返回 可整除性得分 最大的整数 divisors[i] 。如果有多个整数具有最大得分,则返回数值最小的一个。

示例 1:

输入:nums = [4,7,9,3,9], divisors = [5,2,3]
输出:3
解释:divisors 中每个元素的可整除性得分为:
divisors[0] 的可整除性得分为 0 ,因为 nums 中没有任何数字能被 5 整除。
divisors[1] 的可整除性得分为 1 ,因为 nums[0] 能被 2 整除。 
divisors[2] 的可整除性得分为 3 ,因为 nums[2]、nums[3] 和 nums[4] 都能被 3 整除。 
因此,返回 divisors[2] ,它的可整除性得分最大。

示例 2:

输入:nums = [20,14,21,10], divisors = [5,7,5]
输出:5
解释:divisors 中每个元素的可整除性得分为:
divisors[0] 的可整除性得分为 2 ,因为 nums[0] 和 nums[3] 都能被 5 整除。
divisors[1] 的可整除性得分为 2 ,因为 nums[1] 和 nums[2] 都能被 7 整除。
divisors[2] 的可整除性得分为 2 ,因为 nums[0] 和 nums[3] 都能被5整除。 
由于 divisors[0]、divisors[1] 和 divisors[2] 的可整除性得分都是最大的,因此,我们返回数值最小的一个,即 divisors[2] 。

示例 3:

输入:nums = [12], divisors = [10,16]
输出:10
解释:divisors 中每个元素的可整除性得分为:
divisors[0] 的可整除性得分为 0 ,因为 nums 中没有任何数字能被 10 整除。
divisors[1] 的可整除性得分为 0 ,因为 nums 中没有任何数字能被 16 整除。 
由于 divisors[0] 和 divisors[1] 的可整除性得分都是最大的,因此,我们返回数值最小的一个,即 divisors[0] 。

提示:

  • 1 <= nums.length, divisors.length <= 1000
  • 1 <= nums[i], divisors[i] <= 109
class Solution {
public:
    int maxDivScore(vector<int>& nums, vector<int>& divisors) {
        int ans=INT_MAX,num=0;
        for(auto x:divisors){
            int s=0;
            for(auto y:nums)if(y%x==0)s++;
            if(s>num)num=s,ans=x;
            else if(s==num)ans=min(ans,x);
        }
        return ans;
    }
};

2645. 构造有效字符串的最少插入数

给你一个字符串 word ,你可以向其中任何位置插入 "a"、"b" 或 "c" 任意次,返回使 word 有效 需要插入的最少字母数。

如果字符串可以由 "abc" 串联多次得到,则认为该字符串 有效 。

示例 1:

输入:word = "b"
输出:2
解释:在 "b" 之前插入 "a" ,在 "b" 之后插入 "c" 可以得到有效字符串 "abc" 。

示例 2:

输入:word = "aaa"
输出:6
解释:在每个 "a" 之后依次插入 "b" 和 "c" 可以得到有效字符串 "abcabcabc" 。

示例 3:

输入:word = "abc"
输出:0
解释:word 已经是有效字符串,不需要进行修改。 

提示:

  • 1 <= word.length <= 50
  • word 仅由字母 "a"、"b" 和 "c" 组成。
class Solution {
public:
    int addMinimum(string word) {
        int s=1;
        for(int i=1;i<word.length();i++)if(word[i]<=word[i-1])s++;
        return s*3-word.length();
    }
};

2652. 倍数求和

欧几里得

2654. 使数组所有元素变成 1 的最少操作次数

欧几里得

2660. 保龄球游戏的获胜者

水题

2661. 找出叠涂元素

给你一个下标从 0 开始的整数数组 arr 和一个 m x n 的整数 矩阵 mat 。arr 和 mat 都包含范围 [1,m * n] 内的 所有 整数。

从下标 0 开始遍历 arr 中的每个下标 i ,并将包含整数 arr[i] 的 mat 单元格涂色。

请你找出 arr 中第一个使得 mat 的某一行或某一列都被涂色的元素,并返回其下标 i 。

示例 1:

image explanation for example 1

输入:arr = [1,3,4,2], mat = [[1,4],[2,3]]
输出:2
解释:遍历如上图所示,arr[2] 在矩阵中的第一行或第二列上都被涂色。

示例 2:

image explanation for example 2

输入:arr = [2,8,7,4,1,3,5,6,9], mat = [[3,2,5],[1,4,6],[8,7,9]]
输出:3
解释:遍历如上图所示,arr[3] 在矩阵中的第二列上都被涂色。

提示:

  • m == mat.length
  • n = mat[i].length
  • arr.length == m * n
  • 1 <= m, n <= 105
  • 1 <= m * n <= 105
  • 1 <= arr[i], mat[r][c] <= m * n
  • arr 中的所有整数 互不相同
  • mat 中的所有整数 互不相同
class Solution {
public:
	int firstCompleteIndex(vector<int>& arr, vector<vector<int>>& mat) {
		map<int, int>r, c;
		for (int i = 0; i < mat.size(); i++) {
			for (int j = 0; j < mat[0].size(); j++) {
				r[mat[i][j]] = i, c[mat[i][j]] = j;
			}
		}
		map<int, int>rn, cn;
		for (int i = 0; i < arr.size(); i++) {
			rn[r[arr[i]]]++, cn[c[arr[i]]]++;
			if (rn[r[arr[i]]] >= mat[0].size())return i;
			if (cn[c[arr[i]]] >= mat.size())return i;
		}
		return 0;
	}
};

2663. 字典序最小的美丽字符串

如果一个字符串满足以下条件,则称其为 美丽字符串 :

  • 它由英语小写字母表的前 k 个字母组成。
  • 它不包含任何长度为 2 或更长的回文子字符串。

给你一个长度为 n 的美丽字符串 s 和一个正整数 k 。

请你找出并返回一个长度为 n 的美丽字符串,该字符串还满足:在字典序大于 s 的所有美丽字符串中字典序最小。如果不存在这样的字符串,则返回一个空字符串。

对于长度相同的两个字符串 a 和 b ,如果字符串 a 在与字符串 b 不同的第一个位置上的字符字典序更大,则字符串 a 的字典序大于字符串 b 。

  • 例如,"abcd" 的字典序比 "abcc" 更大,因为在不同的第一个位置(第四个字符)上 d 的字典序大于 c 。

示例 1:

输入:s = "abcz", k = 26
输出:"abda"
解释:字符串 "abda" 既是美丽字符串,又满足字典序大于 "abcz" 。
可以证明不存在字符串同时满足字典序大于 "abcz"、美丽字符串、字典序小于 "abda" 这三个条件。

示例 2:

输入:s = "dc", k = 4
输出:""
解释:可以证明,不存在既是美丽字符串,又字典序大于 "dc" 的字符串。

提示:

  • 1 <= n == s.length <= 105
  • 4 <= k <= 26
  • s 是一个美丽字符串
class Solution {
public:
	string smallestBeautifulString(string s, int k) {
		if (addOneAtLoc(s, k, s.length() - 1))return s;
		return "";
	}
	bool addOneAtLoc(string &s, int k,int loc)
	{
		if (loc < 0)return false;
		char c = 'a';
		c+=k;
		if (++s[loc] == c) {
			s[loc] = 'a';
			if (!addOneAtLoc(s, k, loc - 1))return false;
		}
		if ((loc >= 1 && s[loc] == s[loc - 1]) || (loc >= 2 && s[loc] == s[loc - 2]))
			return addOneAtLoc(s, k, loc);
		return true;
	}
};

2670. 找出不同元素数目差数组

给你一个下标从 0 开始的数组 nums ,数组长度为 n 。

nums 的 不同元素数目差 数组可以用一个长度为 n 的数组 diff 表示,其中 diff[i] 等于前缀 nums[0, ..., i] 中不同元素的数目 减去 后缀 nums[i + 1, ..., n - 1] 中不同元素的数目。

返回 nums 的 不同元素数目差 数组。

注意 nums[i, ..., j] 表示 nums 的一个从下标 i 开始到下标 j 结束的子数组(包含下标 i 和 j 对应元素)。特别需要说明的是,如果 i > j ,则 nums[i, ..., j] 表示一个空子数组。

示例 1:

输入:nums = [1,2,3,4,5]
输出:[-3,-1,1,3,5]
解释:
对于 i = 0,前缀中有 1 个不同的元素,而在后缀中有 4 个不同的元素。因此,diff[0] = 1 - 4 = -3 。
对于 i = 1,前缀中有 2 个不同的元素,而在后缀中有 3 个不同的元素。因此,diff[1] = 2 - 3 = -1 。
对于 i = 2,前缀中有 3 个不同的元素,而在后缀中有 2 个不同的元素。因此,diff[2] = 3 - 2 = 1 。
对于 i = 3,前缀中有 4 个不同的元素,而在后缀中有 1 个不同的元素。因此,diff[3] = 4 - 1 = 3 。
对于 i = 4,前缀中有 5 个不同的元素,而在后缀中有 0 个不同的元素。因此,diff[4] = 5 - 0 = 5 。

示例 2:

输入:nums = [3,2,3,4,2]
输出:[-2,-1,0,2,3]
解释:
对于 i = 0,前缀中有 1 个不同的元素,而在后缀中有 3 个不同的元素。因此,diff[0] = 1 - 3 = -2 。
对于 i = 1,前缀中有 2 个不同的元素,而在后缀中有 3 个不同的元素。因此,diff[1] = 2 - 3 = -1 。
对于 i = 2,前缀中有 2 个不同的元素,而在后缀中有 2 个不同的元素。因此,diff[2] = 2 - 2 = 0 。
对于 i = 3,前缀中有 3 个不同的元素,而在后缀中有 1 个不同的元素。因此,diff[3] = 3 - 1 = 2 。
对于 i = 4,前缀中有 3 个不同的元素,而在后缀中有 0 个不同的元素。因此,diff[4] = 3 - 0 = 3 。 

提示:

  • 1 <= n == nums.length <= 50
  • 1 <= nums[i] <= 50
class Solution {
public:
    vector<int> distinctDifferenceArray(vector<int>& nums) {
        set<int>s;
        vector<int>v1;
        for(int i=0;i<nums.size();i++){
            s.insert(nums[i]);
            v1.push_back(s.size());
        }
        s.clear();
        for(int i=nums.size()-1;i;i--){
            s.insert(nums[i]);
            v1[i-1]-=s.size();
        }
        return v1;
    }
};

2671. 频率跟踪器

请你设计并实现一个能够对其中的值进行跟踪的数据结构,并支持对频率相关查询进行应答。

实现 FrequencyTracker 类:

  • FrequencyTracker():使用一个空数组初始化 FrequencyTracker 对象。
  • void add(int number):添加一个 number 到数据结构中。
  • void deleteOne(int number):从数据结构中删除一个 number 。数据结构 可能不包含 number ,在这种情况下不删除任何内容。
  • bool hasFrequency(int frequency): 如果数据结构中存在出现 frequency 次的数字,则返回 true,否则返回 false

示例 1:

输入
["FrequencyTracker", "add", "add", "hasFrequency"]
[[], [3], [3], [2]]
输出
[null, null, null, true]

解释
FrequencyTracker frequencyTracker = new FrequencyTracker();
frequencyTracker.add(3); // 数据结构现在包含 [3]
frequencyTracker.add(3); // 数据结构现在包含 [3, 3]
frequencyTracker.hasFrequency(2); // 返回 true ,因为 3 出现 2 次

示例 2:

输入
["FrequencyTracker", "add", "deleteOne", "hasFrequency"]
[[], [1], [1], [1]]
输出
[null, null, null, false]

解释
FrequencyTracker frequencyTracker = new FrequencyTracker();
frequencyTracker.add(1); // 数据结构现在包含 [1]
frequencyTracker.deleteOne(1); // 数据结构现在为空 []
frequencyTracker.hasFrequency(1); // 返回 false ,因为数据结构为空

示例 3:

输入
["FrequencyTracker", "hasFrequency", "add", "hasFrequency"]
[[], [2], [3], [1]]
输出
[null, false, null, true]

解释
FrequencyTracker frequencyTracker = new FrequencyTracker();
frequencyTracker.hasFrequency(2); // 返回 false ,因为数据结构为空
frequencyTracker.add(3); // 数据结构现在包含 [3]
frequencyTracker.hasFrequency(1); // 返回 true ,因为 3 出现 1 次

提示:

  • 1 <= number <= 105
  • 1 <= frequency <= 105
  • 最多调用 adddeleteOne 和 hasFrequency 共计 2 * 105 次
class FrequencyTracker {
public:
    FrequencyTracker() {
        m.clear();
        m2.clear();
    }

    void add(int number) {
        m2[m[number]++]--;
        m2[m[number]]++;
    }

    void deleteOne(int number) {
        if (m[number]) {
            m2[m[number]--]--;
            m2[m[number]]++;
        }
    }

    bool hasFrequency(int frequency) {
        return m2[frequency];
    }
private:
    map<int, int>m;
    map<int, int>m2;
};

2673. 使二叉树所有路径值相等的最小代价

二叉树DFS

2679. 矩阵中的和

水题

2680. 最大或值

环非域

2681. 英雄的力量

排列组合

2682. 找出转圈游戏输家

n 个朋友在玩游戏。这些朋友坐成一个圈,按 顺时针方向 从 1 到 n 编号。从第 i 个朋友的位置开始顺时针移动 1 步会到达第 (i + 1) 个朋友的位置(1 <= i < n),而从第 n 个朋友的位置开始顺时针移动 1 步会回到第 1 个朋友的位置。

游戏规则如下:

第 1 个朋友接球。

  • 接着,第 1 个朋友将球传给距离他顺时针方向 k 步的朋友。
  • 然后,接球的朋友应该把球传给距离他顺时针方向 2 * k 步的朋友。
  • 接着,接球的朋友应该把球传给距离他顺时针方向 3 * k 步的朋友,以此类推。

换句话说,在第 i 轮中持有球的那位朋友需要将球传递给距离他顺时针方向 i * k 步的朋友。

当某个朋友第 2 次接到球时,游戏结束。

在整场游戏中没有接到过球的朋友是 输家 。

给你参与游戏的朋友数量 n 和一个整数 k ,请按升序排列返回包含所有输家编号的数组 answer 作为答案。

示例 1:

输入:n = 5, k = 2
输出:[4,5]
解释:以下为游戏进行情况:
1)第 1 个朋友接球,第 1 个朋友将球传给距离他顺时针方向 2 步的玩家 —— 第 3 个朋友。
2)第 3 个朋友将球传给距离他顺时针方向 4 步的玩家 —— 第 2 个朋友。
3)第 2 个朋友将球传给距离他顺时针方向 6 步的玩家 —— 第 3 个朋友。
4)第 3 个朋友接到两次球,游戏结束。

示例 2:

输入:n = 4, k = 4
输出:[2,3,4]
解释:以下为游戏进行情况:
1)第 1 个朋友接球,第 1 个朋友将球传给距离他顺时针方向 4 步的玩家 —— 第 1 个朋友。
2)第 1 个朋友接到两次球,游戏结束。

提示:

  • 1 <= k <= n <= 50
class Solution {
public:
	vector<int> circularGameLosers(int n, int k) {
		map<int, int>m;
		for (int i = 0;; i++)
		{
			int a = ((i*i + i) / 2 * k + 1) % n;
			if (m[a])break;
			m[a] = 1;
		}
		vector<int>ans;
		for (int i = 1; i < n; i++) {
			if (m[i] == 0)ans.push_back(i);
		}
		if (m[0] == 0)ans.push_back(n);
		return ans;
	}
};

2684. 矩阵中移动的最大次数

二维DP

2696. 删除子串后的字符串最小长度

给你一个仅由 大写 英文字符组成的字符串 s 。

你可以对此字符串执行一些操作,在每一步操作中,你可以从 s 中删除 任一个 "AB" 或 "CD" 子字符串。

通过执行操作,删除所有 "AB" 和 "CD" 子串,返回可获得的最终字符串的 最小 可能长度。

注意,删除子串后,重新连接出的字符串可能会产生新的 "AB" 或 "CD" 子串。

示例 1:

输入:s = "ABFCACDB"
输出:2
解释:你可以执行下述操作:
- 从 "ABFCACDB" 中删除子串 "AB",得到 s = "FCACDB" 。
- 从 "FCACDB" 中删除子串 "CD",得到 s = "FCAB" 。
- 从 "FCAB" 中删除子串 "AB",得到 s = "FC" 。
最终字符串的长度为 2 。
可以证明 2 是可获得的最小长度。

示例 2:

输入:s = "ACBBD"
输出:5
解释:无法执行操作,字符串长度不变。

提示:

  • 1 <= s.length <= 100
  • s 仅由大写英文字母组成
class Solution {
public:
    int minLength(string s) {
        for(int i=0;i+1<s.length();i++){
            if((s[i]=='A'&&s[i+1]=='B')||(s[i]=='C'&&s[i+1]=='D')){
                string s1="",s2="";
                if(i)s1=s.substr(0,i);
                if(s.length()-i-2)s2=s.substr(i+2,s.length()-i-2);
                return minLength(s1+s2);
            }
        }
        return s.length();
    }
};

2697. 字典序最小回文串

给你一个由 小写英文字母 组成的字符串 s ,你可以对其执行一些操作。在一步操作中,你可以用其他小写英文字母 替换  s 中的一个字符。

请你执行 尽可能少的操作 ,使 s 变成一个 回文串 。如果执行 最少 操作次数的方案不止一种,则只需选取 字典序最小 的方案。

对于两个长度相同的字符串 a 和 b ,在 a 和 b 出现不同的第一个位置,如果该位置上 a 中对应字母比 b 中对应字母在字母表中出现顺序更早,则认为 a 的字典序比 b 的字典序要小。

返回最终的回文字符串。

示例 1:

输入:s = "egcfe"
输出:"efcfe"
解释:将 "egcfe" 变成回文字符串的最小操作次数为 1 ,修改 1 次得到的字典序最小回文字符串是 "efcfe",只需将 'g' 改为 'f' 。

示例 2:

输入:s = "abcd"
输出:"abba"
解释:将 "abcd" 变成回文字符串的最小操作次数为 2 ,修改 2 次得到的字典序最小回文字符串是 "abba" 。

示例 3:

输入:s = "seven"
输出:"neven"
解释:将 "seven" 变成回文字符串的最小操作次数为 1 ,修改 1 次得到的字典序最小回文字符串是 "neven" 。

提示:

  • 1 <= s.length <= 1000
  • s 仅由小写英文字母组成
class Solution {
public:
    string makeSmallestPalindrome(string s) {
        for(int i=0,j=s.length()-1;i<j;i++,j--){
            s[i]=s[j]=min(s[i],s[j]);
        }
        return s;
    }
};

2703. 返回传递的参数的长度

JS实战

2706. 购买两块巧克力

给你一个整数数组 prices ,它表示一个商店里若干巧克力的价格。同时给你一个整数 money ,表示你一开始拥有的钱数。

你必须购买 恰好 两块巧克力,而且剩余的钱数必须是 非负数 。同时你想最小化购买两块巧克力的总花费。

请你返回在购买两块巧克力后,最多能剩下多少钱。如果购买任意两块巧克力都超过了你拥有的钱,请你返回 money 。注意剩余钱数必须是非负数。

示例 1:

输入:prices = [1,2,2], money = 3
输出:0
解释:分别购买价格为 1 和 2 的巧克力。你剩下 3 - 3 = 0 块钱。所以我们返回 0 。

示例 2:

输入:prices = [3,2,3], money = 3
输出:3
解释:购买任意 2 块巧克力都会超过你拥有的钱数,所以我们返回 3 。

提示:

  • 2 <= prices.length <= 50
  • 1 <= prices[i] <= 100
  • 1 <= money <= 100
class Solution {
public:
    int buyChoco(vector<int>& prices, int money) {
        int a=prices[0],b=prices[1];
        for(int i=2;i<prices.size();i++){
            int c=prices[i];
            if(b>c)b^=c^=b^=c;
            if(a>c)a^=c^=a^=c;
        }
        if(a+b<=money)return money-a-b;
        return money;
    }
};

2707. 字符串中的额外字符

区间DP

2708. 一个小组的最大实力值

贪心

2709. 最大公约数遍历

因式分解

2710. 移除字符串中的尾随零

水题

2717. 半有序排列

给你一个下标从 0 开始、长度为 n 的整数排列 nums 。

如果排列的第一个数字等于 1 且最后一个数字等于 n ,则称其为 半有序排列 。你可以执行多次下述操作,直到将 nums 变成一个 半有序排列 :

  • 选择 nums 中相邻的两个元素,然后交换它们。

返回使 nums 变成 半有序排列 所需的最小操作次数。

排列 是一个长度为 n 的整数序列,其中包含从 1 到 n 的每个数字恰好一次。

示例 1:

输入:nums = [2,1,4,3]
输出:2
解释:可以依次执行下述操作得到半有序排列:
1 - 交换下标 0 和下标 1 对应元素。排列变为 [1,2,4,3] 。
2 - 交换下标 2 和下标 3 对应元素。排列变为 [1,2,3,4] 。
可以证明,要让 nums 成为半有序排列,不存在执行操作少于 2 次的方案。

示例 2:

输入:nums = [2,4,1,3]
输出:3
解释:
可以依次执行下述操作得到半有序排列:
1 - 交换下标 1 和下标 2 对应元素。排列变为 [2,1,4,3] 。
2 - 交换下标 0 和下标 1 对应元素。排列变为 [1,2,4,3] 。
3 - 交换下标 2 和下标 3 对应元素。排列变为 [1,2,3,4] 。
可以证明,要让 nums 成为半有序排列,不存在执行操作少于 3 次的方案。

示例 3:

输入:nums = [1,3,4,2,5]
输出:0
解释:这个排列已经是一个半有序排列,无需执行任何操作。

提示:

  • 2 <= nums.length == n <= 50
  • 1 <= nums[i] <= 50
  • nums 是一个 排列
class Solution {
public:
	int semiOrderedPermutation(vector<int>& nums) {
		int a = 0, b = 0;
		for (int i = 0; i < nums.size(); i++) {
			if (nums[i] == 1)a = i;
			if (nums[i] == nums.size())b = i;
		}
		return a + nums.size() - 1 - b - (a > b);
	}
};

2718. 查询后矩阵的和

rust

2719. 统计整数数目

数位DP

2728. 计算一个环形街道上的房屋数量

给定一个代表环形街道的类 Street 和一个正整数 k,表示街道上房屋的最大数量(也就是说房屋数量不超过 k )。每个房屋的门初始时可以是开着的也可以是关着的。

刚开始,你站在一座房子的门前。你的任务是计算街道上的房屋数量。

Street 类包含以下函数:

  • void openDoor() :打开当前房屋的门。
  • void closeDoor() :关闭当前房屋的门。
  • boolean isDoorOpen() :如果当前房屋的门是开着的返回 true ,否则返回 false 。
  • void moveRight() :向右移动到下一座房屋。
  • void moveLeft() :向左移动到上一座房屋。

返回 ans,它表示街道上的房屋数量。

示例 1:

输入:street = [0,0,0,0], k = 10
输出:4
解释:街道上有 4 座房屋,它们的门都是关着的。
房屋数量小于 k,即 10。

示例 2:

输入:street = [1,0,1,1,0], k = 5
输出:5
解释:街道上有 5 座房屋,向右移动时第 1、3 和 4 座房屋的门是开着的,其余的门都是关着的。房屋数量等于 k,即 5。

解释:

  • n  是房屋数量
  • 1 <= n <= k <= 103
class Solution {
public:
	int houseCount(Street* opt, int k)
	{
		while (k--)opt->closeDoor(),opt->moveRight();
		opt->openDoor();
		int ans = 0;
		while (++ans) {
			opt->moveRight();
			if (opt->isDoorOpen())return ans;
		}
		return 0;
	}
};

2729. 判断一个数是否迷人

水题

2731. 移动机器人

算两次

2735. 收集巧克力

给你一个长度为 n 、下标从 0 开始的整数数组 nums ,表示收集不同巧克力的成本。每个巧克力都对应一个不同的类型,最初,位于下标 i 的巧克力就对应第 i 个类型。

在一步操作中,你可以用成本 x 执行下述行为:

  • 同时修改所有巧克力的类型,将巧克力的类型 ith 修改为类型 ((i + 1) mod n)th

假设你可以执行任意次操作,请返回收集所有类型巧克力所需的最小成本。

示例 1:

输入:nums = [20,1,15], x = 5
输出:13
解释:最开始,巧克力的类型分别是 [0,1,2] 。我们可以用成本 1 购买第 1 个类型的巧克力。
接着,我们用成本 5 执行一次操作,巧克力的类型变更为 [1,2,0] 。我们可以用成本 1 购买第 2 个类型的巧克力。
然后,我们用成本 5 执行一次操作,巧克力的类型变更为 [2,0,1] 。我们可以用成本 1 购买第 0 个类型的巧克力。
因此,收集所有类型的巧克力需要的总成本是 (1 + 5 + 1 + 5 + 1) = 13 。可以证明这是一种最优方案。

示例 2:

输入:nums = [1,2,3], x = 4
输出:6
解释:我们将会按最初的成本收集全部三个类型的巧克力,而不需执行任何操作。因此,收集所有类型的巧克力需要的总成本是 1 + 2 + 3 = 6 。

提示:

  • 1 <= nums.length <= 1000
  • 1 <= nums[i] <= 109
  • 1 <= x <= 109
class Solution {
public:
    long long minCost(vector<int>& nums, int x) {
        vector<int>v=nums;
        long long ret=1234567890000;
        for(long long k=0;k<nums.size();k++){
            long long ans=k*x;
            for(int i=0;i<nums.size();i++){
                ans+=v[i];
            }
            ret = min(ret,ans);
            vector<int>v2=v;
            for(int i=0;i<nums.size();i++){
                v2[i]=min(nums[i],v[(i+1)%v.size()]);
            }
            v=v2;
        }
        return ret;
    }
};

2739. 总行驶距离

水题

2740. 找出分区值

给你一个  整数数组 nums 。

将 nums 分成两个数组:nums1 和 nums2 ,并满足下述条件:

  • 数组 nums 中的每个元素都属于数组 nums1 或数组 nums2 。
  • 两个数组都 非空 。
  • 分区值 最小 。

分区值的计算方法是 |max(nums1) - min(nums2)| 。

其中,max(nums1) 表示数组 nums1 中的最大元素,min(nums2) 表示数组 nums2 中的最小元素。

返回表示分区值的整数。

示例 1:

输入:nums = [1,3,2,4]
输出:1
解释:可以将数组 nums 分成 nums1 = [1,2] 和 nums2 = [3,4] 。
- 数组 nums1 的最大值等于 2 。
- 数组 nums2 的最小值等于 3 。
分区值等于 |2 - 3| = 1 。
可以证明 1 是所有分区方案的最小值。

示例 2:

输入:nums = [100,1,10]
输出:9
解释:可以将数组 nums 分成 nums1 = [10] 和 nums2 = [100,1] 。 
- 数组 nums1 的最大值等于 10 。 
- 数组 nums2 的最小值等于 1 。 
分区值等于 |10 - 1| = 9 。 
可以证明 9 是所有分区方案的最小值。

提示:

  • 2 <= nums.length <= 105
  • 1 <= nums[i] <= 109
class Solution {
public:
    int findValueOfPartition(vector<int>& nums) {
        sort(nums.begin(),nums.end());
        int ans=nums[1]-nums[0];
        for(int i=2;i<nums.size();i++)ans=min(ans,nums[i]-nums[i-1]);
        return ans;
    }
};

2742. 给墙壁刷油漆

01背包

2744. 最大字符串配对数目

给你一个下标从 0 开始的数组 words ,数组中包含 互不相同 的字符串。

如果字符串 words[i] 与字符串 words[j] 满足以下条件,我们称它们可以匹配:

  • 字符串 words[i] 等于 words[j] 的反转字符串。
  • 0 <= i < j < words.length

请你返回数组 words 中的 最大 匹配数目。

注意,每个字符串最多匹配一次。

示例 1:

输入:words = ["cd","ac","dc","ca","zz"]
输出:2
解释:在此示例中,我们可以通过以下方式匹配 2 对字符串:
- 我们将第 0 个字符串与第 2 个字符串匹配,因为 word[0] 的反转字符串是 "dc" 并且等于 words[2]。
- 我们将第 1 个字符串与第 3 个字符串匹配,因为 word[1] 的反转字符串是 "ca" 并且等于 words[3]。
可以证明最多匹配数目是 2 。

示例 2:

输入:words = ["ab","ba","cc"]
输出:1
解释:在此示例中,我们可以通过以下方式匹配 1 对字符串:
- 我们将第 0 个字符串与第 1 个字符串匹配,因为 words[1] 的反转字符串 "ab" 与 words[0] 相等。
可以证明最多匹配数目是 1 。

示例 3:

输入:words = ["aa","ab"]
输出:0
解释:这个例子中,无法匹配任何字符串。

提示:

  • 1 <= words.length <= 50
  • words[i].length == 2
  • words 包含的字符串互不相同。
  • words[i] 只包含小写英文字母。
class Solution {
public:
    int maximumNumberOfStringPairs(vector<string>& words) {
        set<string>s;
        int ans=0;
        for(auto str:words){
            string r=str;
            reverse(r.begin(),r.end());
            if(s.find(r)!=s.end())ans++;
            s.insert(str);
        }
        return ans;
    }
};

2745. 构造最长的新字符串

给你三个整数 x ,y 和 z 。

这三个整数表示你有 x 个 "AA" 字符串,y 个 "BB" 字符串,和 z 个 "AB" 字符串。你需要选择这些字符串中的部分字符串(可以全部选择也可以一个都不选择),将它们按顺序连接得到一个新的字符串。新字符串不能包含子字符串 "AAA" 或者 "BBB" 。

请你返回 新字符串的最大可能长度。

子字符串 是一个字符串中一段连续 非空 的字符序列。

示例 1:

输入:x = 2, y = 5, z = 1
输出:12
解释: 我们可以按顺序连接 "BB" ,"AA" ,"BB" ,"AA" ,"BB" 和 "AB" ,得到新字符串 "BBAABBAABBAB" 。
字符串长度为 12 ,无法得到一个更长的符合题目要求的字符串。

示例 2:

输入:x = 3, y = 2, z = 2
输出:14
解释:我们可以按顺序连接 "AB" ,"AB" ,"AA" ,"BB" ,"AA" ,"BB" 和 "AA" ,得到新字符串 "ABABAABBAABBAA" 。
字符串长度为 14 ,无法得到一个更长的符合题目要求的字符串。

提示:

  • 1 <= x, y, z <= 50
class Solution {
public:
	int longestString(int x, int y, int z) {
		if (x == y)return z * 2 + x * 4;
		return z * 2 + min(x, y) * 4 + 2;
	}
};

2748. 美丽下标对的数目

欧几里得

2749. 得到整数零需要执行的最少操作数

二进制

2760. 最长奇偶子数组

给你一个下标从 0 开始的整数数组 nums 和一个整数 threshold 。

请你从 nums 的子数组中找出以下标 l 开头、下标 r 结尾 (0 <= l <= r < nums.length) 且满足以下条件的 最长子数组 :

  • nums[l] % 2 == 0
  • 对于范围 [l, r - 1] 内的所有下标 i ,nums[i] % 2 != nums[i + 1] % 2
  • 对于范围 [l, r] 内的所有下标 i ,nums[i] <= threshold

以整数形式返回满足题目要求的最长子数组的长度。

注意:子数组 是数组中的一个连续非空元素序列。

示例 1:

输入:nums = [3,2,5,4], threshold = 5
输出:3
解释:在这个示例中,我们选择从 l = 1 开始、到 r = 3 结束的子数组 => [2,5,4] ,满足上述条件。
因此,答案就是这个子数组的长度 3 。可以证明 3 是满足题目要求的最大长度。

示例 2:

输入:nums = [1,2], threshold = 2
输出:1
解释:
在这个示例中,我们选择从 l = 1 开始、到 r = 1 结束的子数组 => [2] 。
该子数组满足上述全部条件。可以证明 1 是满足题目要求的最大长度。

示例 3:

输入:nums = [2,3,4,5], threshold = 4
输出:3
解释:
在这个示例中,我们选择从 l = 0 开始、到 r = 2 结束的子数组 => [2,3,4] 。 
该子数组满足上述全部条件。
因此,答案就是这个子数组的长度 3 。可以证明 3 是满足题目要求的最大长度。

提示:

  • 1 <= nums.length <= 100
  • 1 <= nums[i] <= 100
  • 1 <= threshold <= 100
class Solution {
public:
    int longestAlternatingSubarray(vector<int>& nums, int threshold) {
        int low=-1,ans=0;
        for(int i=0;i<=nums.size();i++){
            if(i==nums.size() || nums[i]>threshold){
                if(low>=0)ans=max(ans,i-low);
                low = -1;
                continue;
            }
            if(i > low && low >= 0 && nums[i]% 2 == nums[i-1]%2){
                ans=max(ans,i-low);
                low = -1;
            }
            if (low == -1 && nums[i]%2==0)low = i;
        }        
        return ans;
    }
};

2761. 和等于目标值的质数对

素数筛法

2765. 最长交替子数组

给你一个下标从 0 开始的整数数组 nums 。如果 nums 中长度为 m 的子数组 s 满足以下条件,我们称它是一个 交替子数组 :

  • m 大于 1 。
  • s1 = s0 + 1 。
  • 下标从 0 开始的子数组 s 与数组 [s0, s1, s0, s1,...,s(m-1) % 2] 一样。也就是说,s1 - s0 = 1 ,s2 - s1 = -1 ,s3 - s2 = 1 ,s4 - s3 = -1 ,以此类推,直到 s[m - 1] - s[m - 2] = (-1)m 。

请你返回 nums 中所有 交替 子数组中,最长的长度,如果不存在交替子数组,请你返回 -1 。

子数组是一个数组中一段连续 非空 的元素序列。

示例 1:

输入:nums = [2,3,4,3,4]
输出:4
解释:交替子数组有 [3,4] ,[3,4,3] 和 [3,4,3,4] 。最长的子数组为 [3,4,3,4] ,长度为4 。

示例 2:

输入:nums = [4,5,6]
输出:2
解释:[4,5] 和 [5,6] 是仅有的两个交替子数组。它们长度都为 2 。

提示:

  • 2 <= nums.length <= 100
  • 1 <= nums[i] <= 104
class Solution {
public:
	int alternatingSubarray(vector<int>& v) {
		for (int i = v.size()-1; i ; i--) {
			v[i] -= v[i - 1];
		}
		v[0] = 123456;
		int ans = 0, n = 0;
		for(int i=1;i<v.size();i++){
			if (v[i] == 1) {
				if (n && v[i - 1] == -1)n++;
				else n = 1;
			}
			else if (v[i] == -1) {
				if (v[i - 1] == 1)n++;
				else n = 0;
			}
			else n = 0;
			ans = max(ans, n);
		}
		return ans ? ans + 1 : -1;
	}
};

2766. 重新放置石块

给你一个下标从 0 开始的整数数组 nums ,表示一些石块的初始位置。再给你两个长度 相等 下标从 0 开始的整数数组 moveFrom 和 moveTo 。

在 moveFrom.length 次操作内,你可以改变石块的位置。在第 i 次操作中,你将位置在 moveFrom[i] 的所有石块移到位置 moveTo[i] 。

完成这些操作后,请你按升序返回所有  石块的位置。

注意:

  • 如果一个位置至少有一个石块,我们称这个位置  石块。
  • 一个位置可能会有多个石块。

示例 1:

输入:nums = [1,6,7,8], moveFrom = [1,7,2], moveTo = [2,9,5]
输出:[5,6,8,9]
解释:一开始,石块在位置 1,6,7,8 。
第 i = 0 步操作中,我们将位置 1 处的石块移到位置 2 处,位置 2,6,7,8 有石块。
第 i = 1 步操作中,我们将位置 7 处的石块移到位置 9 处,位置 2,6,8,9 有石块。
第 i = 2 步操作中,我们将位置 2 处的石块移到位置 5 处,位置 5,6,8,9 有石块。
最后,至少有一个石块的位置为 [5,6,8,9] 。

示例 2:

输入:nums = [1,1,3,3], moveFrom = [1,3], moveTo = [2,2]
输出:[2]
解释:一开始,石块在位置 [1,1,3,3] 。
第 i = 0 步操作中,我们将位置 1 处的石块移到位置 2 处,有石块的位置为 [2,2,3,3] 。
第 i = 1 步操作中,我们将位置 3 处的石块移到位置 2 处,有石块的位置为 [2,2,2,2] 。
由于 2 是唯一有石块的位置,我们返回 [2] 。

提示:

  • 1 <= nums.length <= 105
  • 1 <= moveFrom.length <= 105
  • moveFrom.length == moveTo.length
  • 1 <= nums[i], moveFrom[i], moveTo[i] <= 109
  • 测试数据保证在进行第 i 步操作时,moveFrom[i] 处至少有一个石块。
class Solution {
public:
    vector<int> relocateMarbles(vector<int>& nums, vector<int>& moveFrom, vector<int>& moveTo) {
        map<int,int>m;
        for(auto x:nums)m[x]=1;
        for(int i=0;i<moveFrom.size();i++){
            m[moveFrom[i]]=0,m[moveTo[i]]=1;
        }
        vector<int>v;
        for(auto mi:m){
            if(mi.second)v.push_back(mi.first);
        }
        return v;
    }
};

2769. 找出最大的可达成数字

水题

2778. 特殊元素平方和

其他数论问题

2779. 数组的最大美丽值

给你一个下标从 0 开始的整数数组 nums 和一个 非负 整数 k 。

在一步操作中,你可以执行下述指令:

  • 在范围 [0, nums.length - 1] 中选择一个 此前没有选过 的下标 i 。
  • 将 nums[i] 替换为范围 [nums[i] - k, nums[i] + k] 内的任一整数。

数组的 美丽值 定义为数组中由相等元素组成的最长子序列的长度。

对数组 nums 执行上述操作任意次后,返回数组可能取得的 最大 美丽值。

注意:你  能对每个下标执行 一次 此操作。

数组的 子序列 定义是:经由原数组删除一些元素(也可能不删除)得到的一个新数组,且在此过程中剩余元素的顺序不发生改变。

示例 1:

输入:nums = [4,6,1,2], k = 2
输出:3
解释:在这个示例中,我们执行下述操作:
- 选择下标 1 ,将其替换为 4(从范围 [4,8] 中选出),此时 nums = [4,4,1,2] 。
- 选择下标 3 ,将其替换为 4(从范围 [0,4] 中选出),此时 nums = [4,4,1,4] 。
执行上述操作后,数组的美丽值是 3(子序列由下标 0 、1 、3 对应的元素组成)。
可以证明 3 是我们可以得到的由相等元素组成的最长子序列长度。

示例 2:

输入:nums = [1,1,1,1], k = 10
输出:4
解释:在这个示例中,我们无需执行任何操作。
数组 nums 的美丽值是 4(整个数组)。

提示:

  • 1 <= nums.length <= 105
  • 0 <= nums[i], k <= 105
class Solution {
public:
	int maximumBeauty(vector<int>& nums, int k) {
		sort(nums.begin(), nums.end());
		k += k;
		int ans = 0;
		for (int i = 0, j = 0; j < nums.size(); j++) {
			while (nums[j] - nums[i] > k)i++;
			ans = max(ans, j - i + 1);
		}
		return ans;
	}
};

2788. 按分隔符拆分字符串

给你一个字符串数组 words 和一个字符 separator ,请你按 separator 拆分 words 中的每个字符串。

返回一个由拆分后的新字符串组成的字符串数组,不包括空字符串 。

注意

  • separator 用于决定拆分发生的位置,但它不包含在结果字符串中。
  • 拆分可能形成两个以上的字符串。
  • 结果字符串必须保持初始相同的先后顺序。

示例 1:

输入:words = ["one.two.three","four.five","six"], separator = "."
输出:["one","two","three","four","five","six"]
解释:在本示例中,我们进行下述拆分:

"one.two.three" 拆分为 "one", "two", "three"
"four.five" 拆分为 "four", "five"
"six" 拆分为 "six" 

因此,结果数组为 ["one","two","three","four","five","six"] 。

示例 2:

输入:words = ["$easy$","$problem$"], separator = "$"
输出:["easy","problem"]
解释:在本示例中,我们进行下述拆分:

"$easy$" 拆分为 "easy"(不包括空字符串)
"$problem$" 拆分为 "problem"(不包括空字符串)

因此,结果数组为 ["easy","problem"] 。

示例 3:

输入:words = ["|||"], separator = "|"
输出:[]
解释:在本示例中,"|||" 的拆分结果将只包含一些空字符串,所以我们返回一个空数组 [] 。 

提示:

  • 1 <= words.length <= 100
  • 1 <= words[i].length <= 20
  • words[i] 中的字符要么是小写英文字母,要么就是字符串 ".,|$#@" 中的字符(不包括引号)
  • separator 是字符串 ".,|$#@" 中的某个字符(不包括引号)
class Solution {
public:
    vector<string> splitWordsBySeparator(vector<string>& words, char separator) {
        vector<string>ans;
        for(auto s:words){
            ans=fvecJoin(ans,stringSplit(s,separator));
        }
        return ans;
    }
};

2789. 合并后数组中的最大元素

贪心

2798. 满足目标工作时长的员工数目

公司里共有 n 名员工,按从 0 到 n - 1 编号。每个员工 i 已经在公司工作了 hours[i] 小时。

公司要求每位员工工作 至少 target 小时。

给你一个下标从 0 开始、长度为 n 的非负整数数组 hours 和一个非负整数 target 。

请你用整数表示并返回工作至少 target 小时的员工数。

示例 1:

输入:hours = [0,1,2,3,4], target = 2
输出:3
解释:公司要求每位员工工作至少 2 小时。
- 员工 0 工作 0 小时,不满足要求。
- 员工 1 工作 1 小时,不满足要求。
- 员工 2 工作 2 小时,满足要求。
- 员工 3 工作 3 小时,满足要求。
- 员工 4 工作 4 小时,满足要求。
共有 3 位满足要求的员工。

示例 2:

输入:hours = [5,1,4,2,2], target = 6
输出:0
解释:公司要求每位员工工作至少 6 小时。
共有 0 位满足要求的员工。

提示:

  • 1 <= n == hours.length <= 50
  • 0 <= hours[i], target <= 105
class Solution {
public:
    int numberOfEmployeesWhoMetTarget(vector<int>& hours, int target) {
        int s=0;
        for(auto x:hours)if(x>=target)s++;
        return s;
    }
};

2802. 找出第 K 个幸运数字

二进制

2806. 取整购买后的账户余额

一开始,你的银行账户里有 100 块钱。

给你一个整数purchaseAmount ,它表示你在一次购买中愿意支出的金额。

在一个商店里,你进行一次购买,实际支出的金额会向 最近 的 10 的 倍数 取整。换句话说,你实际会支付一个 非负 金额 roundedAmount ,满足 roundedAmount 是 10 的倍数且 abs(roundedAmount - purchaseAmount) 的值 最小 。

如果存在多于一个最接近的 10 的倍数,较大的倍数 是你的实际支出金额。

请你返回一个整数,表示你在愿意支出金额为 purchaseAmount 块钱的前提下,购买之后剩下的余额。

注意: 0 也是 10 的倍数。

示例 1:

输入:purchaseAmount = 9
输出:90
解释:这个例子中,最接近 9 的 10 的倍数是 10 。所以你的账户余额为 100 - 10 = 90 。

示例 2:

输入:purchaseAmount = 15
输出:80
解释:这个例子中,有 2 个最接近 15 的 10 的倍数:10 和 20,较大的数 20 是你的实际开销。
所以你的账户余额为 100 - 20 = 80 。

提示:

  • 0 <= purchaseAmount <= 100
class Solution {
public:
    int accountBalanceAfterPurchase(int x) {
        return 100-(x+5)/10*10;
    }
};

2807. 在链表中插入最大公约数

欧几里得

2808. 使循环数组所有元素相等的最少秒数

给你一个下标从 0 开始长度为 n 的数组 nums 。

每一秒,你可以对数组执行以下操作:

  • 对于范围在 [0, n - 1] 内的每一个下标 i ,将 nums[i] 替换成 nums[i] ,nums[(i - 1 + n) % n] 或者 nums[(i + 1) % n] 三者之一。

注意,所有元素会被同时替换。

请你返回将数组 nums 中所有元素变成相等元素所需要的 最少 秒数。

示例 1:

输入:nums = [1,2,1,2]
输出:1
解释:我们可以在 1 秒内将数组变成相等元素:
- 第 1 秒,将每个位置的元素分别变为 [nums[3],nums[1],nums[3],nums[3]] 。变化后,nums = [2,2,2,2] 。
1 秒是将数组变成相等元素所需要的最少秒数。

示例 2:

输入:nums = [2,1,3,3,2]
输出:2
解释:我们可以在 2 秒内将数组变成相等元素:
- 第 1 秒,将每个位置的元素分别变为 [nums[0],nums[2],nums[2],nums[2],nums[3]] 。变化后,nums = [2,3,3,3,3] 。
- 第 2 秒,将每个位置的元素分别变为 [nums[1],nums[1],nums[2],nums[3],nums[4]] 。变化后,nums = [3,3,3,3,3] 。
2 秒是将数组变成相等元素所需要的最少秒数。

示例 3:

输入:nums = [5,5,5,5]
输出:0
解释:不需要执行任何操作,因为一开始数组中的元素已经全部相等。

提示:

  • 1 <= n == nums.length <= 105
  • 1 <= nums[i] <= 109
class Solution {
public:
    int minimumSeconds(vector<int>& nums) {
        map<int,vector<int>>m;
        for(int i=0;i<nums.size();i++)m[nums[i]].push_back(i);
        int ans=nums.size();
        for(auto &mi:m)ans=min(ans, f(nums.size(),mi.second));
        return ans;
    }
    int f(int n, vector<int>&v){
        if(v.size()<2)return n/2;
        int ans=v[0]+n-v[v.size()-1];
        for(int i=1;i<v.size();i++)ans=max(ans,v[i]-v[i-1]);
        return ans/2;
    }
};

2809. 使数组和小于等于 x 的最少时间

高维DP

2810. 故障键盘

你的笔记本键盘存在故障,每当你在上面输入字符 'i' 时,它会反转你所写的字符串。而输入其他字符则可以正常工作。

给你一个下标从 0 开始的字符串 s ,请你用故障键盘依次输入每个字符。

返回最终笔记本屏幕上输出的字符串。

示例 1:

输入:s = "string"
输出:"rtsng"
解释:
输入第 1 个字符后,屏幕上的文本是:"s" 。
输入第 2 个字符后,屏幕上的文本是:"st" 。
输入第 3 个字符后,屏幕上的文本是:"str" 。
因为第 4 个字符是 'i' ,屏幕上的文本被反转,变成 "rts" 。
输入第 5 个字符后,屏幕上的文本是:"rtsn" 。
输入第 6 个字符后,屏幕上的文本是: "rtsng" 。
因此,返回 "rtsng" 。

示例 2:

输入:s = "poiinter"
输出:"ponter"
解释:
输入第 1 个字符后,屏幕上的文本是:"p" 。
输入第 2 个字符后,屏幕上的文本是:"po" 。
因为第 3 个字符是 'i' ,屏幕上的文本被反转,变成 "op" 。
因为第 4 个字符是 'i' ,屏幕上的文本被反转,变成 "po" 。
输入第 5 个字符后,屏幕上的文本是:"pon" 。
输入第 6 个字符后,屏幕上的文本是:"pont" 。
输入第 7 个字符后,屏幕上的文本是:"ponte" 。
输入第 8 个字符后,屏幕上的文本是:"ponter" 。
因此,返回 "ponter" 。

提示:

  • 1 <= s.length <= 100
  • s 由小写英文字母组成
  • s[0] != 'i'
class Solution {
public:
	string finalString(string s) {
		string ans = "";
		for (auto c : s) {
			if (c == 'i') {
				auto v = StringToCharVec(ans);				
				reverse(v.begin(), v.end());
				v.push_back(0);
				ans = CharToString(v);
			}
			else ans += c;
		}
		return ans;
	}
};

2815. 数组中的最大数对和

其他数论问题

2818. 操作使得分最大

因式分解

2824. 统计和小于目标的下标对数目

rust

2828. 判别首字母缩略词

字符串

2829. k-avoiding 数组的最小总和

给你两个整数 n 和 k 。

对于一个由 不同 正整数组成的数组,如果其中不存在任何求和等于 k 的不同元素对,则称其为 k-avoiding 数组。

返回长度为 n 的 k-avoiding 数组的可能的最小总和。

示例 1:

输入:n = 5, k = 4
输出:18
解释:设若 k-avoiding 数组为 [1,2,4,5,6] ,其元素总和为 18 。
可以证明不存在总和小于 18 的 k-avoiding 数组。

示例 2:

输入:n = 2, k = 6
输出:3
解释:可以构造数组 [1,2] ,其元素总和为 3 。
可以证明不存在总和小于 3 的 k-avoiding 数组。 

提示:

  • 1 <= n, k <= 50
class Solution {
public:
	int minimumSum(int n, int k) {
		if (n <= k / 2)return n * (n + 1) / 2;
		return k / 2 * (k / 2 + 1) / 2 + (n - k / 2)*(n + k * 2 - k / 2 - 1) / 2;
	}
};

2831. 找出最长等值子数组

给你一个下标从 0 开始的整数数组 nums 和一个整数 k 。

如果子数组中所有元素都相等,则认为子数组是一个 等值子数组 。注意,空数组是 等值子数组 。

从 nums 中删除最多 k 个元素后,返回可能的最长等值子数组的长度。

子数组 是数组中一个连续且可能为空的元素序列。

示例 1:

输入:nums = [1,3,2,3,1,3], k = 3
输出:3
解释:最优的方案是删除下标 2 和下标 4 的元素。
删除后,nums 等于 [1, 3, 3, 3] 。
最长等值子数组从 i = 1 开始到 j = 3 结束,长度等于 3 。
可以证明无法创建更长的等值子数组。

示例 2:

输入:nums = [1,1,2,2,1,1], k = 2
输出:4
解释:最优的方案是删除下标 2 和下标 3 的元素。 
删除后,nums 等于 [1, 1, 1, 1] 。 
数组自身就是等值子数组,长度等于 4 。 
可以证明无法创建更长的等值子数组。

提示:

  • 1 <= nums.length <= 105
  • 1 <= nums[i] <= nums.length
  • 0 <= k <= nums.length
class Solution {
public:
	int longestEqualSubarray(vector<int>& nums, int k) {
		map<int, deque<int>>m;
		int ans = 0;
		for (int i = 0; i < nums.size(); i++) {
			auto &q = m[nums[i]];
			q.push_back(i);
			while (q.back() - q.front() + 1 > q.size() + k)q.pop_front();
			ans = max(ans, (int)q.size());
		}
		return ans;
	}
};

2834. 找出美丽数组的最小和

如果数组 nums 满足下述条件,则称其为 美丽数组 。

  • nums.length == n.
  • nums 由两两互不相同的正整数组成。
  • 在范围 [0, n-1] 内,不存在 两个 不同 下标 i 和 j ,使得 nums[i] + nums[j] == target 。

返回符合条件的美丽数组所可能具备的 最小 和,并对结果进行取模 109 + 7

示例 1:

输入:n = 2, target = 3
输出:4
解释:nums = [1,3] 是美丽数组。
- nums 的长度为 n = 2 。
- nums 由两两互不相同的正整数组成。
- 不存在两个不同下标 i 和 j ,使得 nums[i] + nums[j] == 3 。
可以证明 4 是符合条件的美丽数组所可能具备的最小和。

示例 2:

输入:n = 3, target = 3
输出:8
解释:
nums = [1,3,4] 是美丽数组。 
- nums 的长度为 n = 3 。 
- nums 由两两互不相同的正整数组成。 
- 不存在两个不同下标 i 和 j ,使得 nums[i] + nums[j] == 3 。
可以证明 8 是符合条件的美丽数组所可能具备的最小和。

示例 3:

输入:n = 1, target = 1
输出:1
解释:nums = [1] 是美丽数组。

提示:

  • 1 <= n <= 109
  • 1 <= target <= 109
class Solution {
public:
    int minimumPossibleSum(long long n, long long t) {
        int p=1000000007;
        if(n<=t/2)return (n+1)*n/2%p;
        int ans=t*(n-t/2)%p;
        t/=2;
        return (ans+(n*n-n)/2+t*t+t-n*t)%p;
    }
};

2839. 判断通过操作能否让字符串相等 I

给你两个字符串 s1 和 s2 ,两个字符串的长度都为 4 ,且只包含 小写 英文字母。

你可以对两个字符串中的 任意一个 执行以下操作 任意 次:

  • 选择两个下标 i 和 j 且满足 j - i = 2 ,然后 交换 这个字符串中两个下标对应的字符。

如果你可以让字符串 s1  s2 相等,那么返回 true ,否则返回 false 。

示例 1:

输入:s1 = "abcd", s2 = "cdab"
输出:true
解释: 我们可以对 s1 执行以下操作:
- 选择下标 i = 0 ,j = 2 ,得到字符串 s1 = "cbad" 。
- 选择下标 i = 1 ,j = 3 ,得到字符串 s1 = "cdab" = s2 。

示例 2:

输入:s1 = "abcd", s2 = "dacb"
输出:false
解释:无法让两个字符串相等。

提示:

  • s1.length == s2.length == 4
  • s1 和 s2 只包含小写英文字母。

直接用2840. 判断通过操作能否让字符串相等 II的代码

class Solution {
public:
    bool checkSameStrings(string s1, string s2) {
        sort(s1.begin(),s1.end());
        sort(s2.begin(),s2.end());
        return s1==s2;
    }
    bool canBeEqual(string s1, string s2) {
        string s3,s4,s5,s6;
        for(int i=0;i<s1.length();i++){
            if(i%2)s3+=s1[i],s5+=s2[i];
            else s4+=s1[i],s6+=s2[i];
        }
        return checkSameStrings(s3,s5) && checkSameStrings(s4,s6);
    }
};

2840. 判断通过操作能否让字符串相等 II

给你两个字符串 s1 和 s2 ,两个字符串长度都为 n ,且只包含 小写 英文字母。

你可以对两个字符串中的 任意一个 执行以下操作 任意 次:

  • 选择两个下标 i 和 j ,满足 i < j 且 j - i 是 偶数,然后 交换 这个字符串中两个下标对应的字符。

如果你可以让字符串 s1  s2 相等,那么返回 true ,否则返回 false 。

示例 1:

输入:s1 = "abcdba", s2 = "cabdab"
输出:true
解释:我们可以对 s1 执行以下操作:
- 选择下标 i = 0 ,j = 2 ,得到字符串 s1 = "cbadba" 。
- 选择下标 i = 2 ,j = 4 ,得到字符串 s1 = "cbbdaa" 。
- 选择下标 i = 1 ,j = 5 ,得到字符串 s1 = "cabdab" = s2 。

示例 2:

输入:s1 = "abe", s2 = "bea"
输出:false
解释:无法让两个字符串相等。

提示:

  • n == s1.length == s2.length
  • 1 <= n <= 105
  • s1 和 s2 只包含小写英文字母。
class Solution {
public:
    bool checkSameStrings(string s1, string s2) {
        sort(s1.begin(),s1.end());
        sort(s2.begin(),s2.end());
        return s1==s2;
    }
    bool checkStrings(string s1, string s2) {
        string s3,s4,s5,s6;
        for(int i=0;i<s1.length();i++){
            if(i%2)s3+=s1[i],s5+=s2[i];
            else s4+=s1[i],s6+=s2[i];
        }
        return checkSameStrings(s3,s5) && checkSameStrings(s4,s6);
    }
};

2842. 统计一个字符串的 k 子序列美丽值最大的数目

组合

2846. 边权重均等查询

lca

2847. 给定数字乘积的最小数字

调整法

2855. 使数组成为递增数组的最少右移次数

给你一个长度为 n 下标从 0 开始的数组 nums ,数组中的元素为 互不相同 的正整数。请你返回让 nums 成为递增数组的 最少右移 次数,如果无法得到递增数组,返回 -1 。

一次 右移 指的是同时对所有下标进行操作,将下标为 i 的元素移动到下标 (i + 1) % n 处。

示例 1:

输入:nums = [3,4,5,1,2]
输出:2
解释:
第一次右移后,nums = [2,3,4,5,1] 。
第二次右移后,nums = [1,2,3,4,5] 。
现在 nums 是递增数组了,所以答案为 2 。

示例 2:

输入:nums = [1,3,5]
输出:0
解释:nums 已经是递增数组了,所以答案为 0 。

示例 3:

输入:nums = [2,1,4]
输出:-1
解释:无法将数组变为递增数组。

提示:

  • 1 <= nums.length <= 100
  • 1 <= nums[i] <= 100
  • nums 中的整数互不相同。
class Solution {
public:
    int minimumRightShifts(vector<int>& nums) {
        int id=0;
        for(int i=0;i<nums.size();i++)if(nums[id]>nums[i])id=i;
        id = (nums.size()-id)%nums.size();
        for(int i=1;i<nums.size();i++)if(nums[(i+nums.size()-id)%nums.size()]<nums[(i-1+nums.size()-id)%nums.size()])return -1;
        return id;
    }
};

2859. 计算 K 置位下标对应元素的和

二进制和位运算

2860. 让所有学生保持开心的分组方法数

给你一个下标从 0 开始、长度为 n 的整数数组 nums ,其中 n 是班级中学生的总数。班主任希望能够在让所有学生保持开心的情况下选出一组学生:

如果能够满足下述两个条件之一,则认为第 i 位学生将会保持开心:

  • 这位学生被选中,并且被选中的学生人数 严格大于 nums[i] 。
  • 这位学生没有被选中,并且被选中的学生人数 严格小于 nums[i] 。

返回能够满足让所有学生保持开心的分组方法的数目。

示例 1:

输入:nums = [1,1]
输出:2
解释:
有两种可行的方法:
班主任没有选中学生。
班主任选中所有学生形成一组。 
如果班主任仅选中一个学生来完成分组,那么两个学生都无法保持开心。因此,仅存在两种可行的方法。

示例 2:

输入:nums = [6,0,3,3,6,7,2,7]
输出:3
解释:
存在三种可行的方法:
班主任选中下标为 1 的学生形成一组。
班主任选中下标为 1、2、3、6 的学生形成一组。
班主任选中所有学生形成一组。 

提示:

  • 1 <= nums.length <= 105
  • 0 <= nums[i] < nums.length
class Solution {
public:
    int countWays(vector<int>& nums) {
        sort(nums.begin(),nums.end());
        int ans=nums[0]>0?1:0;
        for(int i=0;i+1<nums.size();i++){
            if(nums[i]<i+1 && i+1<nums[i+1])ans++;
        }
        if(nums[nums.size()-1]<nums.size())ans++;
        return ans;
    }
};

2861. 最大合金数

二分法

2862. 完全子集的最大元素和

数论

2864. 最大二进制奇数

字符串

2865. 美丽塔 I

单调栈

2866. 美丽塔 II

单调栈

2867. 统计树中的合法路径数目

树形DP

2873. 有序三元组中的最大值 I

给你一个下标从 0 开始的整数数组 nums 。

请你从所有满足 i < j < k 的下标三元组 (i, j, k) 中,找出并返回下标三元组的最大值。如果所有满足条件的三元组的值都是负数,则返回 0 。

下标三元组 (i, j, k) 的值等于 (nums[i] - nums[j]) * nums[k] 。

示例 1:

输入:nums = [12,6,1,2,7]
输出:77
解释:下标三元组 (0, 2, 4) 的值是 (nums[0] - nums[2]) * nums[4] = 77 。
可以证明不存在值大于 77 的有序下标三元组。

示例 2:

输入:nums = [1,10,3,4,19]
输出:133
解释:下标三元组 (1, 2, 4) 的值是 (nums[1] - nums[2]) * nums[4] = 133 。
可以证明不存在值大于 133 的有序下标三元组。 

示例 3:

输入:nums = [1,2,3]
输出:0
解释:唯一的下标三元组 (0, 1, 2) 的值是一个负数,(nums[0] - nums[1]) * nums[2] = -3 。因此,答案是 0 。

提示:

  • 3 <= nums.length <= 100
  • 1 <= nums[i] <= 106
class Solution {
public:
	long long maximumTripletValue(vector<int>& nums) {
		vector<int>maxs = nums;
		for (int i = maxs.size() - 1; i; i--)maxs[i - 1] = max(maxs[i], maxs[i - 1]);
		long long m = nums[0], ans = 0;
		for (int i = 0; i < nums.size()-1; i++) {
			ans = max(ans, (m - nums[i])*maxs[i + 1]);
			m = max(m,(long long) nums[i]);
		}
		return ans;
	}
};

2874. 有序三元组中的最大值 II

同 2873. 有序三元组中的最大值 I

完全相同。。。

2875. 无限数组的最短子数组

给你一个下标从 0 开始的数组 nums 和一个整数 target 。

下标从 0 开始的数组 infinite_nums 是通过无限地将 nums 的元素追加到自己之后生成的。

请你从 infinite_nums 中找出满足 元素和 等于 target 的 最短 子数组,并返回该子数组的长度。如果不存在满足条件的子数组,返回 -1 。

示例 1:

输入:nums = [1,2,3], target = 5
输出:2
解释:在这个例子中 infinite_nums = [1,2,3,1,2,3,1,2,...] 。
区间 [1,2] 内的子数组的元素和等于 target = 5 ,且长度 length = 2 。
可以证明,当元素和等于目标值 target = 5 时,2 是子数组的最短长度。

示例 2:

输入:nums = [1,1,1,2,3], target = 4
输出:2
解释:在这个例子中 infinite_nums = [1,1,1,2,3,1,1,1,2,3,1,1,...].
区间 [4,5] 内的子数组的元素和等于 target = 4 ,且长度 length = 2 。
可以证明,当元素和等于目标值 target = 4 时,2 是子数组的最短长度。

示例 3:

输入:nums = [2,4,6,8], target = 3
输出:-1
解释:在这个例子中 infinite_nums = [2,4,6,8,2,4,6,8,...] 。
可以证明,不存在元素和等于目标值 target = 3 的子数组。

提示:

  • 1 <= nums.length <= 105
  • 1 <= nums[i] <= 105
  • 1 <= target <= 109
class Solution {
public:
	int minSizeSubarrayWithSum(vector<long long>& s, int target) {
		map<long long, int>m;
		int ans = INT_MAX;
		for (int i = 0; i < s.size(); i++) {
			m[s[i]] = i;
			if (m.find(s[i] - target) != m.end())ans = min(ans, i - m[s[i] - target]);
		}
		return ans;
	}
	int minSizeSubarray(vector<int>& nums, int target) {
		vector<long long>s(nums.size() * 2);
		s[0] = nums[0];
		for (int i = 1; i < nums.size(); i++)s[i] = s[i - 1] + nums[i];
		for (int i = nums.size(); i < s.size(); i++)s[i] = s[i - 1] + nums[i - nums.size()];
		int c = s[nums.size() - 1], ans1 = minSizeSubarrayWithSum(s, target - (target - 1) / c * c);
		int ans = ans1 == INT_MAX ? INT_MAX : ans1 + (target - 1) / c * nums.size();
		cout<<ans;
		if (target > c)ans1 = minSizeSubarrayWithSum(s, target - (target - 1) / c * c+c),
			ans = min(ans, int(ans1 == INT_MAX ? INT_MAX : ans1 + (target - 1) / c * nums.size() - nums.size()));
		return ans == INT_MAX ? -1 : ans;
	}
};

2903. 找出满足差值条件的下标 I

给你一个下标从 0 开始、长度为 n 的整数数组 nums ,以及整数 indexDifference 和整数 valueDifference 。

你的任务是从范围 [0, n - 1] 内找出  2 个满足下述所有条件的下标 i 和 j :

  • abs(i - j) >= indexDifference 且
  • abs(nums[i] - nums[j]) >= valueDifference

返回整数数组 answer。如果存在满足题目要求的两个下标,则 answer = [i, j] ;否则,answer = [-1, -1] 。如果存在多组可供选择的下标对,只需要返回其中任意一组即可。

注意:i 和 j 可能 相等 。

示例 1:

输入:nums = [5,1,4,1], indexDifference = 2, valueDifference = 4
输出:[0,3]
解释:在示例中,可以选择 i = 0 和 j = 3 。
abs(0 - 3) >= 2 且 abs(nums[0] - nums[3]) >= 4 。
因此,[0,3] 是一个符合题目要求的答案。
[3,0] 也是符合题目要求的答案。

示例 2:

输入:nums = [2,1], indexDifference = 0, valueDifference = 0
输出:[0,0]
解释:
在示例中,可以选择 i = 0 和 j = 0 。 
abs(0 - 0) >= 0 且 abs(nums[0] - nums[0]) >= 0 。 
因此,[0,0] 是一个符合题目要求的答案。 
[0,1]、[1,0] 和 [1,1] 也是符合题目要求的答案。 

示例 3:

输入:nums = [1,2,3], indexDifference = 2, valueDifference = 4
输出:[-1,-1]
解释:在示例中,可以证明无法找出 2 个满足所有条件的下标。
因此,返回 [-1,-1] 。

提示:

  • 1 <= n == nums.length <= 100
  • 0 <= nums[i] <= 50
  • 0 <= indexDifference <= 100
  • 0 <= valueDifference <= 50
class Solution {
public:
    vector<int> findIndices(vector<int>& nums, int indexDifference, int valueDifference) {
        for(int i=0;i<nums.size();i++){
            for(int j=i+indexDifference;j<nums.size();j++){
                if(abs(nums[i] - nums[j]) >= valueDifference)return vector<int>{i,j};
            }
        }
        return vector<int>{-1,-1};
    }
};

2908. 元素和最小的山形三元组 I

给你一个下标从 0 开始的整数数组 nums 。

如果下标三元组 (i, j, k) 满足下述全部条件,则认为它是一个 山形三元组 :

  • i < j < k
  • nums[i] < nums[j] 且 nums[k] < nums[j]

请你找出 nums 中 元素和最小 的山形三元组,并返回其 元素和 。如果不存在满足条件的三元组,返回 -1 。

示例 1:

输入:nums = [8,6,1,5,3]
输出:9
解释:三元组 (2, 3, 4) 是一个元素和等于 9 的山形三元组,因为: 
- 2 < 3 < 4
- nums[2] < nums[3] 且 nums[4] < nums[3]
这个三元组的元素和等于 nums[2] + nums[3] + nums[4] = 9 。可以证明不存在元素和小于 9 的山形三元组。

示例 2:

输入:nums = [5,4,8,7,10,2]
输出:13
解释:三元组 (1, 3, 5) 是一个元素和等于 13 的山形三元组,因为: 
- 1 < 3 < 5 
- nums[1] < nums[3] 且 nums[5] < nums[3]
这个三元组的元素和等于 nums[1] + nums[3] + nums[5] = 13 。可以证明不存在元素和小于 13 的山形三元组。

示例 3:

输入:nums = [6,5,4,3,4,5]
输出:-1
解释:可以证明 nums 中不存在山形三元组。

提示:

  • 3 <= nums.length <= 50
  • 1 <= nums[i] <= 50
class Solution {
public:
	int minimumSum(vector<int>& nums) {
		vector<int>mins = nums;
		for (int i = nums.size() - 1; i; i--)mins[i - 1] = min(mins[i - 1], mins[i]);
		int m = nums[0], ans = INT_MAX;
		for (int i = 1; i < nums.size() - 1; i++) {
			if (m< nums[i] && nums[i]>mins[i + 1])ans = min(ans, m + nums[i] + mins[i + 1]);
			m = min(m, nums[i]);
		}
		return ans == INT_MAX ? -1 : ans;
	}
};

2909. 元素和最小的山形三元组 II

同2908. 元素和最小的山形三元组 I

完全相同。。。

2917. 找出数组中的 K-or 值

二进制

2923. 找到冠军 I

一场比赛中共有 n 支队伍,按从 0 到  n - 1 编号。

给你一个下标从 0 开始、大小为 n * n 的二维布尔矩阵 grid 。对于满足 0 <= i, j <= n - 1 且 i != j 的所有 i, j :如果 grid[i][j] == 1,那么 i 队比 j 队  ;否则,j 队比 i 队  。

在这场比赛中,如果不存在某支强于 a 队的队伍,则认为 a 队将会是 冠军 。

返回这场比赛中将会成为冠军的队伍。

示例 1:

输入:grid = [[0,1],[0,0]]
输出:0
解释:比赛中有两支队伍。
grid[0][1] == 1 表示 0 队比 1 队强。所以 0 队是冠军。

示例 2:

输入:grid = [[0,0,1],[1,0,1],[0,0,0]]
输出:1
解释:比赛中有三支队伍。
grid[1][0] == 1 表示 1 队比 0 队强。
grid[1][2] == 1 表示 1 队比 2 队强。
所以 1 队是冠军。

提示:

  • n == grid.length
  • n == grid[i].length
  • 2 <= n <= 100
  • grid[i][j] 的值为 0 或 1
  • 对于所有 i grid[i][i] 等于 0.
  • 对于满足 i != j 的所有 i, j ,grid[i][j] != grid[j][i] 均成立
  • 生成的输入满足:如果 a 队比 b 队强,b 队比 c 队强,那么 a 队比 c 队强
class Solution {
public:
    int findChampion(vector<vector<int>>& grid) {
        for(int i=0;i<grid.size();i++){
            int s=0;
            for(int j=0;j<grid.size();j++)s+=grid[i][j];
            if(s==grid[i][i]+grid.size()-1)return i;
        }
        return 0;
    }
};

2924. 找到冠军 II

一场比赛中共有 n 支队伍,按从 0 到  n - 1 编号。每支队伍也是 有向无环图(DAG) 上的一个节点。

给你一个整数 n 和一个下标从 0 开始、长度为 m 的二维整数数组 edges 表示这个有向无环图,其中 edges[i] = [ui, vi] 表示图中存在一条从 ui 队到 vi 队的有向边。

从 a 队到 b 队的有向边意味着 a 队比 b 队  ,也就是 b 队比 a 队  。

在这场比赛中,如果不存在某支强于 a 队的队伍,则认为 a 队将会是 冠军 。

如果这场比赛存在 唯一 一个冠军,则返回将会成为冠军的队伍。否则,返回 -1 。

注意

  •  是形如 a1, a2, ..., an, an+1 的一个序列,且满足:节点 a1 与节点 an+1 是同一个节点;节点 a1, a2, ..., an 互不相同;对于范围 [1, n] 中的每个 i ,均存在一条从节点 ai 到节点 ai+1 的有向边。
  • 有向无环图 是不存在任何环的有向图。

示例 1:

输入:n = 3, edges = [[0,1],[1,2]]
输出:0
解释:1 队比 0 队弱。2 队比 1 队弱。所以冠军是 0 队。

示例 2:

输入:n = 4, edges = [[0,2],[1,3],[1,2]]
输出:-1
解释:2 队比 0 队和 1 队弱。3 队比 1 队弱。但是 1 队和 0 队之间不存在强弱对比。所以答案是 -1 。

提示:

  • 1 <= n <= 100
  • m == edges.length
  • 0 <= m <= n * (n - 1) / 2
  • edges[i].length == 2
  • 0 <= edge[i][j] <= n - 1
  • edges[i][0] != edges[i][1]
  • 生成的输入满足:如果 a 队比 b 队强,就不存在 b 队比 a 队强
  • 生成的输入满足:如果 a 队比 b 队强,b 队比 c 队强,那么 a 队比 c 队强
class Solution {
public:
    int findChampion(int n, vector<vector<int>>& edges) {
        map<int,int>m;
        for(auto v:edges){
            m[v[1]]=1;
        }
        int ans=-1;
        for(int i=0;i<n;i++){
            if(m[i])continue;
            if(ans==-1)ans=i;
            else return -1;
        }
        return ans;
    }
};

2928. 给小朋友们分糖果 I

容斥原理

2929. 给小朋友们分糖果 II

容斥原理

2930. 重新排列后包含指定子字符串的字符串数目

容斥原理

2931. 购买物品的最大开销

给你一个下标从 0 开始大小为 m * n 的整数矩阵 values ,表示 m 个不同商店里 m * n 件不同的物品。每个商店有 n 件物品,第 i 个商店的第 j 件物品的价值为 values[i][j] 。除此以外,第 i 个商店的物品已经按照价值非递增排好序了,也就是说对于所有 0 <= j < n - 1 都有 values[i][j] >= values[i][j + 1] 。

每一天,你可以在一个商店里购买一件物品。具体来说,在第 d 天,你可以:

  • 选择商店 i 。
  • 购买数组中最右边的物品 j ,开销为 values[i][j] * d 。换句话说,选择该商店中还没购买过的物品中最大的下标 j ,并且花费 values[i][j] * d 去购买。

注意,所有物品都视为不同的物品。比方说如果你已经从商店 1 购买了物品 0 ,你还可以在别的商店里购买其他商店的物品 0 。

请你返回购买所有 m * n 件物品需要的 最大开销 。

示例 1:

输入:values = [[8,5,2],[6,4,1],[9,7,3]]
输出:285
解释:第一天,从商店 1 购买物品 2 ,开销为 values[1][2] * 1 = 1 。
第二天,从商店 0 购买物品 2 ,开销为 values[0][2] * 2 = 4 。
第三天,从商店 2 购买物品 2 ,开销为 values[2][2] * 3 = 9 。
第四天,从商店 1 购买物品 1 ,开销为 values[1][1] * 4 = 16 。
第五天,从商店 0 购买物品 1 ,开销为 values[0][1] * 5 = 25 。
第六天,从商店 1 购买物品 0 ,开销为 values[1][0] * 6 = 36 。
第七天,从商店 2 购买物品 1 ,开销为 values[2][1] * 7 = 49 。
第八天,从商店 0 购买物品 0 ,开销为 values[0][0] * 8 = 64 。
第九天,从商店 2 购买物品 0 ,开销为 values[2][0] * 9 = 81 。
所以总开销为 285 。
285 是购买所有 m * n 件物品的最大总开销。

示例 2:

输入:values = [[10,8,6,4,2],[9,7,5,3,2]]
输出:386
解释:第一天,从商店 0 购买物品 4 ,开销为 values[0][4] * 1 = 2 。
第二天,从商店 1 购买物品 4 ,开销为 values[1][4] * 2 = 4 。
第三天,从商店 1 购买物品 3 ,开销为 values[1][3] * 3 = 9 。
第四天,从商店 0 购买物品 3 ,开销为 values[0][3] * 4 = 16 。
第五天,从商店 1 购买物品 2 ,开销为 values[1][2] * 5 = 25 。
第六天,从商店 0 购买物品 2 ,开销为 values[0][2] * 6 = 36 。
第七天,从商店 1 购买物品 1 ,开销为 values[1][1] * 7 = 49 。
第八天,从商店 0 购买物品 1 ,开销为 values[0][1] * 8 = 64 。
第九天,从商店 1 购买物品 0 ,开销为 values[1][0] * 9 = 81 。
第十天,从商店 0 购买物品 0 ,开销为 values[0][0] * 10 = 100 。
所以总开销为 386 。
386 是购买所有 m * n 件物品的最大总开销。

提示:

  • 1 <= m == values.length <= 10
  • 1 <= n == values[i].length <= 104
  • 1 <= values[i][j] <= 106
  • values[i] 按照非递增顺序排序。
class Solution {
public:
	long long maxSpending(vector<vector<int>>& values) {
		vector<int>v;
		for (auto vi : values)for (auto x : vi)v.push_back(x);
		sort(v.begin(), v.end());
		long long ans = 0;
		for (long long i = 1; i <= v.size(); i++)ans += i * v[i-1];
		return ans;
	}
};

2936. 包含相等值数字块的数量

分治

2938. 区分黑球与白球

桌子上有 n 个球,每个球的颜色不是黑色,就是白色。

给你一个长度为 n 、下标从 0 开始的二进制字符串 s,其中 1 和 0 分别代表黑色和白色的球。

在每一步中,你可以选择两个相邻的球并交换它们。

返回「将所有黑色球都移到右侧,所有白色球都移到左侧所需的 最小步数」。

示例 1:

输入:s = "101"
输出:1
解释:我们可以按以下方式将所有黑色球移到右侧:
- 交换 s[0] 和 s[1],s = "011"。
最开始,1 没有都在右侧,需要至少 1 步将其移到右侧。

示例 2:

输入:s = "100"
输出:2
解释:我们可以按以下方式将所有黑色球移到右侧:
- 交换 s[0] 和 s[1],s = "010"。
- 交换 s[1] 和 s[2],s = "001"。
可以证明所需的最小步数为 2 。

示例 3:

输入:s = "0111"
输出:0
解释:所有黑色球都已经在右侧。

提示:

  • 1 <= n == s.length <= 105
  • s[i] 不是 '0',就是 '1'
class Solution {
public:
    long long minimumSteps(string s) {
        int id=s.length()-1;
        long long ans=0;
        for(int i=0;i<s.length();i++){
            if(s[i]=='1')ans+=id---i;
        }
        return ans;
    }
};

2941. 子数组的最大 GCD-Sum

欧几里得算法

2944. 购买水果需要的最少金币数

dp

2951. 找出峰值

水题

2952. 需要添加的硬币的最小数量

货币

2954. 统计感冒序列的数目

全排列

2956. 找到两个数组中的公共元素

给你两个下标从 0 开始的整数数组 nums1 和 nums2 ,它们分别含有 n 和 m 个元素。请你计算以下两个数值:

  • answer1:使得 nums1[i] 在 nums2 中出现的下标 i 的数量。
  • answer2:使得 nums2[i] 在 nums1 中出现的下标 i 的数量。

返回 [answer1, answer2]

示例 1:

输入:nums1 = [2,3,2], nums2 = [1,2]

输出:[2,1]

解释:

示例 2:

输入:nums1 = [4,3,2,3,1], nums2 = [2,2,5,2,3,6]

输出:[3,4]

解释:

nums1 中下标在 1,2,3 的元素在 nums2 中也存在。所以 answer1 为 3。

nums2 中下标在 0,1,3,4 的元素在 nums1 中也存在。所以 answer2 为 4。

示例 3:

输入:nums1 = [3,4,2,3], nums2 = [1,5]

输出:[0,0]

解释:

nums1 和 nums2 中没有相同的数字,所以答案是 [0,0]。

提示:

  • n == nums1.length
  • m == nums2.length
  • 1 <= n, m <= 100
  • 1 <= nums1[i], nums2[i] <= 100
class Solution {
public:
    vector<int> findIntersectionValues(vector<int>& nums1, vector<int>& nums2) {
        return vector<int>{find1In2(nums1,nums2),find1In2(nums2,nums1)};
    }
    int find1In2(vector<int>& nums1, vector<int>& nums2) {
        map<int,int>m;
        for(auto x:nums2)m[x]++;
        int ans=0;
        for(auto x:nums1)if(m[x])ans++;
        return ans;
    }
};

2960. 统计已测试设备

给你一个长度为 n 、下标从 0 开始的整数数组 batteryPercentages ,表示 n 个设备的电池百分比。

你的任务是按照顺序测试每个设备 i,执行以下测试操作:

  • 如果 batteryPercentages[i] 大于 0
    • 增加 已测试设备的计数。
    • 将下标在 [i + 1, n - 1] 的所有设备的电池百分比减少 1,确保它们的电池百分比 不会低于 0 ,即 batteryPercentages[j] = max(0, batteryPercentages[j] - 1)
    • 移动到下一个设备。
  • 否则,移动到下一个设备而不执行任何测试。

返回一个整数,表示按顺序执行测试操作后 已测试设备 的数量。

示例 1:

输入:batteryPercentages = [1,1,2,1,3]
输出:3
解释:按顺序从设备 0 开始执行测试操作:
在设备 0 上,batteryPercentages[0] > 0 ,现在有 1 个已测试设备,batteryPercentages 变为 [1,0,1,0,2] 。
在设备 1 上,batteryPercentages[1] == 0 ,移动到下一个设备而不进行测试。
在设备 2 上,batteryPercentages[2] > 0 ,现在有 2 个已测试设备,batteryPercentages 变为 [1,0,1,0,1] 。
在设备 3 上,batteryPercentages[3] == 0 ,移动到下一个设备而不进行测试。
在设备 4 上,batteryPercentages[4] > 0 ,现在有 3 个已测试设备,batteryPercentages 保持不变。
因此,答案是 3 。

示例 2:

输入:batteryPercentages = [0,1,2]
输出:2
解释:按顺序从设备 0 开始执行测试操作:
在设备 0 上,batteryPercentages[0] == 0 ,移动到下一个设备而不进行测试。
在设备 1 上,batteryPercentages[1] > 0 ,现在有 1 个已测试设备,batteryPercentages 变为 [0,1,1] 。
在设备 2 上,batteryPercentages[2] > 0 ,现在有 2 个已测试设备,batteryPercentages 保持不变。
因此,答案是 2 。

提示:

  • 1 <= n == batteryPercentages.length <= 100
  • 0 <= batteryPercentages[i] <= 100
class Solution {
public:
    int countTestedDevices(vector<int>& batteryPercentages) {
        int s=0;
        for(auto x:batteryPercentages){
            if(x>s)s++;
        }
        return s;
    }
};

2961. 双模幂运算

快速幂

2963. 统计好分割方案的数目

组合

2965. 找出缺失和重复的数字

搜索else

2970. 统计移除递增子数组的数目 I

2972. 统计移除递增子数组的数目 II的退化版

2972. 统计移除递增子数组的数目 II

给你一个下标从 0 开始的  整数数组 nums 。

如果 nums 的一个子数组满足:移除这个子数组后剩余元素 严格递增 ,那么我们称这个子数组为 移除递增 子数组。比方说,[5, 3, 4, 6, 7] 中的 [3, 4] 是一个移除递增子数组,因为移除该子数组后,[5, 3, 4, 6, 7] 变为 [5, 6, 7] ,是严格递增的。

请你返回 nums 中 移除递增 子数组的总数目。

注意 ,剩余元素为空的数组也视为是递增的。

子数组 指的是一个数组中一段连续的元素序列。

示例 1:

输入:nums = [1,2,3,4]
输出:10
解释:10 个移除递增子数组分别为:[1], [2], [3], [4], [1,2], [2,3], [3,4], [1,2,3], [2,3,4] 和 [1,2,3,4]。移除任意一个子数组后,剩余元素都是递增的。注意,空数组不是移除递增子数组。

示例 2:

输入:nums = [6,5,7,8]
输出:7
解释:7 个移除递增子数组分别为:[5], [6], [5,7], [6,5], [5,7,8], [6,5,7] 和 [6,5,7,8] 。
nums 中只有这 7 个移除递增子数组。

示例 3:

输入:nums = [8,7,6,6]
输出:3
解释:3 个移除递增子数组分别为:[8,7,6], [7,6,6] 和 [8,7,6,6] 。注意 [8,7] 不是移除递增子数组因为移除 [8,7] 后 nums 变为 [6,6] ,它不是严格递增的。

提示:

  • 1 <= nums.length <= 105
  • 1 <= nums[i] <= 109
class Solution {
public:
	long long incremovableSubarrayCount(vector<int>& nums) {
		int a = 0, n = nums.size(), b = n - 1;
        long long ans = 0;
		for (int i = n - 1; i; i--) {
			if (nums[i - 1] < nums[i])b = i - 1;
			else break;
		}
		if (b == 0)return n * (n + 1) / 2;
		while (b < n) {
			while (nums[a] < nums[a + 1] && nums[a + 1] < nums[b])a++;
			if (nums[a] < nums[b])ans += a + 2;
			else ans++;
			b++;
		}
		while (nums[a] < nums[a + 1])a++;
		return ans + a + 2;
	}
};

2974. 最小数字游戏

你有一个下标从 0 开始、长度为 偶数 的整数数组 nums ,同时还有一个空数组 arr 。Alice 和 Bob 决定玩一个游戏,游戏中每一轮 Alice 和 Bob 都会各自执行一次操作。游戏规则如下:

  • 每一轮,Alice 先从 nums 中移除一个 最小 元素,然后 Bob 执行同样的操作。
  • 接着,Bob 会将移除的元素添加到数组 arr 中,然后 Alice 也执行同样的操作。
  • 游戏持续进行,直到 nums 变为空。

返回结果数组 arr 。

示例 1:

输入:nums = [5,4,2,3]
输出:[3,2,5,4]
解释:第一轮,Alice 先移除 2 ,然后 Bob 移除 3 。然后 Bob 先将 3 添加到 arr 中,接着 Alice 再将 2 添加到 arr 中。于是 arr = [3,2] 。
第二轮开始时,nums = [5,4] 。Alice 先移除 4 ,然后 Bob 移除 5 。接着他们都将元素添加到 arr 中,arr 变为 [3,2,5,4] 。

示例 2:

输入:nums = [2,5]
输出:[5,2]
解释:第一轮,Alice 先移除 2 ,然后 Bob 移除 5 。然后 Bob 先将 5 添加到 arr 中,接着 Alice 再将 2 添加到 arr 中。于是 arr = [5,2] 。

提示:

  • 1 <= nums.length <= 100
  • 1 <= nums[i] <= 100
  • nums.length % 2 == 0
class Solution {
public:
    vector<int> numberGame(vector<int>& nums) {
        sort(nums.begin(),nums.end());
        for(int i=1;i<nums.size();i+=2){
            nums[i]^=nums[i-1]^=nums[i]^=nums[i-1];
        }
        return nums;
    }
};

2981. 找出出现至少三次的最长特殊子字符串 I

给你一个仅由小写英文字母组成的字符串 s 。

如果一个字符串仅由单一字符组成,那么它被称为 特殊 字符串。例如,字符串 "abc" 不是特殊字符串,而字符串 "ddd""zz" 和 "f" 是特殊字符串。

返回在 s 中出现 至少三次  最长特殊子字符串 的长度,如果不存在出现至少三次的特殊子字符串,则返回 -1 。

子字符串 是字符串中的一个连续 非空 字符序列。

示例 1:

输入:s = "aaaa"
输出:2
解释:出现三次的最长特殊子字符串是 "aa" :子字符串 "aaaa"、"aaaa" 和 "aaaa"。
可以证明最大长度是 2 。

示例 2:

输入:s = "abcdef"
输出:-1
解释:不存在出现至少三次的特殊子字符串。因此返回 -1 。

示例 3:

输入:s = "abcaba"
输出:1
解释:出现三次的最长特殊子字符串是 "a" :子字符串 "abcaba"、"abcaba" 和 "abcaba"。
可以证明最大长度是 1 。

提示:

  • 3 <= s.length <= 50
  • s 仅由小写英文字母组成。
class Solution {
public:
    int maximumLength(string s) {
        map<string,int>m;
        int ans=-1;
        for(int i=0;i<s.length();i++){
            for(int j=i;j<s.length();j++){
                if(s[j]!=s[i])break;
                string str=s.substr(i,j-i+1);
                if(++m[str]>=3)ans=max(ans,(int)str.length());
            }
        }
        return ans;
    }
};

2982. 找出出现至少三次的最长特殊子字符串 II

给你一个仅由小写英文字母组成的字符串 s 。

如果一个字符串仅由单一字符组成,那么它被称为 特殊 字符串。例如,字符串 "abc" 不是特殊字符串,而字符串 "ddd""zz" 和 "f" 是特殊字符串。

返回在 s 中出现 至少三次  最长特殊子字符串 的长度,如果不存在出现至少三次的特殊子字符串,则返回 -1 。

子字符串 是字符串中的一个连续 非空 字符序列。

示例 1:

输入:s = "aaaa"
输出:2
解释:出现三次的最长特殊子字符串是 "aa" :子字符串 "aaaa"、"aaaa" 和 "aaaa"。
可以证明最大长度是 2 。

示例 2:

输入:s = "abcdef"
输出:-1
解释:不存在出现至少三次的特殊子字符串。因此返回 -1 。

示例 3:

输入:s = "abcaba"
输出:1
解释:出现三次的最长特殊子字符串是 "a" :子字符串 "abcaba"、"abcaba" 和 "abcaba"。
可以证明最大长度是 1 。

提示:

  • 3 <= s.length <= 5 * 105
  • s 仅由小写英文字母组成。
class Solution {
public:
    int maximumLength(string s) {
        map<char,vector<int>>m;
        char ch=0;
        int n=0;
        s+=ch;
        for(auto c:s){
            if(c==ch)n++;
            else{
                m[ch].push_back(n);
                ch=c,n=1;
            }
        }
        int ans=-1;
        for(auto mi:m)ans=max(ans,f(mi.second));
        return ans;
    }
    int f(vector<int>&v)
    {
        sort(v.begin(),v.end());
        int ans=0;
        if(v.size()>=3)ans = v[v.size()-3];
        if(v.size()>=2)ans=max(ans,min(v[v.size()-2],v[v.size()-1]-1));
        ans=max(ans,v[v.size()-1]-2);
        return ans>0?ans:-1;
    }
};

2992. 自整除排列的数量

给定一个整数 n,返回 下标从 1 开始 的数组 nums = [1, 2, ..., n]的 可能的排列组合数量,使其满足 自整除 条件。

如果对于每个 1 <= i <= n,满足 gcd(a[i], i) == 1,数组 nums 就是 自整除 的。

数组的 排列 是对数组元素的重新排列组合,例如,下面是数组 [1, 2, 3] 的所有排列组合:

  • [1, 2, 3]
  • [1, 3, 2]
  • [2, 1, 3]
  • [2, 3, 1]
  • [3, 1, 2]
  • [3, 2, 1]

示例 1:

输入:n = 1
输出:1
解释:数组 [1] 只有一个排列,它是自整除的。

示例 2:

输入:n = 2
输出:1
解释:数组 [1,2] 有 2 个排列,但只有其中一个是自整除的:
nums = [1,2]:这不是自整除的,因为 gcd(nums[2], 2) != 1。
nums = [2,1]:这是自整除的,因为 gcd(nums[1], 1) == 1 并且 gcd(nums[2], 2) == 1。

示例 3:

输入:n = 3
输出:3
解释:数组 [1,2,3] 有 3 个自整除的排列:[1,2,3]、[2,1,3]、[3,2,1]。
其他 3 个排列不能满足自整除条件。因此答案是 3。

提示:

  • 1 <= n <= 12

思路一:

DFS,性能高,写起来稍微麻烦点

思路二:

枚举所有的全排列,性能差,好写

首先有这个代码:

class Solution {
public:
    int selfDivisiblePermutationCount(int n) {
        vector<int>v(n);
        int s=1,ans=0;
        for(int i=0;i<n;i++)v[i]=i+1,s*=i+1;
        while(s--){
            if(check(v))ans++;
            next_permutation(v.begin(),v.end());
        }
        return ans;
    }
    bool check(vector<int>&v){
        for(int i=2;i<=v.size();i+=2)if(v[i-1]%2==0)return false;
        for(int i=3;i<=v.size();i+=3)if(v[i-1]%3==0)return false;
        for(int i=5;i<=v.size();i+=5)if(v[i-1]%5==0)return false;
        for(int i=7;i<=v.size();i+=7)if(v[i-1]%7==0)return false;
        for(int i=11;i<=v.size();i+=11)if(v[i-1]%11==0)return false;
        return true;
    }
};

发现在n=12的时候超时,于是我们利用硬编码的技巧,把n=1到12的情况都算出来:

int main()
{
    for (int i = 1; i <= 12; i++)
        cout << Solution().selfDivisiblePermutationCount(i) << ",";
	return 0;
}

输出 1,1,3,4,28,16,256,324,3600,3600,129744,63504

于是得到新的代码:

class Solution {
public:
    int selfDivisiblePermutationCount(int n) {
        vector<int>v{ 1,1,3,4,28,16,256,324,3600,3600,129744,63504 };
        return v[n-1];
    }
};

3000. 对角线最长的矩形的面积

给你一个下标从 0 开始的二维整数数组 dimensions

对于所有下标 i0 <= i < dimensions.length),dimensions[i][0] 表示矩形 i 的长度,而 dimensions[i][1] 表示矩形 i 的宽度。

返回对角线最 长 的矩形的 面积 。如果存在多个对角线长度相同的矩形,返回面积最 大 的矩形的面积。

示例 1:

输入:dimensions = [[9,3],[8,6]]
输出:48
解释:
下标 = 0,长度 = 9,宽度 = 3。对角线长度 = sqrt(9 * 9 + 3 * 3) = sqrt(90) ≈ 9.487。
下标 = 1,长度 = 8,宽度 = 6。对角线长度 = sqrt(8 * 8 + 6 * 6) = sqrt(100) = 10。
因此,下标为 1 的矩形对角线更长,所以返回面积 = 8 * 6 = 48。

示例 2:

输入:dimensions = [[3,4],[4,3]]
输出:12
解释:两个矩形的对角线长度相同,为 5,所以最大面积 = 12。

提示:

  • 1 <= dimensions.length <= 100
  • dimensions[i].length == 2
  • 1 <= dimensions[i][0], dimensions[i][1] <= 100
class Solution {
public:
	int areaOfMaxDiagonal(vector<vector<int>>& dimensions) {
		int miSum = 0, ans = 0;
		for (auto v : dimensions) {
			if (v[0] * v[0] + v[1] * v[1] > miSum)miSum = v[0] * v[0] + v[1] * v[1], ans = v[0] * v[1];
			else if (v[0] * v[0] + v[1] * v[1] == miSum)ans = max(ans, v[0] * v[1]);
		}
		return ans;
	}
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值