【计划执行报告】Day10 04-09 线性代数知识补充日|单链表设计

Day10 04-09 线性代数知识补充日|单链表设计

今天:

  1. 计划执行的第10
  2. 离蓝桥杯模拟赛还有9

1. 今日动态

  1. 《机器学习中的数学》完成了线性代数部分(向量、矩阵、距离),不过仍然存在疑惑(行列式部分性质的证明、矩阵的LU分解的意义、下三角矩阵的什么性质让其矩阵的求逆变简单了),还有很多线代中的概念书中没提,证明也涉及得少,需要自己去其它地方找资源补充。
  2. 《游戏引擎原理与实践 基础框架》完成了第1、2章的阅读,第2章的习题有两题没做;说实话这本书有点劝退,不过游戏引擎设计本身就是一个综合且高级的内容,需要具备扎实的线性代数、高等数学、概率统计等数学基础、图形学基础、数据结构基础、图形接口编程基础(OpenGL或DirectX)、过硬的C/C++编程能力以及引擎使用经历(Unity或Unreal Engine)等等。(我真的要哭了)
    至少前2章就有一些需要深入了解的概念:①正交矩阵;②四元数;③欧拉角;④线性变换以及仿射变换;
    剩余的习题:
    Q1:3D流水线中,与相机近平面相交的三角形为什么要切割?如果三角形和远平面相交呢?如果三角形和相机上下左右的面相交呢?
    Q2:尝试用Unity3D做一个小游戏,体验书中所说的引擎工作流。
  3. 今天中午先是把单链表有关的知识与面试题看完了,操作感觉很简单,但是在Leetcode上实现时才发现困难重重,遇到了各种错误,大部分时间就是在“揪出内鬼”,通过改变输入来确定到底是哪个函数算计我,充分展现了我的”五毛钱“调试技术,整个解题用时3个多小时,最终总结出如下教训:
    • 指针变量使用前一定要置空!置空!置空!否则就是个野指针,对于”是否为空指针“的判断就会失效;
    • 当出现p->next这种写法时,一定确保p是非空的;
    • 使用指针p指向链表头结点时,当且仅当作移动p本身的操作时赋值符号的左边为p,其余情况赋值符号的左边均为p->next以及p->next->next之类的操作,像p=head,p->next=q;就不等价于p=head,head->next=q;,这是本次犯的最致命的错误!!

2. 计划执行报告

2.1 近期计划(03-31-04-12)(更新)

  1. 《机器学习中的数学》高等数学篇
    2.完成专业课的作业(流体机械能转化、生物质能,新能源热利用可以往后稍稍);
    3.备战蓝桥杯,为此:①利用中午1h左右的时间补充数据结构知识(优先Leetcode“探索”模块);②C/C++语法知识;③常见数据结构的构造与基本操作实现;④必要的练习与练题总结(比如时长1:30虚拟竞赛与“覆盘”)

2.2 今日计划表

04-09

2.3实际时间分配

  1. 今天的单链表设计用的时间有点多,尽管也收获了不少;
图1 时间分配
图2 目标达成情况

3. 《ML中的数学》前三章复习指引

下面简单梳理一下重点内容

Chapter1 向量和它的朋友们

  1. 向量的内积、叉积的作用与意义
  2. 行列式的性质证明与意义

Chapter2 矩阵的威力

  1. 逆矩阵的求法
  2. 消元矩阵与置换矩阵的概念
  3. 矩阵的LU分解步骤、前提与意义

Chapter3 距离

  1. 距离的度量:欧式距离、曼哈顿距离、切比雪夫距离以及夹角余弦;
  2. “人心的距离”一节中对于数据的预处理以及距离度量的选取依据;

4. Leetcode探索:设计(单)链表

设计链表的过程中吃了不少苦头(各种方面)。在“今日动态”中我已经总结出了一些经验&教训,这里仅仅把实现的代码作个记录。

