【问题标题】:algorithm to find the largest area寻找最大区域的算法
【发布时间】:2013-10-16 17:20:49
【问题描述】:
................................
.XXXXXXXXXXXXXXX.....XXXXXXXXXX.
.X.....X.......X.....X........X.
.X.....X.......XXXXXXX........X.
.XXXXXXXXXXXX.................X.
.X....X.....X.................X.
.X....X.....XXXX..............X.
.XXXXXX........X..............X.
......X........X..............X.
......X........X..............X.
......X........X..............X.
......XXXXXXXXXXXXXXXXXXXXXXXXX.
................................

寻找一种算法来找到最大的区域。这里,“面积”定义为以 X 为界的点 (.) 的数量。

   private static void readFile(File inputFile) throws IOException {

    Scanner fileScanner = new Scanner(inputFile);

    Point previousPoint = null;

    int rowCount = 0;
    while(fileScanner.hasNext()){
        String line = fileScanner.next();

        String[] points = line.split(" ");

        for(int columnCount=0;columnCount<points.length;columnCount++){

            if(points[columnCount].equalsIgnoreCase("x")){
                Point currentPoint = new Point();
                currentPoint.setxValue(columnCount);
                currentPoint.setyValue(rowCount);
            }
        }

        rowCount++;
    }
  }

这是我的第一次,正在努力前进。

【问题讨论】:

  • 必须感谢您花费的时间,在问题窗口中正确设计。
  • 它是一个 boolean[][] 数组还是什么?
  • @user1578872 我会很好的。 en.wikipedia.org/wiki/Flood_fill 从这里开始。试着想出一些东西,告诉我们你至少考虑过这个问题,然后再问
  • 提示:添加@Cruncher(或重要的@)以通知他们有新评论。顺便说一句,我对这个问题得到的反对票数量感到沮丧。人们似乎很快就会做出判断,没有时间编辑帖子(就像您所做的那样)。我投票决定重新打开它,但对这种情况的发生并不抱太大希望。如果您无法从提供的建议中解决问题,请通知我,我会考虑最好的解决方法..
  • @Nirk 我不会投票赞成评论,只是你的回答。 ;)

标签: java algorithm graph


【解决方案1】:

这个算法应该可以工作。您只需要在 Java 中实现它。

  1. 将文件加载到 char[][] 中。 (每行 1 个字符 [])
  2. 通过 char[][] 循环(二维)
    1. 找到“.”后,执行flood fill,更改所有“.”到“,”,每次更改时也会增加一个计数器。
    2. 在洪水填充结束时,将此计数器与全局设置的最大值进行比较。如果它更高,则将其设置为新的最高值。 (如果边缘不是正确的边界,那么如果在洪水填充期间通过在 3 期间设置标志达到边缘,则不要设置此计数器)
  3. 返回您设置的最高值。

如果您对 Java 实现有任何具体问题,请告诉我

地理位:

注意:如果您想排除任何框“外部”的区域,请将其泛洪为 通常,但丢弃在填充过程中碰到边缘的任何区域(跳过 洪水的第 2.2 步)。

在进行洪水填充时,您有两种类型的边界。一堵墙('X')和数组的边缘(您需要明确检查以避免 OutOfBounds 异常)。如果您出界,请继续填充,但设置一个标志,以便您以后知道不要考虑您计算的最大盒子的数字。

【讨论】:

  • 注意:如果您想排除任何框“外部”的区域,请照常填充,但丢弃在填充过程中碰到边缘的任何区域(跳过步骤 2.2 进行填充)。
  • 我知道它已经很久了,但我只是想知道如果点和 X 在一个立方体中,我们如何解决这个问题。
  • @Sree 应该完全相同。但是您必须填充 3 个维度而不是 2 个维度。应该是一个微不足道的修改。
【解决方案2】:

我在面试过程中得到了这个作为作业,这是编译和运行代码

import java.io.BufferedReader;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

