偶然在公众号里看到今日头条的一道算法题(如下图),一共有三道题,要求40分钟内做完其中的两道(听说头条的面试一般都比较变态)。
在网上找了找答案感觉都比较繁琐,自己当时也就没当回事就不准备做了。过了半个小时突然灵机一动,想到一种非常清晰的思路来做这道题—用环形链表来做。第一次遍历构建环形链表,并且算出周长。第二次遍历根据当前节点与下一个节点的距离来计算等分点的位置,同时将等分点作为新节点插入环形链表中。整体思路大概就是这样,这样只需两次遍历,时间复杂度O(N)搞定。在这种环形链表的思路下做这道题差不多20分钟就能做完。
一点感悟:1.做这种算法题一定要先有个大概想法和思路再做,花点时间理清思路比上来就闷头一股脑的瞎做强多了。2.一道现实中的数学算法题,用上简简单单的环形链表这种数据结构就能思路非常清晰,可见数据结构的高大尚!
附上代码,写的有点乱,如有不对,欢迎拍砖。
#define precision 10e-6
struct Node {
float x;
float y;
Node* next;
Node(float a,float b):x(a),y(b),next(nullptr){}
};
Node* Construct_Circle(vector<vector<float>> Points,float& c_meter) { /*根据输入构建环形链表,并计算周长*/
Node dummy(0.0,0.0);
Node* tail = &dummy;
for (int i = 0; i < Points.size(); ++i) {
Node* node = new Node(Points[i][0],Points[i][1]);
tail->next = node;
tail = tail->next;
if (i == 0)
c_meter += (fabs(Points[i][0] - Points.back()[0])\
+ fabs(Points[i][1] - Points.back()[1]));
else
c_meter += (fabs(Points[i][0] - Points[i - 1][0])\
+ fabs(Points[i][1] - Points[i - 1][1]));
}
tail->next = dummy.next;
return dummy.next;
}
float dist_between_Node(Node* node1,Node* node2) { /*计算当前节点与下一个节点之间的距离*/
return fabs(node1->x - node2->x) + fabs(node1->y - node2->y);
}
vector<vector<float>> get_Ksplit(const vector<vector<float>> Points,const int k) { /*求等分点主程序*/
if (Points.size() < 4 || k < 1)
return {{}};
vector<vector<float>> ans{{Points[0][0],Points[0][1]}};
float C_meter= 0;
Node* head = Construct_Circle(Points,C_meter);
float split_len = C_meter / k;
for (int i = 0; i < k ; ++i) {
if (dist_between_Node(head,head->next) - split_len > precision) {
Node* new_node = (fabs(head->x - head->next->x) < precision) ?\
new Node(head->x, head->y + (head->y - head->next->y < precision ? 1.0 : -1.0)*split_len)\
: new Node(head->x + (head->x - head->next->x < precision ? 1.0 : -1.0)*split_len, head->y);
new_node->next = head->next;
head->next = new_node;
ans.push_back({new_node->x,new_node->y});
head = head->next;
} else if (dist_between_Node(head,head->next) - split_len < -1.0 * precision) {
float len = split_len;
while (dist_between_Node(head,head->next) - len < -1.0 * precision) {
len -= dist_between_Node(head,head->next);
head = head->next;
}
if (dist_between_Node(head,head->next) - len > precision) {
Node* new_node = (fabs(head->x - head->next->x) < precision) ?\
new Node(head->x, head->y + (head->y - head->next->y < precision ? 1.0 : -1.0) * len)\
: new Node(head->x + (head->x - head->next->x < precision ? 1.0 : -1.0) * len, head->y);
new_node->next = head->next;
head->next = new_node;
ans.push_back({new_node->x,new_node->y});
head = head->next;
} else {
head = head->next;
ans.push_back({head->x,head->y});
}
} else {
head = head->next;
ans.push_back({head->x,head->y});
}
}
return ans;
}