Best Meeting Point 解答

Question

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:

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

Solution 1 -- Sort

根据曼哈顿距离的表达式,我们可以把这个问题转化为求每一维的最短距离。

总距离 = x上最短总距离 + y上最短总距离

并且,我们观察到,对于一个序列,如 [0,0,1,0,1,0,1,1,1,0,0,1]

当邮局选在median的位置时,距离和是最小的。

因此,这里我们遍历数组,得到home的x和y坐标值,然后分别对这两个list排序。再用双指针得到总的最短距离和。

Time complexity O(mn log(mn))

 1 public class Solution {
 2     public int minTotalDistance(int[][] grid) {
 3         if (grid == null || grid.length < 1) {
 4             return 0;
 5         }
 6         int m = grid.length, n = grid[0].length;
 7         List<Integer> xList = new ArrayList<Integer>();
 8         List<Integer> yList = new ArrayList<Integer>();
 9         for (int i = 0; i < m; i++) {
10             for (int j = 0; j < n; j++) {
11                 if (grid[i][j] == 1) {
12                     xList.add(i);
13                     yList.add(j);
14                 }
15             }
16         }
17         return calcTotalDistance(xList) + calcTotalDistance(yList);
18     }
19     
20     private int calcTotalDistance(List<Integer> list) {
21         if (list == null || list.size() < 2) {
22             return 0;
23         }
24         Collections.sort(list);
25         int len = list.size();
26         int i = 0, j = len - 1;
27         int result = 0;
28         while (i < j) {
29             int left = list.get(i);
30             int right = list.get(j);
31             result += (right - left);
32             i++;
33             j--;
34         }
35         return result;
36     }
37 }

Solution 2 -- Without sorting

Discussion里有人给出了不用排序的方法。时间复杂度降低为O(mn)

因为双层循环遍历数组本身就是有次序性的。

1. 外层循环为遍历行,内层循环为遍历该行的每一个元素。

这样得到的是排序好的x的list

2. 外层循环为遍历列,内层循环为遍历该列的每一个元素。

这样得到的是排序好的y的list

 1 public class Solution {
 2     public int minTotalDistance(int[][] grid) {
 3         if (grid == null || grid.length < 1) {
 4             return 0;
 5         }
 6         int m = grid.length, n = grid[0].length;
 7         List<Integer> xList = new ArrayList<Integer>();
 8         List<Integer> yList = new ArrayList<Integer>();
 9         for (int i = 0; i < m; i++) {
10             for (int j = 0; j < n; j++) {
11                 if (grid[i][j] == 1) {
12                     xList.add(i);
13                 }
14             }
15         }
16         for (int j = 0; j < n; j++) {
17             for (int i = 0; i < m; i++) {
18                 if (grid[i][j] == 1) {
19                     yList.add(j);
20                 }
21             }
22         }
23         
24         return calcTotalDistance(xList) + calcTotalDistance(yList);
25     }
26     
27     private int calcTotalDistance(List<Integer> list) {
28         if (list == null || list.size() < 2) {
29             return 0;
30         }
31         int len = list.size();
32         int i = 0, j = len - 1;
33         int result = 0;
34         while (i < j) {
35             result += (list.get(j--) - list.get(i++));
36         }
37         return result;
38     }
39 }

 

转载于:https://www.cnblogs.com/ireneyanglan/p/4945004.html

import randomimport multiprocessing# 定义目标函数,这里以一个简单的二维函数为例def target_func(x, y): return x ** 2 + y ** 2# 定义爬山算法,这里使用随机爬山算法def hill_climbing(start_point): current_point = start_point current_value = target_func(*current_point) while True: next_points = [(current_point[0] + random.uniform(-1, 1), current_point[1] + random.uniform(-1, 1)) for _ in range(10)] next_values = [target_func(*p) for p in next_points] next_point, next_value = min(zip(next_points, next_values), key=lambda x: x[1]) if next_value < current_value: current_point = next_point current_value = next_value else: break return current_point, current_value# 定义并行爬山函数def parallel_hill_climbing(num_workers, num_iterations, start_points): global_best_point, global_best_value = None, float('inf') pool = multiprocessing.Pool(num_workers) for i in range(num_iterations): results = pool.map(hill_climbing, start_points) best_point, best_value = min(results, key=lambda x: x[1]) if best_value < global_best_value: global_best_point, global_best_value = best_point, best_value start_points = [global_best_point] * len(start_points) return global_best_point, global_best_value# 测试代码if __name__ == '__main__': num_workers = 4 num_iterations = 10 start_points = [(random.uniform(-10, 10), random.uniform(-10, 10)) for _ in range(num_workers)] best_point, best_value = parallel_hill_climbing(num_workers, num_iterations, start_points) print(f'Best point: {best_point}, best value: {best_value}')
最新发布
05-05
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值