lc307.区域和检索 - 数组可修改

lc307.区域和检索 - 数组可修改_第1张图片

暴力解法

创建方法,通过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;
    }
}

分块处理

lc307.区域和检索 - 数组可修改_第2张图片

其中 n / size 向上取整

 

构造函数
  • 计算块大小size=根号n

lc307.区域和检索 - 数组可修改_第3张图片

  • 初始化sum块数组
update函数
  • 计算新的块数组sum
  • 更新nums数组
sumRange函数

lc307.区域和检索 - 数组可修改_第4张图片

lc307.区域和检索 - 数组可修改_第5张图片

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;
    }
}

 

你可能感兴趣的:(java,算法,数据结构)