给定三个数a,b,c,请问满足以下3个条件的xy组合数有多少个?
提示:阿里笔试原题,懂得双指针解决单调问题的优化方法
题目
给你3个数abc,请问你有多少这样的xy组合数?使得下列三个条件成立?
a<= x^^2 <=b
a<= y^^3 <=b
x^^2 - y^^3 <=c
abc数量的范围10^^6
一、审题
示例:这就不需要我再举例子了吧
二、解题
abc数量的范围10^^6
也就是说你不能设计o(n^^ 2) 的算法,否则就是10^^12的复杂度,过不了的
这个题要优化为o(n) 的算法复杂度
大流程也很容易,学过就熟悉了:
——1.先罗列x,放入数组xArr
——2.罗列y,放入数组yArr
既然xy他们都是递增的,自然就有单调性,双指针解决没问题【这个思想要牢记】
——然后双指针p1,p2,找满足条件3的位置p2,则可以统计:每次以p1开头的x,达到条件3的位置p2的y,组合xy有几个? N2-p2个,因为p2的右边y更大,则条件3得到的值更小,均符合条件。
但是p1的x - p2左边的y们是不会满足条件的,y太小不行
因此真题p1,p2往右挪一遍,复杂度就是了o(n)
看图:
看代码:
public static int findHowMany(int a, int b, int c){
//abc都正整数
// 1.先罗列x,放入数组xArr
// 2.罗列y,放入数组yArr
List<Integer> xArr = new ArrayList<>();//因为不知道有多少x,只能是静态数组了
List<Integer> yArr = new ArrayList<>();
int x = 1;
while (true){
int t2 = x * x;
int t3 = x * t2;
if (a <= t2 && t2 <= b) xArr.add(t2);//直接记平方,待会用即可
if (a <= t3 && t3 <= b) yArr.add(t3);
if (t3 > b) break;//当t3都越界了,那就没必要玩了
x++;
}
int p1 = 0;
int p2 = 0;
int N1 = xArr.size();
int N2 = yArr.size();
int ans = 0;
while (p1 < N1){
int d = xArr.get(p1) - yArr.get(p2);
if (d <= c) {
ans += N2 - p2;
p1++;//满足就算当前x已经有这么多组合,下一步,以下一个x开头,x增大,势必又有很多答案
}
else p2++;//条件不足,则y太小,需要增加y
if (p2 == N2) break;
}
return ans;
}
测试:
public static void test(){
Scanner in = new Scanner(System.in);
int a = in.nextInt();
int b = in.nextInt();
int c = in.nextInt();
int ans = findHowMany(a, b, c);
System.out.println(ans);
}
public static void main(String[] args) {
test();
}
总结
提示:重要经验:
1)双指针是解决单调问题的良药
2)调代码就是要慢慢写,然后抠清楚边界,多练习,找感觉!