【算法】1476. 子矩形查询(java / c / c++ / python / go / rust)

简介: 请你实现一个类 SubrectangleQueries ,它的构造函数的参数是一个 rows x cols 的矩形(这里用整数矩阵表示),并支持以下两种操作: updateSubrectangle(int row1, int col1, int row2, int col2, int newValue) 用 newValue 更新以 (row1,col1) 为左上角且以 (row2,col2) 为右下角的子矩形。 getValue(int row, int col) 返回矩形中坐标 (row,col) 的当前值。

1476. 子矩形查询:

请你实现一个类 SubrectangleQueries ,它的构造函数的参数是一个 rows x cols 的矩形(这里用整数矩阵表示),并支持以下两种操作:

  1. updateSubrectangle(int row1, int col1, int row2, int col2, int newValue)
  • 用 newValue 更新以 (row1,col1) 为左上角且以 (row2,col2) 为右下角的子矩形。
  1. getValue(int row, int col)
  • 返回矩形中坐标 (row,col) 的当前值。

样例 1


输入:
    
  ["SubrectangleQueries","getValue","updateSubrectangle","getValue","getValue","updateSubrectangle","getValue","getValue"]
  [[[[1,2,1],[4,3,4],[3,2,1],[1,1,1]]],[0,2],[0,0,3,2,5],[0,2],[3,1],[3,0,3,2,10],[3,1],[0,2]]

输出:

  [null,1,null,5,5,null,10,5]

解释:

  SubrectangleQueries subrectangleQueries = new SubrectangleQueries([[1,2,1],[4,3,4],[3,2,1],[1,1,1]]);  
  // 初始的 (4x3) 矩形如下:
  // 1 2 1
  // 4 3 4
  // 3 2 1
  // 1 1 1
  subrectangleQueries.getValue(0, 2); // 返回 1
  subrectangleQueries.updateSubrectangle(0, 0, 3, 2, 5);
  // 此次更新后矩形变为:
  // 5 5 5
  // 5 5 5
  // 5 5 5
  // 5 5 5 
  subrectangleQueries.getValue(0, 2); // 返回 5
  subrectangleQueries.getValue(3, 1); // 返回 5
  subrectangleQueries.updateSubrectangle(3, 0, 3, 2, 10);
  // 此次更新后矩形变为:
  // 5   5   5
  // 5   5   5
  // 5   5   5
  // 10  10  10 
  subrectangleQueries.getValue(3, 1); // 返回 10
  subrectangleQueries.getValue(0, 2); // 返回 5

样例 2

输入:

  ["SubrectangleQueries","getValue","updateSubrectangle","getValue","getValue","updateSubrectangle","getValue"]
  [[[[1,1,1],[2,2,2],[3,3,3]]],[0,0],[0,0,2,2,100],[0,0],[2,2],[1,1,2,2,20],[2,2]]

输出:

  [null,1,null,100,100,null,20]

解释:

  SubrectangleQueries subrectangleQueries = new SubrectangleQueries([[1,1,1],[2,2,2],[3,3,3]]);
  subrectangleQueries.getValue(0, 0); // 返回 1
  subrectangleQueries.updateSubrectangle(0, 0, 2, 2, 100);
  subrectangleQueries.getValue(0, 0); // 返回 100
  subrectangleQueries.getValue(2, 2); // 返回 100
  subrectangleQueries.updateSubrectangle(1, 1, 2, 2, 20);
  subrectangleQueries.getValue(2, 2); // 返回 20

提示

  • 最多有 500 次updateSubrectangle 和 getValue 操作。
  • 1 <= rows, cols <= 100
  • rows == rectangle.length
  • cols == rectangle[i].length
  • 0 <= row1 <= row2 < rows
  • 0 <= col1 <= col2 < cols
  • 1 <= newValue, rectanglei <= 109
  • 0 <= row < rows
  • 0 <= col < cols

分析

  • 矩形的初始值肯定要保存下来。
  • 然后最直观的方式就是每次更新操作就把矩形中的值老老实实更新掉,取值就直接返回就可以了。
  • 根据提示,我们可以知道矩形最大是100 * 100,也就是每次更新值最多可能需要更新10000个值,但是更新次数最多会有500次,所以我们可以记录每次更新操作,在取值的时候我们倒着查找历史操作,如果点没有做过更新,那就是原值。这样更新操作的时间复杂度仅仅是O(1),而取值操作最多就是500次循环去查找历史。
  • 到底哪种方式好不是绝对的,可以根据实际情况,本题的情况是值多,操作少,所以我们不做更新,而是把历史操作存下来。

题解

java

class SubrectangleQueries {
    private final int[][]     rectangle;
    private       List<int[]> history = new ArrayList<>();

    public SubrectangleQueries(int[][] rectangle) {
        this.rectangle = rectangle;
    }

    public void updateSubrectangle(int row1, int col1, int row2, int col2, int newValue) {
        history.add(new int[]{row1, col1, row2, col2, newValue});
    }

    public int getValue(int row, int col) {
        for (int i = history.size() - 1; i >= 0; --i) {
            int[] h = history.get(i);
            if (row >= h[0] && row <= h[2]
                && col >= h[1] && col <= h[3]) {
                return h[4];
            }
        }
        return rectangle[row][col];
    }
}

