昆山市做网站的公司,做料理网站关键词怎么设置,加强纪检监察网站建设,韩国情侣网站模板本文涉及知识点
键值皆有序map 线段树 数学
LeetCode100240. 最小化曼哈顿距离
给你一个下标从 0 开始的数组 points #xff0c;它表示二维平面上一些点的整数坐标#xff0c;其中 points[i] [xi, yi] 。 两点之间的距离定义为它们的曼哈顿距离。 请你恰好移除一个点它表示二维平面上一些点的整数坐标其中 points[i] [xi, yi] 。 两点之间的距离定义为它们的曼哈顿距离。 请你恰好移除一个点返回移除后任意两点之间的 最大 距离可能的 最小 值。 示例 1 输入points [[3,10],[5,15],[10,2],[4,4]] 输出12 解释移除每个点后的最大距离如下所示
移除第 0 个点后最大距离在点 (5, 15) 和 (10, 2) 之间为 |5 - 10| |15 - 2| 18 。移除第 1 个点后最大距离在点 (3, 10) 和 (10, 2) 之间为 |3 - 10| |10 - 2| 15 。移除第 2 个点后最大距离在点 (5, 15) 和 (4, 4) 之间为 |5 - 4| |15 - 4| 12 。移除第 3 个点后最大距离在点 (5, 15) 和 (10, 2) 之间的为 |5 - 10| |15 - 2| 18 。 在恰好移除一个点后任意两点之间的最大距离可能的最小值是 12 。 示例 2 输入points [[1,1],[1,1],[1,1]] 输出0 解释移除任一点后任意两点之间的最大距离都是 0 。
提示 3 points.length 105 points[i].length 2 1 points[i][0], points[i][1] 108
数学
假定p1到p2的距离最大则如果不删除p1或p2最大距离一定不会变小。 我们只需要找到任意一对p1、p2分别尝试删除p1和p2的最大距离。问题就转化成求最大曼哈顿距离。 最大曼哈顿距离应该有公式和模板。但我没有。这两天在研究线段树就用线段树。结果11:59才完成编码。赛下调试了一个小时才搞定。
线段树
将points 按x排序i表示第一个点j表示第二个点。则xi xj恒成立。只需要考虑yi和yj的大小。 { x j − x i y j − y i ( x j y j ) − ( x i y i ) y i y j x j − x i y i − y j ( x j − y j ) − ( x i − y i ) y i y j \begin{cases} xj-xiyj-yi (xjyj)-(xiyi) yi yj \\ xj-xiyi-yj (xj-yj)-(xi-yi) yi yj \\ \end{cases} {xj−xiyj−yi(xjyj)−(xiyi)xj−xiyi−yj(xj−yj)−(xi−yi)yiyjyiyj 我们只需要计算 (xiyi)和(xi-yi) 的最小值。用两棵最小树分别记录最小值单点更新区间查找。难点先要离散化否则空间复杂度会超。
键值皆有序映射
情况一 yi yj (xiyi)和yj都越小越好故键yj 升序值(xiyi)降序如果冲突淘汰键大的。 情况二yi yj (xi- yi) 越小越好yj越大越好。故键yj升序值(xi- yi)升序。发生冲突淘汰键小的。
我看题解才知道的
切比雪夫距离(Chebyshev Distance) 在二维空间中,切比雪夫距离是通过计算两个点在各个坐标轴上的差值的绝对值中的最大值来衡量它。 曼哈顿距离在坐标轴旋转 45 度后与切比雪夫距离等价。
代码
线段树实现
class CDiscretize //离散化
{
public:CDiscretize(vectorint nums){sort(nums.begin(), nums.end());nums.erase(std::unique(nums.begin(), nums.end()), nums.end());m_nums nums;for (int i 0; i nums.size(); i){m_mValueToIndex[nums[i]] i;}}int operator[](const int value)const{auto it m_mValueToIndex.find(value);if (m_mValueToIndex.end() it){return -1;}return it-second;}int size()const{return m_mValueToIndex.size();}vectorint m_nums;
protected: unordered_mapint, int m_mValueToIndex;
};templateclass TSave, class TRecord
class CSingUpdateLineTree
{
public:CSingUpdateLineTree(int iEleSize, TSave tDefautl) :m_iEleSize(iEleSize), m_vSave(iEleSize * 4, tDefautl) {}void Update(int index, TRecord update) {Update(1, 1, m_iEleSize, index 1, update);}void Query(int leftIndex, int leftRight) {Query(1, 1, m_iEleSize, leftIndex 1, leftRight 1);}void Init() {Init(1, 1, m_iEleSize);}const int m_iEleSize;
protected:void Init(int iNodeNO, int iSaveLeft, int iSaveRight){if (iSaveLeft iSaveRight) {OnInit(m_vSave[iNodeNO], iSaveLeft);return;}const int mid iSaveLeft (iSaveRight - iSaveLeft) / 2;Init(iNodeNO * 2, iSaveLeft, mid);Init(iNodeNO * 2 1, mid 1, iSaveRight);OnUpdateParent(m_vSave[iNodeNO], m_vSave[iNodeNO * 2], m_vSave[iNodeNO * 2 1], iSaveLeft, iSaveRight);}void Query(int iNodeNO, int iSaveLeft, int iSaveRight, int iQueryLeft, int iQueryRight) {if ((iSaveLeft iQueryLeft) (iSaveRight iQueryRight)) {OnQuery(m_vSave[iNodeNO]);return;}if (iSaveLeft iSaveRight) {//没有子节点return;}const int mid iSaveLeft (iSaveRight - iSaveLeft) / 2;if (mid iQueryLeft) {Query(iNodeNO * 2, iSaveLeft, mid, iQueryLeft, iQueryRight);}if (mid 1 iQueryRight) {Query(iNodeNO * 2 1, mid 1, iSaveRight, iQueryLeft, iQueryRight);}}void Update(int iNodeNO, int iSaveLeft, int iSaveRight, int iUpdateNO, TRecord update) {if (iSaveLeft iSaveRight){OnUpdate(m_vSave[iNodeNO], iSaveLeft, update);return;}const int mid iSaveLeft (iSaveRight - iSaveLeft) / 2;if (iUpdateNO mid) {Update(iNodeNO * 2, iSaveLeft, mid, iUpdateNO, update);}else {Update(iNodeNO * 2 1, mid 1, iSaveRight, iUpdateNO, update);}OnUpdateParent(m_vSave[iNodeNO], m_vSave[iNodeNO * 2], m_vSave[iNodeNO * 2 1], iSaveLeft, iSaveRight);}virtual void OnInit(TSave save, int iSave) 0;virtual void OnQuery(TSave save) 0;virtual void OnUpdate(TSave save,int iSaveLeft, const TRecord update) 0;virtual void OnUpdateParent(TSave par, const TSave left, const TSave r, int iSaveLeft, int iSaveRight) 0;vectorTSave m_vSave;
};templateclass TSavepairint,int, class TRecord int
class CMyLineTree : protected CSingUpdateLineTreeTSave, TRecord
{
public:CMyLineTree(CDiscretize dis,int iEleSize) : m_dis(dis),CSingUpdateLineTreeTSave, TRecord(iEleSize,std::make_pair(1e9,-1)) {}void Update(int y, TRecord update) {CSingUpdateLineTreeTSave, TRecord::Update(m_dis[y],update);}void QueryLessEqual(int y) {m_prMin { 1e9,-1 };CSingUpdateLineTreeTSave, TRecord::Query(0, m_dis[y]);}void QueryMoreEqual(int y) {m_prMin { 1e9,-1 };CSingUpdateLineTreeTSave, TRecord::Query(m_dis[y], m_dis.size()-1);}pairint, int m_prMin { 1e9,-1 };
protected:virtual void OnInit(TSave save, int iSave) override{}virtual void OnQuery(TSave save) override{if (save m_prMin) {m_prMin save;} }virtual void OnUpdate(TSave save, int iSaveLeft,const TRecord update) override{TSave tmp { update,m_dis.m_nums[iSaveLeft - 1] };save min(save,tmp);}virtual void OnUpdateParent(TSave par, const TSave left, const TSave r, int iSaveLeft, int iSaveRight) override{par min(left, r);} CDiscretize m_dis;
};
class Solution {
public:int minimumDistance(vectorvectorint points) {sort(points.begin(), points.end(), [](const auto v1, const auto v2) {return v1[0] v2[0]; });auto [tmp, i1, i2] Max(points);auto pts1 points, pts2 points;pts1.erase(pts1.begin() i1);pts2.erase(pts2.begin() i2);auto [m1, tmp1, tmp2] Max(pts1);auto [m2, tmp3, tmp4] Max(pts2);return min(m1, m2);}std::tupleint, int, int Max(const vectorvectorint pts) {vectorint ys;for (const auto pt : pts) {ys.emplace_back(pt[1]);}CDiscretize dis(ys);CMyLineTree mXAndY(dis,dis.size()), mXSubY(dis, dis.size());const int n pts.size();int iRet -1e9,i2;std::pairint, int xy;for (int i 1; i n; i) {mXAndY.Update(pts[i - 1][1], pts[i - 1][0] pts[i - 1][1]);mXSubY.Update(pts[i - 1][1], pts[i - 1][0] - pts[i - 1][1]);mXAndY.QueryLessEqual(pts[i][1]);const int iDis1 pts[i][0] pts[i][1] - mXAndY.m_prMin.first;if (iDis1 iRet) {iRet iDis1;xy { mXAndY.m_prMin.first- mXAndY.m_prMin.second, mXAndY.m_prMin.second };i2 i;}mXSubY.QueryMoreEqual(pts[i][1]);const int iDis2 pts[i][0] - pts[i][1] - mXSubY.m_prMin.first;if (iDis2 iRet) {iRet iDis2;xy { mXSubY.m_prMin.first mXSubY.m_prMin.second, mXSubY.m_prMin.second };i2 i;}}int i1 0;for (; (xy.first ! pts[i1][0]) || (xy.second ! pts[i1][1]);i1);return { iRet,i1,i2 };}
};测试用例
templateclass T
void Assert(const T t1, const T t2)
{assert(t1 t2);
}templateclass T
void Assert(const vectorT v1, const vectorT v2)
{if (v1.size() ! v2.size()){assert(false);return;}for (int i 0; i v1.size(); i){Assert(v1[i], v2[i]);}}int main()
{vectorvectorint points;{points { {9,8},{1,8},{3,1},{9,1},{7,7},{3,6} };auto res Solution().minimumDistance(points);Assert(13, res);}{points { {3,10},{5,15},{10,2},{4,4} };auto res Solution().minimumDistance(points);Assert(12, res);}{points { {3,2},{3,9},{7,10},{4,4},{8,10},{2,7} };auto res Solution().minimumDistance(points);Assert(10, res);}{points { {1,1},{1,1},{1,1},{1,1} };auto res Solution().minimumDistance(points);Assert(0, res);}//CConsole::Out(res);
}键值皆有需map
templateclass _Kty, class _Ty, bool bValueAsc, bool bOutSmallKey
class COrderValueMap
{
public:void Add(_Kty key, _Ty value){if (bOutSmallKey){if (bValueAsc){AddOutSmall(key, value, std::less_equal_Ty(), std::greater_equal_Ty());}else{AddOutSmall(key, value, std::greater_equal_Ty(), std::less_equal_Ty());}}else{if (bValueAsc){AddNotOutSmall(key, value, std::greater_equal_Ty(), std::less_equal_Ty());}else{AddNotOutSmall(key, value, std::less_equal_Ty(), std::greater_equal_Ty());}}};std::map_Kty, _Ty m_map;
protected:templateclass _Pr1, class _Pr2void AddOutSmall(_Kty key, _Ty value, _Pr1 pr1, _Pr2 pr2){auto it m_map.lower_bound(key);if ((m_map.end() ! it) pr1(it-second, value)){return;//被旧值淘汰}auto ij it;while (it ! m_map.begin()){--it;if (pr2(it-second, value)){it m_map.erase(it);}else{break;}}m_map[key] value;}templateclass _Pr1, class _Pr2void AddNotOutSmall(_Kty key, _Ty value, _Pr1 pr1, _Pr2 pr2){auto it m_map.upper_bound(key);if ((m_map.begin() ! it) pr1(std::prev(it)-second, value)){return;//被淘汰}auto ij it;for (; (m_map.end() ! ij) pr2(ij-second, value); ij);m_map.erase(it, ij);m_map[key] value;};};class Solution {
public:int minimumDistance(vectorvectorint points) {sort(points.begin(), points.end(), [](const auto v1, const auto v2) {return v1[0] v2[0]; });auto [tmp, i1, i2] Max(points);auto pts1 points, pts2 points;pts1.erase(pts1.begin() i1);pts2.erase(pts2.begin() i2);auto [m1, tmp1, tmp2] Max(pts1);auto [m2, tmp3, tmp4] Max(pts2);return min(m1, m2);}std::tupleint, int, int Max(const vectorvectorint pts) {COrderValueMapint, int, false, false mXAndY;COrderValueMapint, int, true, true mXSubY;const int n pts.size();int iRet -1e9,i2;for (int i 1; i n; i) {mXAndY.Add(pts[i - 1][1], pts[i - 1][0] pts[i - 1][1]);mXSubY.Add(pts[i - 1][1], pts[i - 1][0] - pts[i - 1][1]);auto it1 mXAndY.m_map.upper_bound(pts[i][1]);if (mXAndY.m_map.begin() ! it1 ) {--it1;const int iDis1 pts[i][0] pts[i][1] - it1-second;if (iDis1 iRet) {iRet iDis1;i2 i;}}auto it2 mXSubY.m_map.lower_bound(pts[i][1]);if (it2 ! mXSubY.m_map.end()) {const int iDis2 pts[i][0] - pts[i][1] - it2-second;if (iDis2 iRet) {iRet iDis2;i2 i;}}}int i1 -1,iMinDis-1;for (int i 0; i n; i) {const int curDis abs(pts[i][0] - pts[i2][0]) abs(pts[i][1] - pts[i2][1]);if (curDis iMinDis) {iMinDis curDis;i1 i;}}return { iRet,i1,i2 };}
};扩展阅读
视频课程
有效学习明确的目标 及时的反馈 拉伸区难度合适可以先学简单的课程请移步CSDN学院听白银讲师也就是鄙人的讲解。 https://edu.csdn.net/course/detail/38771
如何你想快速形成战斗了为老板分忧请学习C#入职培训、C入职培训等课程 https://edu.csdn.net/lecturer/6176
相关下载
想高屋建瓴的学习算法请下载《喜缺全书算法册》doc版 https://download.csdn.net/download/he_zhidan/88348653
我想对大家说的话闻缺陷则喜是一个美好的愿望早发现问题早修改问题给老板节约钱。子墨子言之事无终始无务多业。也就是我们常说的专业的人做专业的事。如果程序是一条龙那算法就是他的是睛
测试环境
操作系统win7 开发环境 VS2019 C17 或者 操作系统win10 开发环境 VS2022 C17 如无特殊说明本算法用**C**实现。