lintcode 498. Parking Lot
在职刷题 + System Design + 面试准备的路上
How to design parking system: 需要以parking lot为视角进行操作, 然后主体主要有两个,vehicle和parking spot. 如果以最简单的logic来分析, parking lot里有list of spots. 每辆车会占用一个spot, 开出去会使得一个spot available. Vehichle也可能分为car, bus, truck等,spot也可能分多种。
像这种管理类问题,如果两个对象主体之间产生操作关系,最好的易于扩展的方式是添加一个新的主体,比如receipt或ticket来处理vehicle和spot的关系,并可以记录停车时间和价格等信息。同理,记录租书, 吃饭, 预定等都适用。parking system只需要去控制ticket就可以完成对vehicle和spot的调控
https://www.cnblogs.com/grandyang/p/5656870.html
[CC150v5] 8.4 Design a Parking Lot - Shuatiblog.com
Parking lot for public or club(so maybe user type: vip etc) or malls?
there may be multiple main comments, what we should focus?
Manage park slot and help user find a slot; or payment system?
What kind of parking lot:
Whether its charged and if so how?
The ticket includes info such as enter time and parking slot?
How the slot is assigned? the customer find a slot himself or the admin at entrance assign one?
Whether there are different types of parking slot for different types of cars?
Single or multiple entrance?
then list main component and talk with the interviewer about them.
ParkingSystem - the facade, root class.
ParkingSlot
Floor(Level)
Ticket
Draw UML class digram.
Abstraction, subclasses etc.
Consider design pattern?
Singleton, composite? etc...
https://xmruibi.gitbooks.io/interview-preparation-notes/content/OOD/DesignExamples/ParkingLot.html
http://www.coderanch.com/t/628047/patterns/Parking-Lot-Design
http://javajuggler.blogspot.com/2011/01/oo-design-for-parkinglot.html
ParkingLot: this class can park or unpark and holds finite number of spaces and the spaces are held by two lists one for Parkedspaces and one for unparkedSpaces
ParkingSpace: is another class that represents the actual parking space. It needs a property to specify whether it is a compact/handicap/regular parking space
Car: is the final class that has a property of what kind of car it is and if it is parked, the slot number where it is parked.
The Car object can be further subclassed as CompactCar, HandiCapCar, RegularCar instead of the booleans. Same with the ParkingSpace as well.
Why use PriorityQueue?
http://www.jianshu.com/p/2bd60b69393d
// enum type for Vehicle
enum class VehicleSize {
Motorcycle,
Compact,
Large,
Default
};
class Vehicle {
public:
virtual VehicleSize size() {
return VehicleSize::Default;
}
};
class Bus: public Vehicle {
public:
VehicleSize size() {
return VehicleSize::Large;
}
};
class Car: public Vehicle {
public:
VehicleSize size() {
return VehicleSize::Compact;
}
};
class Motorcycle: public Vehicle {
public:
VehicleSize size() {
return VehicleSize::Motorcycle;
}
};
class Level {
private:
vector<Vehicle* > motoSpots;
vector<Vehicle* > compactSpots;
vector<Vehicle* > largeSpots;
map<Vehicle*, map<VehicleSize, int>> vehicle2spot;
public:
Level(int num_rows, int spots_per_row) {
int motoSpotSize = spots_per_row / 4;
motoSpots.resize(motoSpotSize);
int compactSpotSize = spots_per_row * 3 / 4 - motoSpotSize;
compactSpots.resize(compactSpotSize);
int largeSpotSize = spots_per_row - spots_per_row * 3 / 4 + 1;
largeSpots.resize(largeSpotSize);
}
int canParkVehicle(Vehicle* vehicle, VehicleSize size, int num) {
if (size == VehicleSize::Motorcycle) {
for(int i = 0; i < motoSpots.size(); i++) {
if (motoSpots[i] == NULL) {
return i;
}
}
return -1;
} else if (size == VehicleSize::Compact) {
for(int i = 0; i < compactSpots.size(); i++) {
if (compactSpots[i] == NULL) {
return i;
}
}
return -1;
} else {
for(int i = 0; i < largeSpots.size(); i++) {
if (largeSpots[i] == NULL) {
bool flag = true;
for(int j = i; j < i + num; j++) {
if (largeSpots[i] != NULL) {
flag = false;
break;
}
}
if (flag) {
return i;
}
}
}
return -1;
}
}
void parkVehicle(Vehicle* vehicle, VehicleSize parkSpotType, int index, int num) {
if (parkSpotType == VehicleSize::Motorcycle) {
motoSpots[index] = vehicle;
} else if (parkSpotType == VehicleSize::Compact) {
compactSpots[index] = vehicle;
} else {
for(int i = index; i < index + num; i++) {
largeSpots[i] = vehicle;
}
}
vehicle2spot[vehicle][parkSpotType] = index;
}
void unParkVehicle(Vehicle *vehicle) {
map<VehicleSize, int> spot = vehicle2spot[vehicle];
VehicleSize size = vehicle->size();
int index = spot[size];
if (size == VehicleSize::Motorcycle) {
motoSpots[index] = NULL;
} else if (size == VehicleSize::Compact) {
compactSpots[index] = NULL;
} else {
for(int i = index; i < largeSpots.size(); i++) {
if (largeSpots[i] == vehicle) {
largeSpots[i] = NULL;
} else {
break;
}
}
}
}
};
class ParkingLot {
private:
vector<Level* > levels;
map<Vehicle*, Level*> vehicle2level;
public:
// @param n number of leves
// @param num_rows each level has num_rows rows of spots
// @param spots_per_row each row has spots_per_row spots
ParkingLot(int n, int num_rows, int spots_per_row) {
for(int i = 0; i < n; i++) {
Level *level = new Level(num_rows, spots_per_row);
levels.push_back(level);
}
}
// Park the vehicle in a spot (or multiple spots)
// Return false if failed
bool parkVehicle(Vehicle &vehicle) {
VehicleSize size = vehicle.size();
if (size == VehicleSize::Motorcycle) {
cout << "Moto" << endl;
if (!parkInMotoSpot(vehicle)) {
if (!parkInCompactSpot(vehicle)) {
return parkInLargeSpot(vehicle, 1);
}
}
return true;
} else if (size == VehicleSize::Compact) {
cout << "Compact" << endl;
if (!parkInCompactSpot(vehicle)) {
return parkInLargeSpot(vehicle, 1);
}
} else if (size == VehicleSize::Large) {
cout << "Bus" << endl;
return parkInLargeSpot(vehicle, 5);
} else {
return false;
}
}
bool parkInMotoSpot(Vehicle &vehicle) {
for(int i = 0; i < levels.size(); i++) {
int index = levels[i]->canParkVehicle(&vehicle, VehicleSize::Motorcycle, 1);
if (index != -1) {
levels[i]->parkVehicle(&vehicle, VehicleSize::Motorcycle, index, 1);
vehicle2level[&vehicle] = levels[i];
return true;
}
}
return false;
}
bool parkInCompactSpot(Vehicle &vehicle) {
for(int i = 0; i < levels.size(); i++) {
int index = levels[i]->canParkVehicle(&vehicle, VehicleSize::Compact, 1);
cout << index << endl;
if (index != -1) {
levels[i]->parkVehicle(&vehicle, VehicleSize::Compact, index, 1);
vehicle2level[&vehicle] = levels[i];
return true;
}
}
return false;
}
bool parkInLargeSpot(Vehicle &vehicle, int num) {
for(int i = 0; i < levels.size(); i++) {
int index = levels[i]->canParkVehicle(&vehicle, VehicleSize::Large, num);
if (index != -1) {
levels[i]->parkVehicle(&vehicle, VehicleSize::Large, index, num);
vehicle2level[&vehicle] = levels[i];
return true;
}
}
return false;
}
// unPark the vehicle
void unParkVehicle(Vehicle &vehicle) {
Level *level = vehicle2level[&vehicle];
if (level) {
level->unParkVehicle(&vehicle);
}
}
};
http://stackoverflow.com/questions/764933/amazon-interview-question-design-an-oo-parking-lot
https://blogs.oracle.com/parijat/entry/a_parking_lot_problem
https://www.isr.umd.edu/~austin/ense623.d/projects06.d/ParkingLotProject.pdf
Read full article from [CC150v5] 8.4 Design a Parking Lot - Shuatiblog.com
在职刷题 + System Design + 面试准备的路上
How to design parking system: 需要以parking lot为视角进行操作, 然后主体主要有两个,vehicle和parking spot. 如果以最简单的logic来分析, parking lot里有list of spots. 每辆车会占用一个spot, 开出去会使得一个spot available. Vehichle也可能分为car, bus, truck等,spot也可能分多种。
像这种管理类问题,如果两个对象主体之间产生操作关系,最好的易于扩展的方式是添加一个新的主体,比如receipt或ticket来处理vehicle和spot的关系,并可以记录停车时间和价格等信息。同理,记录租书, 吃饭, 预定等都适用。parking system只需要去控制ticket就可以完成对vehicle和spot的调控
https://www.cnblogs.com/grandyang/p/5656870.html
Design a parking lot.
see CC150 OO Design for details.
1)
2) The parking lot can park motorcycles, cars and buses
3) The parking lot has motorcycle spots, compact spots, and large spots
4) Each row, motorcycle spots id is in range
5) A motorcycle can park in any spot
6) A car park in single compact spot or large spot
7) A bus can park in five large spots that are consecutive and within same row. it can not park in small spots
1)
n
levels, each level has m
rows of spots and each row has k
spots.So each level has m
x k
spots.2) The parking lot can park motorcycles, cars and buses
3) The parking lot has motorcycle spots, compact spots, and large spots
4) Each row, motorcycle spots id is in range
[0,k/4)(0 is included, k/4 is not included)
, compact spots id is in range [k/4,k/4*3)
and large spots id is in range [k/4*3,k)
.5) A motorcycle can park in any spot
6) A car park in single compact spot or large spot
7) A bus can park in five large spots that are consecutive and within same row. it can not park in small spots
Example
level=1, num_rows=1, spots_per_row=11
parkVehicle("Motorcycle_1") // return true
parkVehicle("Car_1") // return true
parkVehicle("Car_2") // return true
parkVehicle("Car_3") // return true
parkVehicle("Car_4") // return true
parkVehicle("Car_5") // return true
parkVehicle("Bus_1") // return false
unParkVehicle("Car_5")
parkVehicle("Bus_1") // return true
parkVehicle("Motorcycle_1") // return true
parkVehicle("Car_1") // return true
parkVehicle("Car_2") // return true
parkVehicle("Car_3") // return true
parkVehicle("Car_4") // return true
parkVehicle("Car_5") // return true
parkVehicle("Bus_1") // return false
unParkVehicle("Car_5")
parkVehicle("Bus_1") // return true
CareerCup上的原题,请参见我之前的博客8.4 Parking Lot 停车场问题。
LintCode的这道题的C++的OJ应该有问题,因为我的代码在本地调试都正确,不知道为何通过不了OJ,有没有大神持有同样的观点?
// enum type for Vehicle enum class VehicleSize { Motorcycle, Compact, Large }; class Vehicle { public: virtual VehicleSize size() {} virtual int spot_num() {} }; class Bus: public Vehicle { public: VehicleSize size() { return VehicleSize::Large; } int spot_num() { return 5; } }; class Car: public Vehicle { public: VehicleSize size() { return VehicleSize::Compact; } int spot_num() { return 1; } }; class Motorcycle: public Vehicle { public: VehicleSize size() { return VehicleSize::Motorcycle; } int spot_num() { return 1; } }; class Level { public: Level(int num_rows, int spots_per_row) { int moto = spots_per_row / 4; moto_spots.resize(moto); int car = spots_per_row / 4 * 3; compact_spots.resize(car - moto); large_spots.resize(spots_per_row - car); } bool park_vehicle(Vehicle* vehicle, VehicleSize size, int num) { if (size == VehicleSize::Motorcycle) { for (int i = 0; i < moto_spots.size(); ++i) { if (moto_spots[i] == NULL) { moto_spots[i] = vehicle; vehicle_to_spot[vehicle][VehicleSize::Motorcycle] = i; return true; } } return false; } else if (size == VehicleSize::Compact) { for (int i = 0; i < compact_spots.size(); ++i) { if (compact_spots[i] == NULL) { compact_spots[i] = vehicle; vehicle_to_spot[vehicle][VehicleSize::Compact] = i; return true; } } for (int i = 0; i < large_spots.size(); ++i) { if (large_spots[i] == NULL) { large_spots[i] = vehicle; vehicle_to_spot[vehicle][VehicleSize::Large] = i; return true; } } return false; } else if (size == VehicleSize::Large) { for (int i = 0; i < large_spots.size(); ++i) { if (large_spots[i] == NULL) { bool can_park = true; for (int j = i; j < i + num; ++j) { if (large_spots[j] != NULL) { can_park = false; break; } } if (can_park) { for (int j = i; j < i + num; ++j) { large_spots[j] = vehicle; } vehicle_to_spot[vehicle][VehicleSize::Large] = i; return true; } } } return false; } } void unpark_vehicle(Vehicle *vehicle) { map<VehicleSize, int> spot = vehicle_to_spot[vehicle]; VehicleSize size = vehicle->size(); if (spot.count(size)) { int idx = spot[size]; if (size == VehicleSize::Motorcycle) { moto_spots[idx] = NULL; } else if (size == VehicleSize::Compact) { compact_spots[idx] = NULL; } else { for (int i = idx; i < large_spots.size(); ++i) { if (large_spots[i] == vehicle) { large_spots[i] = NULL; } else { break; } } } } else if (size == VehicleSize::Compact && spot.count(VehicleSize::Large)) { int idx = spot[VehicleSize::Large]; large_spots[idx] = NULL; } } private: vector<Vehicle*> moto_spots; vector<Vehicle*> compact_spots; vector<Vehicle*> large_spots; map<Vehicle*, map<VehicleSize, int>> vehicle_to_spot; }; class ParkingLot { public: // @param n number of leves // @param num_rows each level has num_rows rows of spots // @param spots_per_row each row has spots_per_row spots ParkingLot(int n, int num_rows, int spots_per_row) { for (int i = 0; i < n; ++i) { Level *level = new Level(num_rows, spots_per_row); levels.push_back(level); } } // Park the vehicle in a spot (or multiple spots) // Return false if failed bool parkVehicle(Vehicle &vehicle) { for (int i = 0; i < levels.size(); ++i) { if (levels[i]->park_vehicle(&vehicle, vehicle.size(), vehicle.spot_num())) { vehicle_to_level[&vehicle] = levels[i]; return true; } } return false; } // unPark the vehicle void unParkVehicle(Vehicle &vehicle) { Level *level = vehicle_to_level[&vehicle]; if (level) { level->unpark_vehicle(&vehicle); } } private: vector<Level*> levels; map<Vehicle*, Level*> vehicle_to_level; };
[CC150v5] 8.4 Design a Parking Lot - Shuatiblog.com
- A parking lot has multiple Levels.
- A Level has multiple Parking Spot.
- A Spot can park motorcycle, car or bus, which all belongs to Vehicle.
- Vehicle.parkInSpot(Spot s)
- Vehicle.leaveSpot(Spot s)
- Vehicle.canFitIn(Spot s)
- ParkingLot.parkVehicle(Vehicle v)
- Level.parkVehicle(Vehicle v)
- Level.parkVehicleAtSpot(Vehicle v, Spot s)
- Level.findAvailableSpot(VehicleType vt)
Parking lot for public or club(so maybe user type: vip etc) or malls?
there may be multiple main comments, what we should focus?
Manage park slot and help user find a slot; or payment system?
What kind of parking lot:
Whether its charged and if so how?
The ticket includes info such as enter time and parking slot?
How the slot is assigned? the customer find a slot himself or the admin at entrance assign one?
Whether there are different types of parking slot for different types of cars?
Single or multiple entrance?
then list main component and talk with the interviewer about them.
ParkingSystem - the facade, root class.
ParkingSlot
Floor(Level)
Ticket
Draw UML class digram.
Abstraction, subclasses etc.
Consider design pattern?
Singleton, composite? etc...
https://xmruibi.gitbooks.io/interview-preparation-notes/content/OOD/DesignExamples/ParkingLot.html
- Vehicle
- size of vehicle (small, medium, large)
- status of vehicle (run or parked)
- Sedan, SUV, Bus, Truck... extends Vehicle
- Slot
- size of slot
- status (available or not)
- Lot
- hold slots in lot
Diagram
- Vehicle
public class Vehicle {
private final int size;
private final int lisense;
private boolean status;
private Lot lot;
public Vehicle(int size) {
this.size = size;
lisense = this.hashCode();
lot = Lot.getInstance();
}
public void setStatus(boolean status) {
this.status = status;
}
private Slot findSlot() {
Slot slot;
switch (this.size) {
case 1:
slot = lot.getSmallSlots().remove(0);
case 2:
slot = lot.getCompactSlots().remove(0);
case 3:
slot = lot.getLargeSlots().remove(0);
default:
slot = null;
}
return slot;
}
public void park() {
Slot slot = findSlot();
if (slot != null) {
lot.occupiedSlots.put(this.lisense, slot);
slot.occupy(this);
}
}
public void leave() {
Slot slot = lot.occupiedSlots.remove(this.lisense);
slot.release();
switch (this.size) {
case 1:
lot.getSmallSlots().add(slot);
case 2:
lot.getCompactSlots().add(slot);
case 3:
lot.getLargeSlots().add(slot);
}
}
}
public class Car extends Vehicle{
public Car(){
super(1);
}
}
public class Truck extends Vehicle{
public Truck(){
super(2);
}
}
// ... other type of vehicle
- Lot
public class Lot {
private static Lot lot = null;
private static final int NUMBER_OF_SMALL_SLOTS = 10;
private static final int NUMBER_OF_COMPACT_SLOTS = 10;
private static final int NUMBER_OF_LARGE_SLOTS = 10;
public Map<Integer, Slot> occupiedSlots;
private List<Slot> smallSlots;
private List<Slot> compactSlots;
private List<Slot> largeSlots;
private Lot() {
smallSlots = new LinkedList<>();
compactSlots = new LinkedList<>();
largeSlots = new LinkedList<>();
occupiedSlots = new HashMap<>();
for (int i = 1; i <= NUMBER_OF_SMALL_SLOTS; i++)
smallSlots.add(new Slot(i, 1));
for (int i = 1; i <= NUMBER_OF_COMPACT_SLOTS; i++)
compactSlots.add(new Slot(i, 2));
for (int i = 1; i <= NUMBER_OF_LARGE_SLOTS; i++)
largeSlots.add(new Slot(i, 3));
}
public List<Slot> getSmallSlots() {
return smallSlots;
}
public List<Slot> getCompactSlots() {
return compactSlots;
}
public List<Slot> getLargeSlots() {
return largeSlots;
}
public static Lot getInstance() {
if (lot == null)
lot = new Lot();
return lot;
}
}
- Slot
public class Slot {
private final int id;
private final int size;
private boolean available;
private Vehicle vehicle;
public Slot(int id, int size) {
this.id = id;
this.size = size;
this.available = true;
}
public void occupy(Vehicle v) {
this.vehicle = v;
this.available = false;
}
public void release() {
this.vehicle = null;
this.available = true;
}
}
http://javajuggler.blogspot.com/2011/01/oo-design-for-parkinglot.html
ParkingLot: this class can park or unpark and holds finite number of spaces and the spaces are held by two lists one for Parkedspaces and one for unparkedSpaces
ParkingSpace: is another class that represents the actual parking space. It needs a property to specify whether it is a compact/handicap/regular parking space
Car: is the final class that has a property of what kind of car it is and if it is parked, the slot number where it is parked.
The Car object can be further subclassed as CompactCar, HandiCapCar, RegularCar instead of the booleans. Same with the ParkingSpace as well.
public class ParkingLot { int totalSpaces = 100; public static List ParkingSpace parkedSpaces = new ArrayList(); public static List ParkingSpace emptySpaces = new ArrayList(); public static void park(Car car) { //Traverse though the emptySpaces list to find the //spot for specific car type //set the car object for that parkingspace //change it to park. move the object into parkedSpaces // remove it from emptySpaces } public static void unPark(int parkingSpot) { //get the parkingspot from array //set the parkingspace to available } public static boolean isEmpty() { if (emptySpaces.size() > 0) return true; return false; } public static void main(String args[]) { //build emptySpaces list. Insert 100 parking spaces //with their type properties Car car = new Car(); car.setCompact(true); if(ParkingLot.isEmpty()) ParkingLot.park(car); ParkingLot.unPark(20); } } public class ParkingSpace { boolean isCompact; boolean isRegular; boolean isHandicap; //setter and getter calls } public class Car { boolean isCompact; boolean isRegular; boolean isHandicap; int parkingSlotNumber; public Car() { } public void setParkingSlotNumber(int value) { this.parkingSlotNumber = value; } }
public class ParkingLot {
private Level[] levels;
private final int NUM_LEVELS = 5;
public ParkingLot() {
levels = new Level[NUM_LEVELS];
for (int i = 0; i < NUM_LEVELS; i++) {
levels[i] = new Level(i, 30);
}
}
/* Park the vehicle in a spot (or multiple spots). Return false if failed. */
public boolean parkVehicle(Vehicle vehicle) {
for (int i = 0; i < levels.length; i++) {
if (levels[i].parkVehicle(vehicle)) {
return true;
}
}
return false;
}
}
/* Represents a level in a parking garage */
public class Level {
private int floor;
private ParkingSpot[] spots;
private int availableSpots = 0; // number of free spots
private static final int SPOTS_PER_ROW = 10;
public Level(int flr, int numberSpots) {
floor = flr;
spots = new ParkingSpot[numberSpots];
int largeSpots = numberSpots / 4;
int bikeSpots = numberSpots / 4;
int compactSpots = numberSpots - largeSpots - bikeSpots;
for (int i = 0; i < numberSpots; i++) {
VehicleSize sz = VehicleSize.Motorcycle;
if (i < largeSpots) {
sz = VehicleSize.Large;
} else if (i < largeSpots + compactSpots) {
sz = VehicleSize.Compact;
}
int row = i / SPOTS_PER_ROW;
spots[i] = new ParkingSpot(this, row, i, sz);
}
availableSpots = numberSpots;
}
public int availableSpots() {
return availableSpots;
}
/* Try to find a place to park this vehicle. Return false if failed. */
public boolean parkVehicle(Vehicle vehicle) {
if (availableSpots() < vehicle.getSpotsNeeded()) {
return false;
}
int spotNumber = findAvailableSpots(vehicle);
if (spotNumber < 0) {
return false;
}
return parkStartingAtSpot(spotNumber, vehicle);
}
/* Park a vehicle starting at the spot spotNumber, and continuing until vehicle.spotsNeeded. */
private boolean parkStartingAtSpot(int spotNumber, Vehicle vehicle) {
vehicle.clearSpots();
boolean success = true;
for (int i = spotNumber; i < spotNumber + vehicle.spotsNeeded; i++) {
success &= spots[i].park(vehicle);
}
availableSpots -= vehicle.spotsNeeded;
return success;
}
/* find a spot to park this vehicle. Return index of spot, or -1 on failure. */
private int findAvailableSpots(Vehicle vehicle) {
int spotsNeeded = vehicle.getSpotsNeeded();
int lastRow = -1;
int spotsFound = 0;
for (int i = 0; i < spots.length; i++) {
ParkingSpot spot = spots[i];
if (lastRow != spot.getRow()) {
spotsFound = 0;
lastRow = spot.getRow();
}
if (spot.canFitVehicle(vehicle)) {
spotsFound++;
} else {
spotsFound = 0;
}
if (spotsFound == spotsNeeded) {
return i - (spotsNeeded - 1);
}
}
return -1;
}
public void print() {
int lastRow = -1;
for (int i = 0; i < spots.length; i++) {
ParkingSpot spot = spots[i];
if (spot.getRow() != lastRow) {
System.out.print(" ");
lastRow = spot.getRow();
}
spot.print();
}
}
/* When a car was removed from the spot, increment availableSpots */
public void spotFreed() {
availableSpots++;
}
}
https://hellosmallworld123.wordpress.com/2014/08/03/design-a-parking-lot/Why use PriorityQueue?
public
class
Lot {
PriorityQueue<ParkingSpace> handicapParkingSpaceQueue;
PriorityQueue<ParkingSpace> normalParkingSpaceQueue;
HashMap<Integer, ParkingSpace> occupiedSpace =
new
HashMap<Integer, ParkingSpace>();
public
Lot(
int
noHandicapParking,
int
totalNoParking) {
int
num =
0
;
handicapParkingSpaceQueue =
new
PriorityQueue<ParkingSpace>(noHandicapParking,
new
ParkingComparator());
normalParkingSpaceQueue =
new
PriorityQueue<ParkingSpace>(totalNoParking - noHandicapParking,
new
ParkingComparator());
for
(
int
i =
0
; i < noHandicapParking; i++) {
handicapParkingSpaceQueue.add(
new
HandicapParkingSpace(num++));
}
for
(
int
i = noHandicapParking; i < totalNoParking; i++) {
normalParkingSpaceQueue.add(
new
ParkingSpace(num++));
}
}
//take the first available space and park
public
boolean
park(Car c) {
if
(c.isHandicap()) {
//get the first handicap space if possible
if
(!handicapParkingSpaceQueue.isEmpty()) {
ParkingSpace takenSpace = handicapParkingSpaceQueue.remove();
occupiedSpace.put(c.getNum(), takenSpace);
takenSpace.take();
return
true
;
}
}
if
(!normalParkingSpaceQueue.isEmpty()) {
ParkingSpace takenSpace = normalParkingSpaceQueue.remove();
occupiedSpace.put(c.getNum(), takenSpace);
takenSpace.take();
return
true
;
}
return
false
;
}
//valte parking get the car for the customer
public
long
unpark(Car c) {
if
(!occupiedSpace.containsKey(c.getNum())) {
return
-
1
;
//no such car in this lot
}
ParkingSpace freeSpace = occupiedSpace.remove(c.getNum());
if
(freeSpace.type == ParkingSpace.TYPE.HANDICAP) {
handicapParkingSpaceQueue.add(freeSpace);
}
else
{
normalParkingSpaceQueue.add(freeSpace);
}
return
freeSpace.leave();
}
public
boolean
isNormalFull(){
return
normalParkingSpaceQueue.isEmpty();
}
public
boolean
isHandicapFull() {
return
handicapParkingSpaceQueue.isEmpty();
}
//comparator to sort the parking space in num
class
ParkingComparator
implements
Comparator<ParkingSpace> {
@Override
public
int
compare(ParkingSpace arg0, ParkingSpace arg1) {
if
(arg0.num < arg1.num)
return
-
1
;
else
if
(arg0.num > arg1.num){
return
1
;
}
return
0
;
}
}
Example
- n levels, each level has m rows of spots and each row has k spots.So each level has m x k spots.
- The parking lot can park motorcycles, cars and buses
- The parking lot has motorcycle spots, compact spots, and large spots
- Each row, motorcycle spots id is in range [0,k/4)(0 is included, k/4 is not included), compact spots id is in range [k/4,k3/4) and large spots id is in range [k3/4,k].
- A motorcycle can park in any spot
- A car park in single compact spot or large spot
- A bus can park in five large spots that are consecutive and within same row. it can not park in small spots
level=1, num_rows=1, spots_per_row=11 parkVehicle("Motorcycle_1") // return true parkVehicle("Car_1") // return true parkVehicle("Car_2") // return true parkVehicle("Car_3") // return true parkVehicle("Car_4") // return true parkVehicle("Car_5") // return true parkVehicle("Bus_1") // return false unParkVehicle("Car_5") parkVehicle("Bus_1") // return true
enum class VehicleSize {
Motorcycle,
Compact,
Large,
Default
};
class Vehicle {
public:
virtual VehicleSize size() {
return VehicleSize::Default;
}
};
class Bus: public Vehicle {
public:
VehicleSize size() {
return VehicleSize::Large;
}
};
class Car: public Vehicle {
public:
VehicleSize size() {
return VehicleSize::Compact;
}
};
class Motorcycle: public Vehicle {
public:
VehicleSize size() {
return VehicleSize::Motorcycle;
}
};
class Level {
private:
vector<Vehicle* > motoSpots;
vector<Vehicle* > compactSpots;
vector<Vehicle* > largeSpots;
map<Vehicle*, map<VehicleSize, int>> vehicle2spot;
public:
Level(int num_rows, int spots_per_row) {
int motoSpotSize = spots_per_row / 4;
motoSpots.resize(motoSpotSize);
int compactSpotSize = spots_per_row * 3 / 4 - motoSpotSize;
compactSpots.resize(compactSpotSize);
int largeSpotSize = spots_per_row - spots_per_row * 3 / 4 + 1;
largeSpots.resize(largeSpotSize);
}
int canParkVehicle(Vehicle* vehicle, VehicleSize size, int num) {
if (size == VehicleSize::Motorcycle) {
for(int i = 0; i < motoSpots.size(); i++) {
if (motoSpots[i] == NULL) {
return i;
}
}
return -1;
} else if (size == VehicleSize::Compact) {
for(int i = 0; i < compactSpots.size(); i++) {
if (compactSpots[i] == NULL) {
return i;
}
}
return -1;
} else {
for(int i = 0; i < largeSpots.size(); i++) {
if (largeSpots[i] == NULL) {
bool flag = true;
for(int j = i; j < i + num; j++) {
if (largeSpots[i] != NULL) {
flag = false;
break;
}
}
if (flag) {
return i;
}
}
}
return -1;
}
}
void parkVehicle(Vehicle* vehicle, VehicleSize parkSpotType, int index, int num) {
if (parkSpotType == VehicleSize::Motorcycle) {
motoSpots[index] = vehicle;
} else if (parkSpotType == VehicleSize::Compact) {
compactSpots[index] = vehicle;
} else {
for(int i = index; i < index + num; i++) {
largeSpots[i] = vehicle;
}
}
vehicle2spot[vehicle][parkSpotType] = index;
}
void unParkVehicle(Vehicle *vehicle) {
map<VehicleSize, int> spot = vehicle2spot[vehicle];
VehicleSize size = vehicle->size();
int index = spot[size];
if (size == VehicleSize::Motorcycle) {
motoSpots[index] = NULL;
} else if (size == VehicleSize::Compact) {
compactSpots[index] = NULL;
} else {
for(int i = index; i < largeSpots.size(); i++) {
if (largeSpots[i] == vehicle) {
largeSpots[i] = NULL;
} else {
break;
}
}
}
}
};
class ParkingLot {
private:
vector<Level* > levels;
map<Vehicle*, Level*> vehicle2level;
public:
// @param n number of leves
// @param num_rows each level has num_rows rows of spots
// @param spots_per_row each row has spots_per_row spots
ParkingLot(int n, int num_rows, int spots_per_row) {
for(int i = 0; i < n; i++) {
Level *level = new Level(num_rows, spots_per_row);
levels.push_back(level);
}
}
// Park the vehicle in a spot (or multiple spots)
// Return false if failed
bool parkVehicle(Vehicle &vehicle) {
VehicleSize size = vehicle.size();
if (size == VehicleSize::Motorcycle) {
cout << "Moto" << endl;
if (!parkInMotoSpot(vehicle)) {
if (!parkInCompactSpot(vehicle)) {
return parkInLargeSpot(vehicle, 1);
}
}
return true;
} else if (size == VehicleSize::Compact) {
cout << "Compact" << endl;
if (!parkInCompactSpot(vehicle)) {
return parkInLargeSpot(vehicle, 1);
}
} else if (size == VehicleSize::Large) {
cout << "Bus" << endl;
return parkInLargeSpot(vehicle, 5);
} else {
return false;
}
}
bool parkInMotoSpot(Vehicle &vehicle) {
for(int i = 0; i < levels.size(); i++) {
int index = levels[i]->canParkVehicle(&vehicle, VehicleSize::Motorcycle, 1);
if (index != -1) {
levels[i]->parkVehicle(&vehicle, VehicleSize::Motorcycle, index, 1);
vehicle2level[&vehicle] = levels[i];
return true;
}
}
return false;
}
bool parkInCompactSpot(Vehicle &vehicle) {
for(int i = 0; i < levels.size(); i++) {
int index = levels[i]->canParkVehicle(&vehicle, VehicleSize::Compact, 1);
cout << index << endl;
if (index != -1) {
levels[i]->parkVehicle(&vehicle, VehicleSize::Compact, index, 1);
vehicle2level[&vehicle] = levels[i];
return true;
}
}
return false;
}
bool parkInLargeSpot(Vehicle &vehicle, int num) {
for(int i = 0; i < levels.size(); i++) {
int index = levels[i]->canParkVehicle(&vehicle, VehicleSize::Large, num);
if (index != -1) {
levels[i]->parkVehicle(&vehicle, VehicleSize::Large, index, num);
vehicle2level[&vehicle] = levels[i];
return true;
}
}
return false;
}
// unPark the vehicle
void unParkVehicle(Vehicle &vehicle) {
Level *level = vehicle2level[&vehicle];
if (level) {
level->unParkVehicle(&vehicle);
}
}
};
http://stackoverflow.com/questions/764933/amazon-interview-question-design-an-oo-parking-lot
https://blogs.oracle.com/parijat/entry/a_parking_lot_problem
https://www.isr.umd.edu/~austin/ense623.d/projects06.d/ParkingLotProject.pdf
Read full article from [CC150v5] 8.4 Design a Parking Lot - Shuatiblog.com