class MyLinkedList {
public:
    int val;
    MyLinkedList* next;
    MyLinkedList* head;
    /** Initialize your data structure here. */
    MyLinkedList():head(NULL){//head=NULL不可少,否则就是野指针,判断if(head)会成立
        //cout<<head<<endl;
    }
    MyLinkedList* init_node(int val){//结点初始化
        MyLinkedList* p=(MyLinkedList*)malloc(sizeof(MyLinkedList));
        p->val=val;
        p->next=NULL;
        return p;
    }
    
    /** Get the value of the index-th node in the linked list. If the index is invalid, return -1. */
    int get(int index) {
        int i=0;
        MyLinkedList* p=head;
        //cout<<p->val<<endl;
        while(i<index&&p){
            p=p->next;
            i++;
        }
        if(i==index&&p)
            return p->val;
        else
            return -1;
    }
    
    /** Add a node of value val before the first element of the linked list. After the insertion, the new node will be the first node of the linked list. */
    void addAtHead(int val) {
        MyLinkedList* q=init_node(val);
        q->next=head; 
        head=q;      
    }
    
    /** Append a node of value val to the last element of the linked list. */
    void addAtTail(int val) {
        MyLinkedList* q=init_node(val);
        //cout<<q->val<<endl;
        MyLinkedList* p=head;
        if(!p){//空表
            //p=q; //链表中切忌直接赋值,这样会直接使p指向其它地址而丢失了原本的链表
            head=q;
            return;
        }
        /*  致命错误
        while(p){
            p=p->next;
        }
        p=q;
        */
        while(p->next){
            p=p->next;
        }
        p->next=q;
    }
    
    /** Add a node of value val before the index-th node in the linked list. If index equals to the length of linked list, the node will be appended to the end of linked list. If index is greater than the length, the node will not be inserted. */
    void addAtIndex(int index, int val) {
        if(index<=0){//头结点
            addAtHead(val);
            return;
        }
        int i=0;
        MyLinkedList* p=head;
        while(i<index-1&&p){//找到index-th的前一个结点
            p=p->next;
            i++;
        }
        MyLinkedList* q;
        if(i==index-1&&p){//一般情况,包括末尾
            q=init_node(val);
            q->next=p->next;
            p->next=q;
        }

    }
    
    /** Delete the index-th node in the linked list, if the index is valid. */
    void deleteAtIndex(int index) {
        if(index<0) return;
        
        int i=0;
        MyLinkedList* p,*q;
        
        p=head;
        while(i<index-1&&p){//找到待删结点的前驱
            p=p->next;
            i++;
        }
        if(!p) return;//当后文涉及p->next时,此句话不可少
        /* 同样的错误:p指向head,但是用p进行操作时等号左边一定不能为p本身,否则只会改变自己
        if(index==0){//删除头结点
            q=p;
            p=p->next;
            //delete q; //1
        }
        */
        //以下为正确写法
        if(index==0){//删除头结点
            head=head->next;
        }
        //if(!p->next) return; //error,p=NULL时就错了
        if(i==index-1&&p->next){//一般,包括尾节点
            q=p->next;
            p->next=q->next;
            //delete q;//2 AddressSanitizer: attempting double-free on 0x602000000150 in thread T0
        }
        //delete q;  //没想到题目自己已经考虑了释放存储,我tm怎么会知道!!
    }
};

/**
 * Your MyLinkedList object will be instantiated and called as such:
 * MyLinkedList* obj = new MyLinkedList();
 * int param_1 = obj->get(index);
 * obj->addAtHead(val);
 * obj->addAtTail(val);
 * obj->addAtIndex(index,val);
 * obj->deleteAtIndex(index);
 */

【明日计划】

04-10
最后分享一个名人名言:

如果你刻意练习某个事物超过10000个小时,那么你就可以达到世界级——拉里·佩奇(谷歌创始人)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章