【計劃執行報告】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個小時,那麼你就可以達到世界級——拉里·佩奇(谷歌創始人)

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