出题是一件痛苦的事情!
相同的题目看多了也会有审美疲劳,于是我舍弃了大家所熟悉的 A+B Problem,改用 A-B 了哈哈!
给出一串正整数数列以及一个正整数 \(C\),要求计算出所有满足 \(A - B = C\) 的数对的个数(不同位置的数字一样的数对算不同的数对)。
输入共两行。
第一行,两个正整数 \(N,C\)。
第二行,\(N\) 个正整数,作为要求处理的那串数。
一行,表示该串正整数中包含的满足 \(A - B = C\) 的数对的个数。
4 1 1 1 2 3
3
对于 \(75\%\) 的数据,\(1 \leq N \leq 2000\)。
对于 \(100\%\) 的数据,\(1 \leq N \leq 2 \times 10^5\),\(0 \leq a_i <2^{30}\),\(1 \leq C < 2^{30}\)。
2017/4/29 新添数据两组
注意这里由于每组两两组合都可能满足条件,所以这里的结果记录变量 ans 可能是 N^2 大小,这里使用long long 记录!!!
类似 1.两数之和
#include<iostream> #include<vector> #include<unordered_map> using namespace std; int main(){ int N, C; cin >> N >> C; vector<int> arr(N); unordered_map<int,int> mp(N); for(int i = 0; i < N; i++) { cin >> arr[i]; mp[arr[i]]++; } long long ans = 0; for(int i = 0; i < N; i++){ if(mp.count(arr[i] - C)) ans += mp[arr[i] - C]; } cout << ans; }
1.空间复杂度:数组,哈希表 O(N)
2.时间复杂度: 哈希表 O(1), 数组遍历 O(N). 总体O(N)
先排序,之后利用单调性,使用双指针构建结果区域,求得具体长度。
比如像目前数为s[i],我要找到s[i]-C。l为s[l]首个大于等于s[i]-C的数,r为s[r]首个大于s[i]-C的数,由二者共同构建的区域长度即为所需长度。
#include <bits/stdc++.h> using namespace std; int main(){ int N, C; cin >> N >> C; vector<int> arr(N); for(int i = 0; i < N; i++) { cin >> arr[i]; } // sort(arr, arr + N); //这是对于数组的排序,不是对于vector的排序,vector用迭代器即可 sort(arr.begin(), arr.end()); long long ans = 0; int l = 0, r = 0; /*1. 这里为何l,r不需要回溯?因为arr[i]-C在不断增大,l和r必定是右移 *2.由于跳出while循环条件是第一个不满足该条件的情况出现,所以这里l指向区域首部第一个节点,r指向区域尾部节点的下一个节点,长度即r-l*/ for(int i = 0; i < N; i++){ while(arr[l] < arr[i] - C && l < N) l++; while(arr[r] <= arr[i] - C && r < N) r++; if(s[i] - s[l] == c) ans += r - l; //这里的判断并不是非常有必要? } cout << ans; }
1.空间复杂度: 使用了数组 O(n)
2.时间复杂度:由排序决定O(nlogn){后面的数组遍历,由于l和r无需回溯所以就是O(n)}