AI刷题第291 禁着点方案数 | 豆包MarsCode AI刷题

30 阅读3分钟

问题描述

小U有一个长度为n的数组,这个数组的元素被定义为“禁着点”。她现在希望你找出有多少对正整数 x 和 y,满足 x+y=s 且 x 和 y 都不在禁着点的数组中。注意,(x,y) 和 (y,x) 被视为不同的正整数对。 对于这道题目,请帮我优化和扩展下面的题解,要详细且正确 这道题的思路比较简单,要求是 正整数x和y,并且x+y=s。其中(x,y)和(y,x)被视为不同的整数对。

测试样例

样例1:

输入:n = 3,a = [1, 2, 3],s = 10
输出:3

样例2:

输入:n = 2,a = [5, 9],s = 15
输出:10

样例3:

输入:n = 4,a = [1, 6, 9, 4],s = 13
输出:6

问题分析

给定一个长度为 n 的数组,数组中的元素被称为“禁着点”。我们需要找出有多少对正整数 (x, y) 满足以下条件:

  1. x + y = s
  2. x 和 y 都不在禁着点的数组中。

注意, (x, y) 和 (y, x) 被视为不同的正整数对。

总体思路

  1. 计算总对数:对于给定的 s ,所有可能的整数对为 (1, s-1), (2, s-2), ... , (s-1, 1) 。因此,总的满足条件的整数对数为 s - 1 。

  2. 不满足条件的对数

    • 当数组中存在一个数字出现在所有可能的整数对中时,将从总数中减去 2(因为 (x, y) 和 (y, x) 都会被排除)。
    • 如果一个整数对 (x, s-x) 中的两个数字都在禁着点数组中,那么这对数将减少 2。
    • 如果s为偶数,并且恰好x==s-x。那么就只能将总数减去1,因为这两个数字颠倒位置并不能产生两组整数对。
  3. 标记出现的数字:那么如何判断是否两个数字都在给出的数组中呢?为了避免重复的遍历行为,我们需要对出现的数字进行标记,可以使用数组或者哈希表之类的进行标记,这主要取决于变量的取值范围。就比如如果变量被限制到了100以内(仅举例),那么完全可以使用一个大小为100的数组进行标记。如果变量的取值范围很大且很稀疏,那么使用数组进行标记就变得非常浪费,此时可以使用哈希表进行记录。在本题中,题目中并没有给出s的取值范围,所以使用哈希表进行标记是一个不错的选择。

具体步骤

  1. 构建禁着点集合: 使用哈希表(或集合)存储禁着点,以便快速查找。

  2. 遍历所有可能的整数对: 对于每一对 (x, s-x) ,检查这两个数是否都在禁着点集合中:

    • 如果是,则从总数中减去 2。
    • 如果只有一个数在禁着点中,则从总数中减去 1。
  3. 确保无重复计算: 由于 (x, y) 和 (y, x) 被视为不同对,因此在遍历时需要确保每对只计算一次。

代码实现

#include <iostream>
#include <vector>
#include <string>
#include <unordered_map>

using namespace std;

int solution(int n, vector<int>& a, int s) {
    // write code here
    unordered_map<int, int> m;
    int sum = s-1;
    int even = s%2==0;
    for(int i=0;i<n;++i){
        if(a[i]>0 && a[i]<s){
            if(m[s-a[i]] || m[a[i]]){//防止重复出现的数字
                continue;
            }
            else{
                if(even && a[i]==s/2){
                    sum-=1;
                }
                else{
                    sum-=2;
                }
                
            }
            m[a[i]]++;
        }
    }
    return sum>=0 ? sum:0;
}

int main() {
    vector<int> a1 = {1,3,-1,12,11,9,16,3,8,5,9};
    cout << (solution(11, a1, 6) == 2) << endl;

    // vector<int> a2 = {5, 9};
    // cout << (solution(2, a2, 15) == 10) << endl;

    // vector<int> a3 = {1, 6, 9, 4};
    // cout << (solution(4, a3, 13) == 6) << endl;
}