【leetcode】296.Best Meeting Point

原题

A group of two or more people wants to meet and minimize the total travel distance.
You are given a 2D grid of values 0 or 1, where each 1 marks the home of someone in the group.
The distance is calculated using Manhattan Distance,
where distance(p1, p2) = |p2.x - p1.x| + |p2.y - p1.y|.

For example, given three people living at (0,0), (0,4), and (2,2):

1 - 0 - 0 - 0 - 1
| | | | |
0 - 0 - 0 - 0 - 0
| | | | |
0 - 0 - 1 - 0 - 0
The point (0,2) is an ideal meeting point, as the total travel distance of 2+2+2=6 is minimal. So return 6.

Hint:
Try to solve it in one dimension first. How can this solution apply to the two dimension case?

解析

曼哈顿距离:即一个矩阵的矩阵方格边线距离,如上例中,(0,0)-(2,2)的距离为4
该题求一个矩阵中的1位置到哪一个矩阵点的距离之和最小,并返回该距离
如上例中,三个点(0,0)(0,4)(2,2) 到(0,2)距离之和最小,为6
入参有两种表达:
一是入参为矩阵点的二维数组,每个数组值为0/1
二是入参为矩阵点的位置坐标,如上例中就是{{0,0},{0,4},{2,2}}

我的解法

没解出来,Hard难度的题真的不一样。。
我来写下我看过答案后的思路
原题的提示是将二维问题在一维先解决,再应用到二维上,意思就是先思考如何解决一条线上的点,求最短距离之和
1、一条线上有2个点
最短距离的点一定是这两个点的中点,则最短距离是两个点的直线距离
2、一条线上有3个点
最短距离是所有点到中间那个点的距离,还是最远的两个点的直线距离
3、一条线上有4个点
最短距离的点一定在最远的两个点之间,最远的两个点的距离就是固定的直线距离,那若要让中间两个点的距离最短,则最短距离点应该是中间两个点的中点,所以四个点的最短距离就是外部两点直线距离+内部两点直线距离
以此类推,一条线上的点,要求最短距离点,一定是中间两点的中点(偶数个点),或最中间的一个点(奇数个点),最短距离算法就是,最外侧两点距离+次外层两点距离+...+最内侧两点距离的和(若有中点,距离为0可以省略)

现在将问题扩展到二维,因为求的是曼哈顿距离,所以二维的最短距离也是在水平和垂直两个方向上的,所以只要求出水平的最短距离和垂直的最短距离,求和即可

最优解法

public class BestMeetingPoint {
    //以下代码以入参为矩阵二维数组来实现
    // O(MN)
    public static int minTotalDistance(int[][] grid) {
        //传入的矩阵是这样的   int[][] grid = { { 1, 0, 0, 0, 1 }, { 0, 0, 0, 0, 0 }, { 0, 0, 1, 0, 0 } };
        // means which row has the people on it
        List<Integer> row = new LinkedList();
        // means which col has the people on it
        List<Integer> col = new LinkedList();
        for (int i = 0; i < grid.length; i++) {
            for (int j = 0; j < grid[0].length; j++) {
                if (grid[i][j] == 1) {
                    row.add(i);
                    col.add(j);
                }
            }
        }
        // 分别放到一维上来做;
        return getMin(row) + getMin(col);
    }

    //一维距离算法
    private static int getMin(List<Integer> list) {
        int res = 0;
        Collections.sort(list);
        int i = 0, j = list.size() - 1;
        while (i < j) {
            res += list.get(j--) - list.get(i++);
        }
        return res;
    }
}
posted @ 2017-07-06 11:37  l.shane  阅读(400)  评论(0编辑  收藏  举报