我有一个像下面那样的4 * 5矩阵。
1 1 1 0 0
1 0 0 0 1
1 1 1 0 0
0 0 0 1 1
我正在寻找java中的程序来获取以下组的模式。
上述任何一组都不应相交。 这是Zycus infotech的一个面试问题,我无法解决。任何能够提出解决这个问题的逻辑的人都会很有帮助!
答案 0 :(得分:2)
我将假设对数据的处理和组织方式没有限制。通过这个我的意思是你没有必要用给定的矩阵就地做任何事情,并且你可以创建辅助数据结构来帮助你完成任务(因为我在我的答案中使用了一个额外的ArrayList)。
我们从:
开始int[][] matrix = {{1,1,1,0,0},{1,0,0,0,1},{1,1,1,0,0},{0,0,0,1,1}};
对应我们原来的结构:
1 1 1 0 0
1 0 0 0 1
1 1 1 0 0
0 0 0 1 1
所以,我们马上看到,为了获得一组4个1,我们需要从第2行到第3行,然后得到一个5个1的组,我们需要从第4行回来这意味着我们基本上将这个矩阵视为1和0的连续线,并且矩阵结构使这一点令人困惑。因此,我们可以将其扁平化以使事情变得更容易:
List<Integer> list = new ArrayList<Integer>();
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[i].length; j++) {
list.add(matrix[i][j]);
}
}
这给了我们:
[1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1]
这看起来好一点了!但是,我们仍然有这个列表的问题在一个循环中包围自己。现在,我们可以编写代码来解释这个列表本身仍然可能相邻的1,或者我们可以修改列表,以便我们知道100%肯定在列表的开头和结尾之间没有相邻的1。这意味着我们希望列表以0开头或结尾,从而确保没有邻接。我们通过从列表开头到列表末尾的所有1的一个很好的小移动来实现这一点。
// keep track of how we're adjusting the list so we can calculate the proper start of adjacency
int adjustment = 0;
for (int i = 0; i < list.size(); i++) {
if (list.get(i) == 1) {
list.add(list.remove(i));
i--;
adjustment++;
} else {
break;
}
}
现在我们有:
[0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1]
我们现在可以很容易地根据要求获得所需的1组。
如果你只是想计算1的邻接:
int count = 0;
for (Integer a : list) {
if (a == 1) {
count++;
} else {
if (count > 0) {
System.out.println("Group of " + count + " adjacent 1's");
}
count = 0;
}
}
if (count > 0) {
System.out.println("Group of " + count + " adjacent 1's");
}
如果您正在寻找1组5个相邻的1个,2个相邻的1个组和1个1个相邻1组没有交叉点,那么我们可以这样做:
for (int num : Arrays.asList(5, 2, 2, 1)) {
int count = 0;
int start = -1;
for (int i = 0; i < list.size(); i++) {
if (list.get(i) == 1) {
if (start == -1) {
start = i;
}
count++;
} else {
start = -1;
count = 0;
}
if (count == num) {
System.out.println("Group of " + num + " adjacent 1's starting at " + ((start + adjustment) / 5) + "," + ((start + adjustment) % 5));
for (int j = start; j < start + count; j++) {
list.set(j, 0);
}
break;
}
}
}
通过查看计数相邻的列表来工作,直到我们达到我们想要的数量(从我们的最大数字(5)开始并逐渐减小),然后我们输出它的开始,然后去掉那些相邻的列表中的1(通过将它们设置为0)。这样,我们就不会意外地再次计算它们(满足我们对没有交叉群的限制)。一旦我们得到了相邻1的所需数量,我们也存储了它的起始位置。然后我们根据从列表开头到后面移动了多少1来调整它,然后除以得到行号并使用模数来获得列号。
我们的结果是:
Group of 5 adjacent 1's starting at 3,3
Group of 2 adjacent 1's starting at 1,4
Group of 2 adjacent 1's starting at 2,1
Group of 1 adjacent 1's starting at 1,0
到目前为止,我已假设矩阵中始终至少有一个0。如果没有,您需要在我的循环之前添加list.contains(0)
检查,以便将1从列表的前面移动到列表的后面。
将这些全部放在一个代码块中:
int[][] matrix = {{1,1,1,0,0},{1,0,0,0,1},{1,1,1,0,0},{0,0,0,1,1}};
List<Integer> list = new ArrayList<Integer>();
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[i].length; j++) {
list.add(matrix[i][j]);
}
}
int adjustment = 0;
if (list.contains(0)) {
for (int i = 0; i < list.size(); i++) {
if (list.get(i) == 1) {
list.add(list.remove(i));
i--;
adjustment++;
} else {
break;
}
}
}
int count = 0;
for (Integer a : list) {
if (a == 1) {
count++;
} else {
if (count > 0) {
System.out.println("Group of " + count + " adjacent 1's");
}
count = 0;
}
}
if (count > 0) {
System.out.println("Group of " + count + " adjacent 1's");
}
for (int num : Arrays.asList(5, 2, 2, 1)) {
int count2 = 0;
int start = -1;
for (int i = 0; i < list.size(); i++) {
if (list.get(i) == 1) {
if (start == -1) {
start = i;
}
count2++;
} else {
start = -1;
count2 = 0;
}
if (count2 == num) {
System.out.println("Group of " + num + " adjacent 1's starting at " + ((start + adjustment) / 5) + "," + ((start + adjustment) % 5));
for (int j = start; j < start + count2; j++) {
list.set(j, 0);
}
break;
}
}
}