【k倍区间】前缀和;long / int的比较

k倍区间

范围:[1, 105]

public static long numOfK(int[] nums, int k) {
    
    
	int len = nums.length;
	//long[] pre = new long[len + 1];
	long sum = 0;
	long[] y = new long[k];
	for (int i = 1; i <= len; i++) {
    
    
		//pre[i] += nums[i - 1] + pre[i - 1];
		sum += nums[i];
		y[(int) (sum % k)]++;
	}
	long res = y[0];

	for (int i = 0; i < k; i++) {
    
    
		res += y[i] * (y[i] - 1) / 2;
	}

	return res;
}

关键

  • 虽然要计算前缀和,但是此题不需要使用每个元素的前缀和,所以无需使用数组 pre[]去记录每个元素的前缀和,只需要sum记录一下(一次性)。

  • 为什么数组y[](记录相同余数个数)是long类型?

    1. 为什么会涉及到long
      因为本题的范围是105,在记录前缀和时max(N*K) = 1010,超过int
    2. 数组y[]是用来存余数,余数<k∈[1, 105](余数<除数),为什么还需要用long
      因为这行代码:
    res += y[i] * (y[i] - 1) / 2;
    

    根据运算顺序,先计算乘除,这就意味着:如果y[]int,那么在进行y[i] * (y[i] - 1) / 2运算时,如果超过了int范围,依然会转成int(有损失)。

    其实,y[]可以用int y[],但是在这行代码得调整为:

    res += (long)y[i] * (y[i] - 1) / 2; //int往高类型long转换
    

    Q:那sum += nums[i];没有这样的问题吗?(long sum / int[] nums
    A:sum += nums[i]本质上是sum = sum + nums[i] // 往高类型转换

    但是,res += y[i] * (y[i] - 1) / 2 => res = res + y[i] * (y[i] - 1) / 2 是先计算乘除,乘除后结果仍是int(在此处损失),再和long相加。

猜你喜欢

转载自blog.csdn.net/m0_60641871/article/details/129766312
今日推荐