Skip to content

Commit bb56efa

Browse files
authored
Add files via upload
1 parent 89e4514 commit bb56efa

File tree

1 file changed

+301
-0
lines changed

1 file changed

+301
-0
lines changed

AlgoQuestion.java

Lines changed: 301 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,301 @@
1+
package com.mycompany;
2+
3+
/*
4+
Algo question:
5+
N people, M restaurants, on a one-dimensional street. All the people are to meet at one restaurant,
6+
find the restaurant, where total travel distance from all people to that restaurant is the shortest among all restaurants.
7+
8+
The problem can be solved with brutal force with O(n*m) complexity. Question is how to solve it faster than brutal force.
9+
Describe the algorithm, and why it is better than brutal force. Coding is not required
10+
11+
[zc] this is one dimensional street.
12+
13+
A list of people can be represented with their coordinates (p1, p2, ... pn).
14+
15+
A list of restaurant can be represented with their coordinates (r1, r2, ... rm)
16+
17+
The distance between i-th people and j-th restaurant can be calculated as ABS(pi - rj)
18+
19+
Time Complexity of BruteForce Algorithm 1: O(M * N)
20+
21+
Time Complexity of Proposed Algorithm 2 : O(M+N)
22+
This Algorithm tries to compute the distance in two passes of the Combined Sorted List
23+
Once from Left to Right and Another time from Right to Left
24+
Time Complexity of the Algorithm :
25+
O(M+N) : counting sort
26+
O(M+N) : Left to Right Traversal
27+
O(M+N) : Right to Left Traversal
28+
O(M) : traversal over the restautart list to find the minimal cost
29+
Overall Complexity = O(3 * (M+N) + M), removing constant multiplier and lower order terms it is O(M+N)
30+
31+
Space Complexity : Needs O(M+N) extra storage for the combine list and O(M) addtional space to store
32+
two lists of Restaurant objects for Left to Right and Right to Left Traversal respectively.
33+
34+
*/
35+
36+
import java.util.*;
37+
38+
public class AlgoQuestion {
39+
40+
public static void main(String[] args) {
41+
42+
int[] people = new int[]{1,2,4,6,7};
43+
int[] restaurants = new int[]{1,3,5};
44+
int restaurantWithShortedDist = getShortestDistanceBruteForce(people, restaurants);
45+
System.out.println("Nearest Restaurant for all people is: " + (restaurantWithShortedDist));
46+
47+
restaurantWithShortedDist = getShortestTotalDistanceOptimal(people, restaurants);
48+
System.out.println("Nearest Restaurant for all people is: " + (restaurantWithShortedDist));
49+
50+
people = new int[]{3,4,2,5,9};
51+
restaurants = new int[]{4,6,7};
52+
restaurantWithShortedDist = getShortestDistanceBruteForce(people, restaurants);
53+
System.out.println("Nearest Restaurant for all people is: " + (restaurantWithShortedDist));
54+
55+
restaurantWithShortedDist = getShortestTotalDistanceOptimal(people, restaurants);
56+
System.out.println("Nearest Restaurant for all people is: " + (restaurantWithShortedDist));
57+
58+
people = new int[]{2,6,8,10,11};
59+
restaurants = new int[]{7,9};
60+
restaurantWithShortedDist = getShortestDistanceBruteForce(people, restaurants);
61+
System.out.println("Nearest Restaurant for all people is: " + (restaurantWithShortedDist));
62+
63+
restaurantWithShortedDist = getShortestTotalDistanceOptimal(people, restaurants);
64+
System.out.println("Nearest Restaurant for all people is: " + (restaurantWithShortedDist));
65+
66+
}
67+
68+
public static int getShortestDistanceBruteForce(int[] people, int[] restaurants) {
69+
int resultRestaurant= -1;
70+
int globalMin = Integer.MAX_VALUE;
71+
int totalOperations = 0;
72+
for (int r=0; r < restaurants.length; r++) {
73+
int currentRSum = 0;
74+
for (int p=0; p < people.length; p++) {
75+
currentRSum += Math.abs(people[p] - restaurants[r]);
76+
totalOperations++;
77+
if (currentRSum > globalMin) {
78+
break;
79+
}
80+
}
81+
if (currentRSum < globalMin) {
82+
globalMin = currentRSum;
83+
resultRestaurant = r;
84+
}
85+
}
86+
System.out.println("Minimum Distance for all people: " + globalMin);
87+
return resultRestaurant;
88+
}
89+
90+
public static class Triple {
91+
//distance
92+
int d;
93+
//r == true indicates restaurant
94+
//otherwise person
95+
boolean r;
96+
int index;
97+
98+
public Triple(Integer d, Integer indx, boolean r) {
99+
this.d = d;
100+
this.r = r;
101+
this.index = indx;
102+
}
103+
public int getDistance() {
104+
return d;
105+
}
106+
}
107+
108+
public static class Restaurant {
109+
int currentCost;
110+
int cumCost;
111+
int cumPeopleCount;
112+
int peopleCount;
113+
int currentCostRight;
114+
115+
Triple r;
116+
117+
public Restaurant(Triple r) {
118+
this.r = r;
119+
}
120+
121+
//assumes setCostAndCount method already called.
122+
public void setCumCost(Restaurant prev) {
123+
//if prev is null, it means i am the first restaurant in the list
124+
if(prev == null) {
125+
cumCost = 0;
126+
cumPeopleCount = peopleCount;
127+
return;
128+
}
129+
cumCost = prev.cumCost+ prev.currentCost + Math.abs(r.d - prev.r.d) * prev.cumPeopleCount;
130+
cumPeopleCount = peopleCount + prev.cumPeopleCount;
131+
}
132+
133+
public void setCostAndCount(int c, int count) {
134+
currentCost = c;
135+
peopleCount = count;
136+
}
137+
138+
public void updateCostAndCount(int costUpdate, int countUpdate) {
139+
currentCost += costUpdate;
140+
peopleCount += countUpdate;
141+
currentCostRight = costUpdate;
142+
}
143+
}
144+
145+
//Linear implementation.
146+
public static int getShortestTotalDistanceOptimal(int[] people, int[] restaurants) {
147+
148+
int[] restaurantDistance = new int[restaurants.length];
149+
List<Restaurant> restaurantsListLR = new ArrayList<>();
150+
List<Restaurant> restaurantsListRL = new ArrayList<>();
151+
List<Triple> combined = new ArrayList<>();
152+
for (int i=0; i< people.length; i++) {
153+
combined.add(new Triple(people[i], i, false));
154+
}
155+
for (int i=0; i< restaurants.length; i++) {
156+
Triple t = new Triple(restaurants[i], i, true);
157+
combined.add(t);
158+
restaurantsListLR.add(new Restaurant(t));
159+
restaurantsListRL.add(new Restaurant(t));
160+
}
161+
162+
//TODO: do a Counting sort for people with restaurants
163+
//based on the distance from origin.
164+
//This will be O(M+N) when changed to Counting Sort
165+
combined.sort(Comparator.comparing(Triple::getDistance));
166+
167+
int runningCost = 0;
168+
int runningCount = 0;
169+
170+
Restaurant prev = null;
171+
Restaurant current = null;
172+
for (int i=0; i < combined.size(); i++) {
173+
Triple t = combined.get(i);
174+
if (t.r) {
175+
//restaurant handling
176+
current = restaurantsListLR.get(t.index);
177+
current.setCostAndCount(Math.abs((runningCount * t.d) - runningCost), runningCount);
178+
runningCost = 0;
179+
runningCount = 0;
180+
current.setCumCost(prev);
181+
prev = current;
182+
183+
} else {
184+
//people handling
185+
runningCost += t.d;
186+
runningCount++;
187+
}
188+
}
189+
190+
//if at the end of this loop we have runningCost it needs to be attributed
191+
//to current restaurant
192+
if (runningCount > 0) {
193+
current.updateCostAndCount(Math.abs((runningCount * current.r.d) - runningCost), runningCount);
194+
}
195+
196+
runningCost = 0;
197+
runningCount = 0;
198+
prev = null;
199+
current = null;
200+
201+
for (int i= combined.size() -1; i >=0; i--) {
202+
Triple t = combined.get(i);
203+
if (t.r) {
204+
//restaurant handling
205+
current = restaurantsListRL.get(t.index);
206+
current.setCostAndCount(Math.abs((runningCount * t.d) - runningCost), runningCount);
207+
runningCost = 0;
208+
runningCount = 0;
209+
current.setCumCost(prev);
210+
prev = current;
211+
212+
} else {
213+
//people handling
214+
runningCost += t.d;
215+
runningCount++;
216+
}
217+
}
218+
219+
//if at the end of this loop we have runningCost it needs to be attributed
220+
//to current restaurant
221+
if (runningCount > 0) {
222+
current.updateCostAndCount(Math.abs((runningCount * current.r.d) - runningCost), runningCount);
223+
}
224+
225+
int minCost = Integer.MAX_VALUE;
226+
int minIndex = -1;
227+
for (int i=0; i < restaurantsListLR.size(); i++) {
228+
Restaurant rL = restaurantsListLR.get(i);
229+
Restaurant rR = restaurantsListRL.get(i);
230+
int totalCost = 0;
231+
if (i==0) {
232+
totalCost = rL.currentCost + rR.cumCost + (rR.currentCost - rR.currentCostRight);
233+
} else if (i==restaurantsListLR.size() -1) {
234+
totalCost = (rL.currentCost - rL.currentCostRight) + rL.cumCost + rR.currentCost;
235+
} else {
236+
totalCost = rL.currentCost + rR.currentCost + rL.cumCost + rR.cumCost;
237+
}
238+
if (totalCost < minCost) {
239+
minCost = totalCost;
240+
minIndex = i;
241+
}
242+
//System.out.println("Total Cost at Restaurant:" + i + "=" + totalCost);
243+
}
244+
245+
System.out.println("Minimum Distance for all people: " + minCost);
246+
return minIndex;
247+
}
248+
249+
//Assumption the Street is of fixed length so we can apply Counting Sort
250+
//for the combined list of People and Restaurants
251+
public static int getShortestTotalDistance(int[] people, int[] restaurants) {
252+
253+
int[] restaurantDistance = new int[restaurants.length];
254+
List<Triple> combined = new ArrayList<>();
255+
for (int i=0; i< people.length; i++) {
256+
combined.add(new Triple(people[i], i, false));
257+
}
258+
for (int i=0; i< restaurants.length; i++) {
259+
combined.add(new Triple(restaurants[i], i, true));
260+
}
261+
262+
//TODO: do a Counting sort for people with restaurants
263+
//based on the distance from origin.
264+
//This will be O(M+N) when changed to Counting Sort
265+
combined.sort(Comparator.comparing(Triple::getDistance));
266+
267+
//This loop is O(M+N)
268+
int personSumTillNow = 0;
269+
int personCountTillNow = 0;
270+
int restaurantSeenTillNow = -1;
271+
272+
for (int i=0; i < combined.size(); i++) {
273+
Triple t = combined.get(i);
274+
if (t.r) {
275+
//restaurant handling
276+
restaurantDistance[t.index] = Math.abs(personCountTillNow * t.d - personSumTillNow);
277+
restaurantSeenTillNow = t.index;
278+
} else {
279+
//people handling
280+
personSumTillNow += t.d;
281+
personCountTillNow += 1;
282+
//update only restaurants seen till now
283+
for (int j=restaurantSeenTillNow; j >=0; j--) {
284+
restaurantDistance[j] += (Math.abs(t.d - restaurants[j]));
285+
}
286+
}
287+
}
288+
289+
int resultRestaurant= -1;
290+
int globalMin = Integer.MAX_VALUE;
291+
for (int i=0; i < restaurantDistance.length; i++) {
292+
if (restaurantDistance[i] < globalMin) {
293+
globalMin = restaurantDistance[i];
294+
resultRestaurant = i;
295+
}
296+
}
297+
System.out.println("Minimum Distance for all people: " + globalMin);
298+
return resultRestaurant;
299+
}
300+
301+
}

0 commit comments

Comments
 (0)