给你一个有序整数数组,数组中的数可以是正数、负数、零,请实现一个函数,这个函数返回一个整数:返回这个数组所有数的平方值中有多少种不同的取值。举例:
-
nums = {-1,1,1,1},
那么你应该返回的是:1。因为这个数组所有数的平方取值都是1,只有一种取值
-
nums = {-1,0,1,2,3}
你应该返回4,因为nums数组所有元素的平方值一共4种取值:1,0,4,9
在往下看之前,请先进行思考,如果当时是你在面试,你会给出什么样的结题思路?下面会给出两种解法,最优解:时间复杂度:O(n)、空间复杂度O(1)。无论有没有思路,在往下看之前一定要有自己的思考。
分析:
方法一:暴力法,先算平方和,保存在一个数组中,然后使用集合统计不同。
方法二:集合保存平方和。直接先遍历一次得到平方和,将平方和放入集合中,输出集合的大小。时间复杂度为O(n),空间复杂度为O(n).
方法三:以上两种方法都没有使用到数组有序,需要计算的是不同的平方和,那么平方和相同时有两种情况,一:两个元素是相邻元素,元素值本身相同;二:两个元素绝对值相等;对于第一种情况可以直接比较是否与相邻元素相等,相等时不计数;对于第二种情况利用数组有序的条件,使用双指针分别指向数组的头和尾,相等时不计数。两指针向中间移动。
public static int DifferentMi(int nums[]){
int cnt=0;
int i=0,j=nums.length-1;
while(i<j){
while(i<j && nums[i]*nums[i]==nums[j]*nums[j])
i++;
if(nums[i]*nums[i]>nums[j]*nums[j]){
while(i<j && nums[i]*nums[i]==nums[i+1]*nums[i+1])
i++;
i++;
}else{
while(i<j && nums[j]*nums[j]==nums[j-1]*nums[j-1])
j--;
j--;
}
cnt++;
}
return cnt;
}