public class FindArea {
public static void main(String[] args) 
{
    String fileName="C:\\map.txt";
    FindArea area = new FindArea();
    try{
        FileReader inputFile = new FileReader(fileName);
        BufferedReader bufferReader = new BufferedReader(inputFile);

        char[][] twoArray= new char[100][100];
        String line;
        int i=0;

        while ((line = bufferReader.readLine()) != null) {
            twoArray[i] = line.toCharArray();
            System.out.println(line);
            i++;
        }
        bufferReader.close();

        System.out.println("file read");
        System.out.println("Max area: " + area.getMaxArea(twoArray));

    } catch(Exception e) {
        System.out.println("error : " + e.getMessage());
    }
}

/**
 * Get the maximum area from the given map
 * 
 * @param charArray
 * @return
 */
private int getMaxArea(char[][] charArray) {
    HashMap<Integer, ArrayList<String>> numberOfBoxes = convertToBoxes(charArray);

    numberOfBoxes = mergeOverlapAreas(numberOfBoxes);

    int largeSize = 0; 
    for (Integer key : numberOfBoxes.keySet()) {
        ArrayList<String> list = numberOfBoxes.get(key);
        System.out.println("Key : " + key + " Size : " + list.size());
        if (largeSize < list.size()) {
            largeSize = list.size();
        }
    }
    return largeSize;
}

/**
 * Convert the 2d Array to HashMap
 * Key being the count of boxes and 
 * Value being the list of indexes associations
 * 
 * @param charArray
 * @return
 */
private HashMap<Integer, ArrayList<String>> convertToBoxes(char[][] charArray) {
    HashMap<Integer, ArrayList<String>> numberOfBoxes = new HashMap<Integer, ArrayList<String>>();
    int boxes = 0;

    for(int i=1; i<charArray.length; i++) {

        for (int j=0; j<charArray[i].length; j++) {

            if (charArray[i][j] == '.') {

                boolean isExists = false;

                for(Integer key : numberOfBoxes.keySet()) {

                    ArrayList<String> arrList = numberOfBoxes.get(key);

                    if(arrList != null) {

                        if(arrList.contains((i-1) + "-" + j) ||
                           arrList.contains(i + "-" + (j-1))) {

                            isExists = true;
                            arrList.add(i + "-" + j);
                            numberOfBoxes.put(key, arrList);
                        }
                    } 
                }

                if (!isExists) {
                    ArrayList<String> list = new ArrayList<String>();
                    list.add(i + "-" + j);
                    numberOfBoxes.put(boxes, list);
                    boxes++;
                }
            }
        }
    }
    return numberOfBoxes;
}

/**
 * Check for the points exists in more than one area
 * @param numberOfBoxes
 * @return
 */
private  HashMap<Integer, ArrayList<String>> mergeOverlapAreas( HashMap<Integer, ArrayList<String>> numberOfBoxes) {

    for(Integer key : numberOfBoxes.keySet()) {
        ArrayList<String> list1 = numberOfBoxes.get(key);

        for (Integer key2 : numberOfBoxes.keySet()) {

            if (key < key2) {

                ArrayList<String> list2 = numberOfBoxes.get(key2);
                Iterator<String> listIter = list2.iterator();

                while(listIter.hasNext()) {

                    if (list1.contains(listIter.next())) {
                        list1.addAll(list2);
                        Set<String> noDuplicates = new HashSet<String>(list1);
                        numberOfBoxes.put(key, new ArrayList<String>(noDuplicates));
                        break;
                    }
                }
            }
        }

    }
    return numberOfBoxes;
}

}

【讨论】:

    【解决方案3】:

    这是一种替代洪水填充的算法。此方法扫描二维数组,每当遇到左侧(右、上、下)外部的节点(像素)时,它会将当前节点标记为外部,即如果您的邻居在“外部”,则您被标记'外面'也是。

    算法继续这样,直到没有更多更新。这意味着所有可以从“外部”到达的节点都已被标记。顺便说一句,这与水平集功能和更新它们非常相似(其中也使用了洪水填充)。这种方法的好处是它非常适合并行化。

    1. Load 2D Symbol Array from File 
    2. hasupdates = false
    3. Create 'isinside' bool array -> {
           if(symbolarray[row][col] == '.' and row or col is at boundary)
               isinside[row][col] = false
           else
               isinside[row][col] = true
       }
    
    4. do{
        Do a sweep from left to right (for all rows) -> //This loop can be run parallely on all rows. 
            If (!isinside[row][col-1] and symbolarray[row][col] == '.'){
                isinside[row][col] = false //mark current value as 'outside'
                hasupdates = true
            }
        Do similar sweeps from right to left, top to bottom(all columns) and bottom to top.
    
    }while(hasupdates)
    
    5. Go through 'isinside' array and count the number of falses.
    

    如果您有大量文件需要进行面积计算,您可以让沿行和列的扫描并行运行,因为每个行更新(列更新)都独立于其他更新。

    【讨论】:

    • 这不仅会找到不在所有(联合)框之外的所有内容吗?我们需要比较几个不同的边界
    • 正如所写,我认为它只是将一切标记为外部。如果您从左到右扫过并且第一个在外面,那么该扫过的每个“左邻居”都将是。
    • @Geobits。我修正了逻辑。谢谢指点。当标记为“外部”时,需要检查邻居是否在外部以及自己的值是否为“。” .
    • 这确实更有意义,但我认为 Cruncher 的评论更重要。
    • @Geobits 好的。我完全错过了“最大”的部分。将尝试查看是否可以使用“扫描”方法计算各个区域的面积。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多