/**
 * Your SubrectangleQueries object will be instantiated and called as such:
 * SubrectangleQueries obj = new SubrectangleQueries(rectangle);
 * obj.updateSubrectangle(row1,col1,row2,col2,newValue);
 * int param_2 = obj.getValue(row,col);
 */

c

typedef struct {
    int value[100][100];
    int history[500][5];
    int history_size;
} SubrectangleQueries;


SubrectangleQueries *subrectangleQueriesCreate(int **rectangle, int rectangleSize, int *rectangleColSize) {
    SubrectangleQueries *obj = NULL;

    obj = (SubrectangleQueries *) malloc(sizeof(SubrectangleQueries));
    if (obj == NULL) {
        return NULL;
    }

    for (int i = 0; i < rectangleSize; ++i) {
        for (int j = 0; j < rectangleColSize[i]; ++j) {
            obj->value[i][j] = rectangle[i][j];
        }
    }

    return obj;
}

void
subrectangleQueriesUpdateSubrectangle(SubrectangleQueries *obj, int row1, int col1, int row2, int col2, int newValue) {
    int *h = obj->history[obj->history_size++];
    h[0] = row1;
    h[1] = col1;
    h[2] = row2;
    h[3] = col2;
    h[4] = newValue;
}

int subrectangleQueriesGetValue(SubrectangleQueries *obj, int row, int col) {
    for (int i = obj->history_size - 1; i >= 0; --i) {
        int *h = obj->history[i];
        if (row >= h[0] && row <= h[2]
            && col >= h[1] && col <= h[3]) {
            return h[4];
        }
    }
    return obj->value[row][col];
}

void subrectangleQueriesFree(SubrectangleQueries *obj) {
    free(obj);
}

/**
 * Your SubrectangleQueries struct will be instantiated and called as such:
 * SubrectangleQueries* obj = subrectangleQueriesCreate(rectangle, rectangleSize, rectangleColSize);
 * subrectangleQueriesUpdateSubrectangle(obj, row1, col1, row2, col2, newValue);

 * int param_2 = subrectangleQueriesGetValue(obj, row, col);

 * subrectangleQueriesFree(obj);
*/

c++

class SubrectangleQueries {
private:
    vector<vector<int>> rectangle;
    vector<vector<int>> history;
public:
    SubrectangleQueries(vector<vector<int>>& rectangle) : rectangle(rectangle) {
    }

    void updateSubrectangle(int row1, int col1, int row2, int col2, int newValue) {
        history.push_back({row1, col1, row2, col2, newValue});
    }

    int getValue(int row, int col) {
        for (int i = history.size() - 1; i >= 0; --i) {
            vector<int> h = history[i];
            if (row >= h[0] && row <= h[2]
                && col >= h[1] && col <= h[3]) {
                return h[4];
            }
        }
        return rectangle[row][col];
    }
};

/**
 * Your SubrectangleQueries object will be instantiated and called as such:
 * SubrectangleQueries* obj = new SubrectangleQueries(rectangle);
 * obj->updateSubrectangle(row1,col1,row2,col2,newValue);
 * int param_2 = obj->getValue(row,col);
 */

python

class SubrectangleQueries:

    def __init__(self, rectangle: List[List[int]]):
        self.rectangle = rectangle
        self.history = []

    def updateSubrectangle(self, row1: int, col1: int, row2: int, col2: int, newValue: int) -> None:
        self.history.append((row1, col1, row2, col2, newValue))


    def getValue(self, row: int, col: int) -> int:
        for i in range(len(self.history) - 1, -1, -1):
            row1, col1, row2, col2, val = self.history[i]
            if row1 <= row <= row2 and col1 <= col <= col2:
                return val

        return self.rectangle[row][col]


# Your SubrectangleQueries object will be instantiated and called as such:
# obj = SubrectangleQueries(rectangle)
# obj.updateSubrectangle(row1,col1,row2,col2,newValue)
# param_2 = obj.getValue(row,col)

go

type SubrectangleQueries struct {
    rectangle [][]int
    history   [][]int
}

func Constructor(rectangle [][]int) SubrectangleQueries {
    return SubrectangleQueries{rectangle: rectangle}
}

func (this *SubrectangleQueries) UpdateSubrectangle(row1 int, col1 int, row2 int, col2 int, newValue int) {
    this.history = append(this.history, []int{row1, col1, row2, col2, newValue})
}

func (this *SubrectangleQueries) GetValue(row int, col int) int {
    for i := len(this.history) - 1; i >= 0; i-- {
        h := this.history[i]
        if h[0] <= row && row <= h[2] && h[1] <= col && col <= h[3] {
            return h[4]
        }
    }
    return this.rectangle[row][col]
}


/**
 * Your SubrectangleQueries object will be instantiated and called as such:
 * obj := Constructor(rectangle);
 * obj.UpdateSubrectangle(row1,col1,row2,col2,newValue);
 * param_2 := obj.GetValue(row,col);
 */

rust

