一.题目描述
NC540排列询问
牛妹有一个长度为n的排列p,她有q个询问。
每个询问包含l1,r1,l2,r2.她想知道从[l1,r1]中选取x,[l2,r2]中选取y,有多少组(x,y)满足min(x,y)==gcd(x,y)?
返回一个vector代表对这q个询问的答案
二.算法(暴力)
读懂题目我们可以采用暴力的方法来解决本题目,我们可以两重循环的方式进行求解,我们遍历q次查询,找到每一次遍历的数对个数,并判断是否满足条件(这块有一点我们需要注意,对于判断是否满足条件我们不能暴力判断,两个数的最小值是否等于两个是的最小公倍数,那样会超时,我们要想到等式一边的值一定是min(a,b)中的a或者b,所以判断等价于(a%b==0||b%a==0),这样就不会超时)。下面是完整代码:
class Solution { public: vector<int> PermutationQuery(int n, int q, vector<int>& p, vector<int>& l1, vector<int>& r1, vector<int>& l2, vector<int>& r2) { vector<int> ans(q,0); for(int i=0;i<q;i++){ for(int j=l1[i];j<=r1[i];j++){ int a=p[j]; for(int k=l2[i];k<=r2[i];k++){ int b=p[k]; //不能直接判断会超时 //分析后的判断a%b==0||b%a==0 if(a%b==0||b%a==0){ ans[i]++; } } } } return ans; } };
时间复杂度: 对于每一次都需要二重循环
空间复杂度: 需要额外开辟数组返回答案
优缺点:时间复杂度高,但是便于实现
三.算法(java实现)
同样也可以采用java去实现,下面是完整代码:
import java.util.*; public class Solution { //java的静态代码块和静态成员变量 static final int[] num; static{ num=new int[100005]; } public int[] PermutationQuery (int n, int q, int[] p, int[] l1, int[] r1, int[] l2, int[] r2) { for(int i=0;i<q;i++){ for(int j=l1[i];j<=r1[i];j++){ int a=p[j]; for(int k=l2[i];k<=r2[i];k++){ int b=p[k]; //不能直接判断会超时 //分析后的判断a%b==0||b%a==0 if(a%b==0||b%a==0){ num[i]++; } } } } //为了使返回值符合要求 int[] ans=new int[q]; for(int i=0;i<q;i++){ ans[i]=num[i]; } return ans; } }
时间复杂度:对于每一次都需要二重循环
空间复杂度:需要额外开辟数组返回答案(java的返回值相比于c++还比较麻烦)
优缺点:时间复杂度高,但是便于实现