记一道完美体现出数据结构高大尚的字节跳动算法题

偶然在公众号里看到今日头条的一道算法题(如下图),一共有三道题,要求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;

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值