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

举报
二当家的白帽子 发表于 2021/12/10 13:15:12 2021/12/10
【摘要】 1476. 子矩形查询:请你实现一个类 SubrectangleQueries ,它的构造函数的参数是一个 rows x cols 的矩形(这里用整数矩阵表示),并支持以下两种操作:updateSubrectangle(int row1, int col1, int row2, int col2, int newValue)用 newValue 更新以 (row1,col1) 为左上角且以...

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, rectangle[i][j] <= 1 0 9 10^9
  • 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://bbs.huaweicloud.com/community/usersnew/id_1628396583336561 博客原创~


【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。