No.0002-CareerCup

Given a sparse matrix, implement below two methods: void set(int row, int col, int val) //Update value at given row and col; int sum(int row, int col) //Get sum from top left corner to given row, col sub-matrix.
给出一个稀疏矩阵,要求实现两个方法:第一个是更新指定行列的元素值,第二个是给出行列值,求从左上到该坐标的子矩阵的元素值之和。

1. 询问

假如不明白稀疏矩阵是什么意思,应该要问清楚。

2. 分析

常规方法

一个非常自然的想法就是存储[row, col, val]这样的元素。那么空间复杂度上是O(n)。
假如用这种存储方法,set函数就必须遍历所有元素来找到对应的row和col值,复杂度O(n);而sum函数,也需要遍历所有元素把范围内的挑出来相加,复杂度还是O(n)。

如何改进

在上面这种解法中,瓶颈主要是在查找。可以考虑利用哈希表来降低查找的时间复杂度。
但是,这道题里面行和列两者是并列的,如何映射?

解法1

一种思路是把行和列映射成为一个值,而且不同的行列值这个值必须不同。例如,我们知道mxn的矩阵里面有m*n个元素,因此可以用序号0~m*n-1来唯一确定这些元素,也就是说:
hash(row, col) = row*n + col,同样从hash到row和col: row = hash(row, col)//n, col = hash(row, col)%n。
建立如上映射关系之后,set方法就可以直接查找,时间复杂度降为O(1);而对于sum方法,还是要遍历所有元素,O(n)。此外,因为使用了哈希表,空间复杂度为O(n)。

解法2

此外,因为有row和col两个查询参数,可以用两层哈希表。第一层是row为key,value则是下一层的哈希表;第二层是col为key,然后给的元素值作为value。也就是{row:{col:val}}。
该方法复杂度和方法1还是一样。

拓展

上面两种方法,set函数都已经达到了理论最优,但是sum函数和最直接的解法相比较也没有任何改进。可不可以提高sum函数的复杂度呢?
其实如果是普通的矩阵,可以用二维的Fenwick Tree来实现,查询复杂度O(logm*logn),不过代码比较难写,还需要构造时间O(m*n)和更新数据O(logm*logn),对于稀疏矩阵而言,并不算太合适。

3. 代码

class Solution:
    def __init__(self, m, n):
        self.m, self.n, self.d = m, n, {}

    def set(self, row, col, val):
        h = (row - 1) * self.n + col
        self.d[h] = val

    def sum(self, row, col):
        s = 0
        for key in self.d.keys():
            r, c = key // self.n, key % self.n
            if r <= row and c <= col:
                s += self.d[key]
        return s

4. 总结

难度Easy,主要是考察哈希表的使用。

你可能感兴趣的:(No.0002-CareerCup)