暴力解法
创建方法,通过switch-case判断所需要调用的方法。
public class RegionsAndSertches {
public static void main(String[] args) {
String[] str = new String[]{"NumArray", "sumRange", "update", "sumRange"};
int[][] arr = new int[][]{{1, 3, 5}, {0, 2}, {1, 2}, {0, 2}};
invoke(str, arr);
}
public static void invoke(String[] str, int[][] arr) {//str表示上面一行字符串输入,arr表示下面一行二维数组输入
NumArray numArray = new NumArray(arr[0]);//第一个必须为NumArray,一定要先创建对象,否则无法调用方法
System.out.println("null");//根据题意返回null
for (int i = 1; i < str.length; i++) {//跳过第一个,索引从1开始
//根据输入的字符串判断需要执行哪个方法
switch (str[i]) {
case "sumRange":
//调用sumRange方法,arr[i][0]为left,arr[i][1]为right,方法返回累加和
System.out.println(numArray.sumRange(arr[i][0], arr[i][1]));
break;
case "update":
//方法不返回,根据题意输出null
numArray.update(arr[i][0], arr[i][1]);
System.out.println("null");
break;
default:
System.out.println("请输入sumRange或update以执行方法");
}
}
}
}
class NumArray {
public int[] nums;
public NumArray(int[] nums) {//构造器
this.nums = nums;//创建了哪个对象,this就表示哪个对象
}
public void update(int index, int val) {
this.nums[index] = val;//题目表示nums[index],不考虑是否加减一
}
public int sumRange(int left, int right) {
int sum = 0;//表示累加和
for (int i = left; i <= right; i++) {//left和right都为索引,不用考虑是否加减一
sum += this.nums[i];
}
return sum;
}
}
分块处理
其中 n / size 向上取整
构造函数
- 计算块大小size=根号n
- 初始化sum块数组
update函数
- 计算新的块数组sum
- 更新nums数组
sumRange函数
class NumArray {
private int[] sum; // sum[i] 表示第 i 个块的元素和
private int size; // 块的大小
private int[] nums;
public NumArray(int[] nums) {
this.nums = nums;
int n = nums.length;
size = (int) Math.sqrt(n);//size的值取根号n,此时的时间复杂度最优
sum = new int[n / size + 1];//向上取整
for (int i = 0; i < n; i++) {
sum[i / size] += nums[i];
}
}
public void update(int index, int val) {
// index/size是sum数组的索引
sum[index / size] = sum[index / size] - nums[index] + val;//更新sum数组
nums[index] = val;//更新nums数组
}
public int sumRange(int left, int right) {
int b1 = left / size, i1 = left % size, b2 = right / size, i2 = right % size;
//因为是从b1这块数据内从0开始的索引,需要调整
//left - left / size - 1, left=0会越界算出来=-1
//避免出现长度为1的数组,一个数被加两次的情况,虽然此时sum3=0,但是sum1和sum2都会加一次
if (b1 == b2) { // 区间 [left, right] 在同一块中
int sum = 0;
for (int j = i1; j <= i2; j++) {
sum += nums[b1 * size + j];
}
return sum;
}
int sum1 = 0;
for (int j = i1; j < size; j++) {//包括left
sum1 += nums[b1 * size + j];
}
int sum2 = 0;
for (int j = 0; j <= i2; j++) {//包括right
sum2 += nums[b2 * size + j];
}
int sum3 = 0;
for (int j = b1 + 1; j < b2; j++) {//b1和b2相等的时候sum3=0,从索引为b1+1的块到b2-1的块之和
sum3 += sum[j];
}
return sum1 + sum2 + sum3;
}
}