今天朋友问了我一道leetcode第296题,于是我将自己对题目的拙见写了下来。
(提前说明,暴力破解方法比较简单粗暴,时间和内存会消耗很大,如果需要更快更省的办法去解决这个问题的话,建议不用看这篇随笔了!)
题目分析:
由题可知:1. 输入的数据是一个由0和1 组成的二维数组
2.(一队人)两人或以上 --------> 说明值为1 的数据至少有两个
3.提供了一个公式 曼哈顿公式 ------->这大大降低了题目难度。
根据题目析提供的输入和输出,假设碰面点 为P点(0,2) ,三个人的点分别是A(0,0) B(0,4) C(2,2) 三个点,根据曼哈顿公式
AP距离 = |0-0|+|2-0|=2 BP距离 = |0-0|+|2-4|=2 CP距离 = |0-2|+|2-2|=2
总的行走距离就为 distase = AP+BP+CP=2+2+2=6
题目难点:
1.如何确定最佳碰面点 ?
答:由于万物皆可暴力,先标记值为1的点, 然后对二维数组的每一个的位置,进行距离运算 ,统计最小的值
(我最初的想法是对值为0的位置运算,但测试数据告诉我,如果一个人不走,也有可能最小距离。 例 [{1,0,1,0,1}] 结果是4)
2.初始的人数无法确定
答:创建两个int数组,一个是每个人的x 坐标 ,一个是每个人的y坐标,进行距离运算的时候,只需遍历数组即可。
数据结构分析:
由于输入的数据长度 无法确定 ----> 优先考虑使用 list 集合 存储
由于 一个人代表的是一个坐标 有两个属性(x,y) -----> 考虑创建一个point 对象 存储到集合里
1 public class point { 2 public int x; 3 public int y; 4 //构造方法 5 public point(int x, int y) { 6 this.x = x; 7 this.y = y; 8 } 9 }
解题思路:
1.声明两个集合,list1用来存储值为1的点 list2用来存储所有位置的点
List<point> list1 = new ArrayList<point>(); List<point> list2 = new ArrayList<point>();
2.遍历数据,将数值放入对应集合
for(int i=0;i<arr.length;i++) { for(int j=0;j<arr[i].length;j++) { list2.add(new point(i,j)); //每个位置放到List2 if(arr[i][j]==1) { list1.add(new point(i,j)); //值为1的点放入List1 } } }
3,创建两个数组,分别代表每个人的 x位置数组 和y位置数组。并利用list1 集合给数组添加值
1 int x[] =new int[list1.size()]; //每个人的x位置 2 int y[] =new int[list1.size()]; //每个人都y位置 3 4 for(int i=0;i<x.length;i++) { 5 x[i]=list1.get(i).x; //获取list1第i个点的x 6 y[i]=list1.get(i).y;//获取list1第i个点的y 7 }
4.对每个点(list2的点)进行距离运算,并将所有结果放到一个mindis数组中
int mindis[] = new int[list2.size()]; for(int i=0;i<list2.size();i++) { int xvalue= list2.get(i).x; //每一个对应的点的x int yvalue= list2.get(i).y; //每一个对应的点的y int nums=0; //利用曼哈顿公式进行运算 ,并放入mindis数组中。 for(int j=0;j<list1.size();j++) { int num=Math.abs(x[j]-xvalue)+Math.abs(y[j]-yvalue); nums+=num; } mindis[i]=nums; }
5.对mindis数组进行排序,输入第一个值就,因为第一个值就是是最小的距离。
1 Arrays.parallelSort(mindis); 2 System.out.println("最小距离为:"+mindis[0]);
代码总结:
import java.util.ArrayList; import java.util.Arrays; import java.util.List; class point { public int x; public int y; //构造方法 public point(int x, int y) { this.x = x; this.y = y; } } public class leetcode296 { public static void main(String[] args) { //测试数据 int grid[][]={ //数据1 // {1,1} //数据2 // {1,0,1} //数据3 // {1,0,1,0,1} //数据4 {1,0,0,0,1}, {0,0,0,0,0}, {0,0,1,0,0} }; System.out.println(minTotalDistance(grid)); } public static int minTotalDistance(int[][]grid) { // 1.声明两个集合,list1用来存储值为1的点 list2用来存储所有位置的点 List<point> list1 = new ArrayList<point>(); List<point> list2 = new ArrayList<point>(); //2.遍历数据,将数值放入对应集合 for(int i=0;i<grid.length;i++) { for(int j=0;j<grid[i].length;j++) { list2.add(new point(i,j)); //每个位置放到List2 if(grid[i][j]==1) { list1.add(new point(i,j)); //值为1的点放入List1 } } } //3.创建两个数组,分别代表每个人的 x位置数组 和y位置数组。并利用list1 集合给数组添加值 int x[] =new int[list1.size()]; //每个人的x位置 int y[] =new int[list1.size()]; //每个人都y位置 for(int i=0;i<x.length;i++) { x[i]=list1.get(i).x; //获取list1第i个点的x y[i]=list1.get(i).y;//获取list1第i个点的y } //4.对每个点(list2的点)进行距离运算,并将所有结果放到一个mindis数组中 int mindis[] = new int[list2.size()]; for(int i=0;i<list2.size();i++) { int xvalue= list2.get(i).x; //每一个对应的点的x int yvalue= list2.get(i).y; //每一个对应的点的y int nums=0; //利用曼哈顿公式进行运算 ,并放入mindis数组中。 for(int j=0;j<list1.size();j++) { int num=Math.abs(x[j]-xvalue)+Math.abs(y[j]-yvalue); nums+=num; } mindis[i]=nums; } //5.对mindis数组进行排序,输入第一个值就,因为第一个值就是是最小的距离。 Arrays.parallelSort(mindis); return mindis[0]; } }
结果截图:
(侧面反映暴力法真的不太好,本题解仅提供一个解决的思路,并不是最优解! )