题目:
编写一种算法,若M × N矩阵中某个元素为0,则将其所在的行与列清零。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27# 样例1
输入:
[
[1,1,1],
[1,0,1],
[1,1,1]
]
输出:
[
[1,0,1],
[0,0,0],
[1,0,1]
]
# 样例2
输入:
[
[0,1,2,0],
[3,4,5,2],
[1,3,1,5]
]
输出:
[
[0,0,0,0],
[0,4,5,0],
[0,3,1,0]
]
解题方法:
读到零直接修改行列这种做法会是数据变脏,导致结果不符合预期,因此需要将有0的行和列存下来,然后再想办法置零,这里有两种置零策略,前者时间复杂度更低,后者find()
函数的复杂度为\(O(n)\)
使用标记数组:遍历矩阵,找到有零存在的所有行和列;分别遍历这些行和列,并置零
时间复杂度为\(O(n^2)\),额外的空间复杂度为\(O(n)\)
使用标记数组:遍历矩阵,找到有零存在的所有行和列;重新遍历矩阵,判断当前所在的行列是否属于有零存在的行列,因为用
set
集合存储了为零的行列,因此利用find()
函数即可时间复杂度为\(O(n^3)\),因为
find()
函数的复杂度为\(O(n)\),额外的空间复杂度为\(O(n)\)使用两个标记变量:用矩阵的第一行和第一列来当标记数组,然后用两个标记变量标记原本第一行和第一列是否出现过0,这样就可以降低空间复杂度了!目前未实现
时间复杂度为\(O(n^3)\),额外的空间复杂度为\(O(1)\)
解法一:使用标记数组
集合的定义:
set<int> set_row;
集合添加元素:
set_row.insert(int i);
- 添加pair:
set<pair<T1, T2>> set_pair; set_pair.emplace(T1 a, T2, b);
集合删除元素:成员函数 clear() 会删除 set 的所有元素。成员函数 erase() 会删除迭代器指定位置的元素或与对象匹配的元素。
set_row.erase(int a);
删除对应的元素,如果没有会返回什么?set_row.erase(iterator);
删除迭代器位置元素set_row.clear();
删除全部元素
集合的遍历(只能用iterator):
1
2
3
4
5set<int>::iterator it;
for(it = set_row.begin(); it != set_row.end(); ++it)
{
cout << *it << endl; // *it为取it地址下的值
}查找元素是否在集合中:
if(set_row.find(int a) != set_row.end()) return true;
find的复杂度为\(O(n)\),底层逻辑就是遍历整个set,直到end()
1 | class Solution { |
解法二:使用标记数组
- 集合的find操作,见上文
1 | class Solution { |