报告错误
如果你发现该网页中存在错误/显示异常,可以从以下两种方式向我们报告错误,我们会尽快修复:
- 使用 CS Club 网站错误 为主题,附上错误截图或描述及网址后发送邮件到 286988023@qq.com
- 在我们的网站代码仓库中创建一个 issue 并在 issue 中描述问题 点击链接前往Github仓库
题目描述
题目会给你一个HxW的矩阵,并且该矩阵中只有n个元素拥有数值。在获得矩阵之后可以进行以下的操作:
如果有一列没有元素的话,则将其他的元素都向左移动一位;
如果有一行没有元素的话,则将所有的元素都向上移动一位;
打印出所有有效元素在进行操作之后的位置
思路
思路1:
前缀和数组:
用数组中的index来表示每一个元素的位置,数组中的内容是输出的时候,这一个行/列需要减去多少才是化简之后的位置。
但是这样会有一个问题,因为 \(1\le H,W\le 10^9\) 所以数组中的元素过多,直接导致了爆栈。
思路2
本质上是思路一的改进方法:
因为上一个方法发生了爆栈的情况,所以第二个方法不用数组中的index来表示行或列,直接使用两个数组来表示每一个行/列需要减去多少。因为这样子可以大大的减小空间。具体求出每一个行/列需要减去的数量 \(f(n) = row(n)-row(n-1)+f(n-1)\)
并将这些所有的行/列需要减去的数量都一一对应储存到两个Hashmap里面,最后在输出的时候直接提取这个数就好了。这一步主要是降低复杂度,如果不将这些数放进Hashmap中就需要用O(N^2)的复杂度来输出,只是放到Hashmap里只需要O(N)的复杂度,提取时只要O(1)的复杂度。
复杂度分析:
将所有的数放进数组里: \(O(N)\) 将两个数组进行排序: \(O(N\log N)\) 将所有的需要减去的数算出来: \(O(N)\) 放进Hashmap里: \(O(N)\) 最后输出的收提取Hashmap里面的数: \(O(1)\) 所以整体复杂度为: \(O(N\log N)\)
代码实现
import java.util.*;
public class reorder{
public static void main(String [] args){
Scanner in = new Scanner(System.in);
int h = in.nextInt();
int w = in.nextInt();
int n = in.nextInt();
HashSet<Integer>row = new HashSet<Integer>();
HashSet<Integer>col = new HashSet<Integer>();
oneDot [] coordinate = new oneDot [n];
for (int i = 0; i < n; i++) {
int theRow = in.nextInt()-1;
int theCol = in.nextInt()-1;
row.add(theRow);
col.add(theCol);
coordinate[i] = new oneDot(theRow, theCol);
}
int rownum = row.size();
int colnum = col.size();
int [] rows = new int [rownum];
int [] cols = new int [colnum];
int index = 0;
for(int oneRow:row){
rows[index] = oneRow;
index++;
}
index = 0;
Arrays.sort(rows);
for(int oneCol:col){
cols[index] = oneCol;
index++;
}
Arrays.sort(cols);
int [] rowm = new int [rownum];
int [] colm = new int [colnum];
rowm[0] = rows[0]-0;
for (int i = 1; i < rowm.length; i++) {
rowm[i] = rows[i]-rows[i-1]+rowm[i-1]-1;
}
colm[0] = cols[0]-0;
for (int i = 1; i < colm.length; i++) {
colm[i] = cols[i]-cols[i-1]+colm[i-1]-1;
}
HashMap <Integer,Integer> rowminus= new HashMap<Integer,Integer>();
HashMap <Integer,Integer> colminus= new HashMap<Integer,Integer>();
for (int i = 0; i < rowm.length; i++) {
rowminus.put(rows[i], rowm[i]);
}
for (int i = 0; i < colm.length; i++) {
colminus.put(cols[i], colm[i]);
}
for (int i = 0; i < coordinate.length; i++) {
System.out.println((coordinate[i].row-rowminus.get(coordinate[i].row)+1)+" "+((coordinate[i].col-colminus.get(coordinate[i].col))+1));
}
}
}
class oneDot{
int row;
int col;
public oneDot(int row,int col){
this.row = row;
this.col = col;
}
}