struct SubrectangleQueries {
  rectangle: Vec<Vec<i32>>,
  history: Vec<(i32, i32, i32, i32, i32)>,
}

/**
 * `&self` means the method takes an immutable reference.
 * If you need a mutable reference, change it to `&mut self` instead.
 */
impl SubrectangleQueries {

  fn new(rectangle: Vec<Vec<i32>>) -> Self {
    Self {rectangle, history: vec![]}
  }

  fn update_subrectangle(&mut self, row1: i32, col1: i32, row2: i32, col2: i32, new_value: i32) {
    self.history.push((row1, col1, row2, col2, new_value));
  }

  fn get_value(&self, row: i32, col: i32) -> i32 {
    for &(r1, c1, r2, c2, val) in self.history.iter().rev() {
      if r1 <= row && row <= r2 && c1 <= col && col <= c2 {
        return val
      }
    }
    self.rectangle[row as usize][col as usize]
  }
}

/**
 * Your SubrectangleQueries object will be instantiated and called as such:
 * let obj = SubrectangleQueries::new(rectangle);
 * obj.update_subrectangle(row1, col1, row2, col2, newValue);
 * let ret_2: i32 = obj.get_value(row, col);
 */

原题传送门:https://leetcode-cn.com/problems/subrectangle-queries/


非常感谢你阅读本文~
放弃不难,但坚持一定很酷~
希望我们大家都能每天进步一点点~
本文由 二当家的白帽子:https://developer.aliyun.com/profile/sqd6avc7qgj7y 博客原创~

相关文章
|
11月前
|
设计模式 算法 搜索推荐
Java 设计模式之策略模式:灵活切换算法的艺术
策略模式通过封装不同算法并实现灵活切换,将算法与使用解耦。以支付为例,微信、支付宝等支付方式作为独立策略,购物车根据选择调用对应支付逻辑,提升代码可维护性与扩展性,避免冗长条件判断,符合开闭原则。
2777 35
|
11月前
|
算法 搜索推荐 JavaScript
基于python智能推荐算法的全屋定制系统
本研究聚焦基于智能推荐算法的全屋定制平台网站设计,旨在解决消费者在个性化定制中面临的选择难题。通过整合Django、Vue、Python与MySQL等技术,构建集家装设计、材料推荐、家具搭配于一体的一站式智能服务平台,提升用户体验与行业数字化水平。
|
11月前
|
存储 人工智能 算法
从零掌握贪心算法Java版:LeetCode 10题实战解析(上)
在算法世界里,有一种思想如同生活中的"见好就收"——每次做出当前看来最优的选择,寄希望于通过局部最优达成全局最优。这种思想就是贪心算法,它以其简洁高效的特点,成为解决最优问题的利器。今天我们就来系统学习贪心算法的核心思想,并通过10道LeetCode经典题目实战演练,带你掌握这种"步步为营"的解题思维。
|
11月前
|
存储 算法 搜索推荐
《数据之美》:Java数据结构与算法精要
本系列深入探讨数据结构与算法的核心原理及Java实现,涵盖线性与非线性结构、常用算法分类、复杂度分析及集合框架应用,助你提升程序效率,掌握编程底层逻辑。
|
12月前
|
存储 算法 调度
【复现】【遗传算法】考虑储能和可再生能源消纳责任制的售电公司购售电策略(Python代码实现)
【复现】【遗传算法】考虑储能和可再生能源消纳责任制的售电公司购售电策略(Python代码实现)
512 26
|
12月前
|
机器学习/深度学习 算法 机器人
【机器人路径规划】基于D*算法的机器人路径规划(Python代码实现)
【机器人路径规划】基于D*算法的机器人路径规划(Python代码实现)
454 0
|
12月前
|
机器学习/深度学习 算法 机器人
【机器人路径规划】基于改进型A*算法的机器人路径规划(Python代码实现)
【机器人路径规划】基于改进型A*算法的机器人路径规划(Python代码实现)
689 0
|
12月前
|
机器学习/深度学习 编解码 算法
【机器人路径规划】基于迪杰斯特拉算法(Dijkstra)的机器人路径规划(Python代码实现)
【机器人路径规划】基于迪杰斯特拉算法(Dijkstra)的机器人路径规划(Python代码实现)
781 4
|
12月前
|
机器学习/深度学习 算法 机器人
【机器人路径规划】基于A*算法的机器人路径规划研究(Python代码实现)
【机器人路径规划】基于A*算法的机器人路径规划研究(Python代码实现)
1225 4
|
前端开发 安全 Java
面试官:java8中parallelStream提升数倍查询效率是怎样实现的
业务场景 在很多项目中,都有类似数据汇总的业务场景,查询今日注册会员数,在线会员数,订单总金额,支出总金额等。。。这些业务通常都不是存在同一张表中,我们需要依次查询出来然后封装成所需要的对象返回给前端。那么在此过程中,就可以把这个接口中“大任务”拆分成N个小任务,异步执行这些小任务,等到最后一个小任务执行完,把所有任务的执行结果封装到返回结果中,统一返回到前端展示。
面试官:java8中parallelStream提升数倍查询效率是怎样实现的

热门文章

最新文章

推荐镜像

更多