Google Interview Question
SDETsCountry: United States
Top down dynamic programming. O(n^2 * k) time and O(n^3 * k) space.
#include <iostream>
#include <vector>
#include <unordered_map>
using namespace std;
class Path {
public:
Path()
{
distance_ = 0;
}
vector<int> cities_;
int distance_;
};
Path ShortestPath(int n, vector<vector<int>> const &distances, unordered_map<uint64_t, Path> &memo,
int k, int16_t idx = 0, int16_t prev_idx = -1)
{
if (idx < 0 ||
idx >= n)
{
return Path();
}
uint64_t memo_key = (static_cast<uint64_t>(k) << 32) | (static_cast<uint32_t>(idx) << 16) | prev_idx;
auto it = memo.find(memo_key);
if (it != memo.end()) {
return it->second;
}
Path path = ShortestPath(n, distances, memo, k, idx + 1, idx);
path.cities_.push_back(idx);
if (prev_idx != -1) {
path.distance_ += distances[prev_idx][idx];
}
if (k > 0) {
Path skip = ShortestPath(n, distances, memo, k - 1, idx + 1, prev_idx);
if (skip.distance_ < path.distance_) {
path = skip;
}
}
memo[memo_key] = path;
return path;
}
int main()
{
int n = 5;
int k = 2;
vector<vector<int>> distances(n, vector<int>(n, numeric_limits<int>::max()));
distances[0][1] = 2;
distances[0][2] = 9;
distances[0][3] = 7;
distances[0][4] = 5;
distances[1][2] = 7;
distances[1][3] = 1;
distances[1][4] = 5;
distances[2][3] = 1;
distances[2][4] = 8;
distances[3][4] = 1;
unordered_map<uint64_t, Path> memo;
Path path = ShortestPath(n, distances, memo, k);
cout << path.distance_ << ": ";
for (int i = path.cities_.size() - 1; i >= 0; --i) {
cout << path.cities_[i] << "->";
}
cout << "\n";
}
EDIT: On second thought this approach might not work in case we have the same max distance more then k times. Then there is a difference how we follow the path
- Scavi November 30, 2017