我在Hackerrank [1]上解决了这个问题:https://www.hackerrank.com/challenges/gridland-metro
Gridland城市被表示为 n by m 矩阵,其中行的编号从1到 n 且列数从1到 m 。
Gridland有一个火车轨道网络,总是沿着一条直线水平线运行。换句话说,火车轨道的起点和终点是( r,c1 )和( r,c2 ),其中 r 表示行号 c1 表示起始列, c2 表示列车轨道的结束列。
格特兰市市长正在调查该市以确定可放置灯柱的位置数量。灯柱可以放置在没有被火车轨道占据的任何单元中。
鉴于Gridland及其 k 列车轨道的地图,找到并打印市长可以放置路灯柱的单元格数。
注意:火车轨道可能(或可能不)与同一行内的其他火车轨道重叠。
输入格式
第一行包含三个以空格分隔的整数,用于描述 n (行数)的相应值, m (列数)和 k (列车轨道数)。 k 后续行的每一行 i 包含三个以空格分隔的整数,用于描述的相应值用于定义火车轨道的 r,c1, 和 c2 。
打印一个整数,表示市长可以安装灯柱的单元格数。
这是我的解决方案:
import java.io. * ;
import java.util. * ;
public class Solution {
public static void main(String[] args) {
/* Enter your code here. Read input from STDIN. Print output to STDOUT. Your class should be named Solution. */
Scanner input = new Scanner(System. in );
int n = input.nextInt();
int m = input.nextInt();
int k = input.nextInt();
int[][] arr = new int[n][m];
int occupied = 0;
for (int i = 0; i < n; i++) {
Arrays.fill(arr[i], 0);
}
for (int i = 0; i < k; i++) {
int r = input.nextInt() - 1;
int c1 = input.nextInt() - 1;
int c2 = input.nextInt() - 1;
for (int j = c1; j <= c2; j++) {
arr[r][j] = -1;
}
}
int count = 0;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (arr[i][j] != -1) {
count++;
}
}
}
System.out.println(count);
}
}
有人能在我的代码中指出问题吗? (它只是提交了4个测试用例)
答案 0 :(得分:0)
问题中的约束是1<=n,m<=10^9
。
你不能声明这么大的二维数组,因为它需要大量的堆空间,例如,如果n,m都是10 ^ 9,则arr的大小为{{1} }。
这个问题可以在不使用这个大阵列的情况下解决。如果您需要任何正确方法的帮助,我可以提供帮助,但请先尝试自己。
答案 1 :(得分:0)
我使用HashMap编写了这个解决方案,我正在维护一个map Integer是行号,hashset是特定行访问的列集。维护此映射以检查是否存在任何重叠轨道。代码为小测试用例提供了正确的答案。但是,在大多数测试用例中,由于超时而失败。任何优化此代码的帮助都非常受欢迎。
import java.io.*;
import java.util.*;
import java.text.*;
import java.math.*;
import java.util.regex.*;
public class Solution {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
long n = sc.nextInt();
long m = sc.nextInt();
int k = sc.nextInt();
HashMap<Integer,HashSet> map = new HashMap<Integer,HashSet>();
long count = n*m;
for (int i =0;i<k;i++)
{
HashSet<Integer> set = new HashSet<Integer>();
int row = sc.nextInt();
int c1 = sc.nextInt();
int c2 = sc.nextInt();
//System.out.println(row+" "+ c1+" "+c2);
if (map.containsKey(row))
{
set = map.get(row);
for (int j = c1;j<=c2;j++)
{
if(set.add(j)) count--;
}
//if (set.add(c2)) count--;
map.put(row,set);
}
else
{
for (int p = c1;p<=c2;p++)
{
if (set.add(p)) count --;
}
//if (set.add(c2)) count--;
map.put(row,set);
}
}
System.out.println(count);
}
}
答案 2 :(得分:0)
我不打算在这里提供解决方案,因为我不认为它符合HackerRank的精神。但是,我提供了一些提示并确定了代码的问题。
Scanner input = new Scanner(System.in);
int n = input.nextInt();//ERROR: n ranges from 1 to 10E9, read in as a String
int m = input.nextInt();//ERROR: m ranges from 1 to 10E9, read in as String
int k = input.nextInt();
int[][] arr = new int[n][m];/*ERROR: The range of an int is 2E31-1 and large
integers will cause stack overflow anyway.
You'll need to consider a data structure
that's compatible w/ strings. Hint, consider
a hash table. */
int occupied = 0;
for (int i = 0; i < n; i++) {
Arrays.fill(arr[i], 0);
}
for (int i = 0; i < k; i++) {
int r = input.nextInt() - 1;//ERROR: r ranges from 1 to 10E9, read in as a String
int c1 = input.nextInt() - 1;//ERROR: c1 ranges from 1 to 10E9, read in as a String
int c2 = input.nextInt() - 1;//ERROR: c2 ranges from 1 to 10E9, read in as a String
for (int j = c1; j <= c2; j++) {
arr[r][j] = -1;
}
}
/* NOTE: A train track may (or may not) overlap other train tracks within the
same row. Hence, your algorithm will need to account for track overlaps
and tracks that are in between of each other. For example, if a track
overlaps with another track in the same the row, the tracks should be
merged into a single track. If a smaller track is contained in a bigger
track, the smaller track should be ignored.*/
int count = 0;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (arr[i][j] != -1) {
count++;
}
}
}
System.out.println(count);