不确定是否相关,但是我要解决的问题是
~~~~~~~~~~~~~与所有建筑物的最短距离~~~~~~~~~~~~~~~~
您要在空旷的土地上盖房子,该土地应以最短的距离到达所有建筑物。您只能上下左右移动。您将获得一个二维网格,其值为0、1或2,其中:
每个0标记一个空地,您可以自由通过。 每个1代表您无法通过的建筑物。 每2个标志都是您无法通过的障碍。
找到可以进入所有建筑物的空地的最小距离 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~
尽管我的解决方案可以在小输入上正常工作,但由于时间复杂度高,对于较大的输入却会超时。
但是我不确定该解决方案的确切时间复杂度,并想正确理解该解决方案的时间复杂度是什么,以便在可能的情况下尝试改善它。
我非常确定外部循环的时间复杂度是O(MN)(M是总行数,N是总行数),因为我们正在遍历网格的所有位置,但是我我不确定递归shortDist方法的时间复杂度。是否也是O(MN),因为在最坏的情况下它将接触网格的每个位置,因此此解决方案的总时间复杂度将为O(M ^ 2 * N ^ 2)或其他(如果是)如果有人可以向我解释一下,那就太好了。
我的解决方法是
class Solution {
public:
int shortestDistance(vector<vector<int>>& grid) {
vector<std::pair<int,int>> dir = {{-1,0}, {1,0}, {0,-1}, {0,1}};
// pair(row, col) -> distance
map<std::pair<int,int>, int> cache;
vector<vector<bool>> visited(grid.size(), vector<bool>(grid[0].size(), false)); // to check if we have already visited that location on the grid
int minDist = INT_MAX;
int maxCount =0;
// Finding number of 1's
for(int i =0; i< grid.size(); i++)
{
for(int y =0; y < grid[0].size(); y++)
{
if(grid[i][y] == 1)
{
maxCount++;
}
}
}
// For each 0 find the distance of each 1's and their count
// if the count of 1's is less than the number of 1's in the
// grid that grid position is not an acceptable pos
for(int i =0; i< grid.size(); i++)
{
for(int y =0; y < grid[0].size(); y++)
{
if(grid[i][y] == 0)
{
shortDist(grid, cache, dir, visited, i, y, 0);
int dist =0;
int count = cache.size();// number of 1's
if(count == maxCount)
{
// if we are here it implies that the empty land space have path to all the buildings
for(auto iter = cache.begin(); iter != cache.end(); iter++)
{
dist += iter->second;
}
if(dist < minDist)
{
minDist = dist;
}
}
cache.clear();
}
}
}
return minDist == INT_MAX ? -1 : minDist;
}
void shortDist(vector<vector<int>>& grid, map<std::pair<int,int>, int>& cache, vector<std::pair<int,int>>& dir, vector<vector<bool>>& visited, int row, int col, int dist)
{
if(row < 0 || col < 0 || row >= grid.size() || col >= grid[0].size())
{
return;
}
if(grid[row][col] == 2)
{
return;
}
if(grid[row][col] == 1)
{
auto found = cache.find(make_pair(row, col));
if(found == cache.end())
{
cache[(make_pair(row, col))] = dist;
}
else
{
found->second = min(found->second, dist);
}
return;
}
if(visited[row][col])
{
return;
}
visited[row][col] = true;
for(int i =0; i < dir.size(); i++)
{
int newRow = row + dir[i].first;
int newCol = col + dir[i].second;
shortDist(grid, cache, dir, visited, newRow, newCol, dist+1);
}
visited[row][col] = false;
}
};
答案 0 :(得分:1)
据我所知shortDist
是主要贡献者。
函数shortDist
的{{1}}具有O(log(MN)),因为缓存可以最大包含行* cols项,(使用find
,使用{{1} }只有O(1)(如果您有完善的哈希函数)。然后您递归得出D = max(M,N)的距离,实际上,您访问了每个MN点。对于来自std::map
的每个呼叫总计O(MN log(MN))。
在std::unordered_map
中,网格上的第二个循环的前两个循环具有O(MN),然后在高速缓存中具有O(MN),给出O(M ^ 2 * N ^ 2),调用shortDist是O(M ^ 2N ^ 2 log(MN))。
如果您使用另一个MN数组直接查找值,则可以保存log(MN)。
实施优化。
您对shortDist的调用包含太多参数。
shortestDistance
向量应该是constexpr std :: array,因为它永远不会改变,并且会在所有搜索中使用。
shortestDistance
和dir
应该是该类的成员,对于每个调用,shortestDistance都会重置,如果不是的话,Solution实例仅使用一次。
使用网格拖动作为参数似乎也很浪费,因为您需要执行几次。将其设置为类引用或副本即可解决此问题。
然后Cache
仅具有合理的3个参数。
通过使网格成为一维并计算自己的索引,可以将visited
中的每个x,y查找从两次访问减少到一次,可以节省很多性能损失。