劍指offer(三):鏈表(cpp)

上一篇

1.從尾到頭打印鏈表

輸入一個鏈表,按鏈表從尾到頭的順序返回一個ArrayList。

    vector<int> printListFromTailToHead(ListNode* head) {
        vector<int> res;
        if(!head)
            return res;
        while(head!=nullptr){
            res.push_back(head->val);
            head = head->next;
        }
        reverse(res.begin(),res.end());
        return res;
    }

注意:此處重點應當是考查棧的使用,不過先輸入在反轉也可以,時間複雜度一樣。

2.鏈表中倒數第k個結點

輸入一個鏈表,輸出該鏈表中倒數第k個結點。

class Solution {
public:
    ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {
        if(pListHead==nullptr || k<=0)
            return nullptr;
        ListNode* fast=pListHead, *slow=pListHead;
        unsigned int i=k;
        for(;i>0&&fast;--i)
            fast = fast->next;
        if(i!=0)    return nullptr;
        while(fast){
            fast = fast->next;
            slow = slow->next;
        }
        return slow;
    }
};

3.反轉鏈表

輸入一個鏈表,反轉鏈表後,輸出新鏈表的表頭。

    ListNode* ReverseList(ListNode* pHead) {
        if(pHead==nullptr||pHead->next==nullptr)
            return pHead;
        ListNode *pre=pHead, *now=pHead->next, *tmp=nullptr;
        pre->next = nullptr;
        while(now){
            tmp = now;
            now = now->next;
            tmp->next = pre;
            pre = tmp;
        }
        return pre;
    }

4. 合併兩個排序的鏈表

輸入兩個單調遞增的鏈表,輸出兩個鏈表合成後的鏈表,當然我們需要合成後的鏈表滿足單調不減規則。

class Solution {
public:
    void merge(ListNode* p1, ListNode* p2,ListNode* head){
        ListNode* to=head;
        while(p1&&p2){
            if(p1->val<=p2->val){
                to->next = p1;
                to = to->next;
                p1 = p1->next;
            }else{
                to->next = p2;
                to = to->next;
                p2 = p2->next;
            }
        }
        while(p1){
            to->next = p1;
            to = to->next;
            p1 = p1->next;
        }
        while(p2){
            to->next = p2;
            to = to->next;
            p2 = p2->next;
        }
        to->next = nullptr;
    }
    ListNode* Merge(ListNode* pHead1, ListNode* pHead2)
    {
        if(!pHead1)
            return pHead2;
        else if(!pHead2)
            return pHead1;
        ListNode *p1=pHead1, *p2=pHead2, *head;
        if(p1->val<=p2->val){
            head = p1;
            merge(p1->next,p2,head);
        }else{
            head = p2;
            merge(p1,p2->next,head);
        }
        return head;
    }
};

5.複雜鏈表的複製

輸入一個複雜鏈表(每個節點中有節點值,以及兩個指針,一個指向下一個節點,另一個特殊指針指向任意一個節點),返回結果爲複製後複雜鏈表的head。(注意,輸出結果中請不要返回參數中的節點引用,否則判題程序會直接返回空)

/*
struct RandomListNode {
    int label;
    struct RandomListNode *next, *random;
    RandomListNode(int x) :
            label(x), next(NULL), random(NULL) {
    }
};
*/
class Solution {
public:
    RandomListNode* CopyNode(RandomListNode* node){
        RandomListNode* head = new RandomListNode(node->label);
        head->next = node->next;
        return head;
    }
    RandomListNode* Clone(RandomListNode* pHead){
        if(!pHead)    return nullptr;
        RandomListNode* node = pHead, *clone=nullptr;
        while(node){//複製單個節點
            node->next = CopyNode(node);
            node = node->next->next;
        }
        node = pHead;
        while(node){//複製random節點
            if(node->random)
                node->next->random = node->random->next;
            node = node->next->next;
        }
        RandomListNode* head = pHead->next;
        node=pHead;
        node->next = head->next;
        node = node->next;
        clone = head;
        while(node){//分離複合鏈表
            clone->next = node->next;
            clone = clone->next;
            node->next = clone->next;
            node = node->next;
        }
        return head;
    }
};

6. 二叉搜索樹與雙向鏈表

輸入一棵二叉搜索樹,將該二叉搜索樹轉換成一個排序的雙向鏈表。要求不能創建任何新的結點,只能調整樹中結點指針的指向。

/*
struct TreeNode {
	int val;
	struct TreeNode *left;
	struct TreeNode *right;
	TreeNode(int x) :
			val(x), left(NULL), right(NULL) {
	}
};*/
class Solution {
public:
    void ConvertNode(TreeNode* proot,TreeNode** plast){
        if(!proot)
            return;
        ConvertNode(proot->left,plast);
        proot->left = *plast;
        if((*plast))
            (*plast)->right = proot;
        *plast = proot;
        ConvertNode(proot->right,plast);
    }
    TreeNode* Convert(TreeNode* pRootOfTree)
    {
        TreeNode *plastnode = nullptr;
        ConvertNode(pRootOfTree,&plastnode);
        TreeNode* head = plastnode;
        while(head!=nullptr && head->left!=nullptr)
            head = head->left;
        return head;
    }
};

7. 兩個鏈表的第一個公共結點

輸入兩個鏈表,找出它們的第一個公共結點。(單鏈表)

class Solution {
public:
    void length(ListNode* pHead1, ListNode* pHead2 ,int *l1, int *l2){
        (*l1)=(*l2)=0;
        while(pHead1)
        { pHead1 = pHead1->next; ++(*l1);}
        while(pHead2)
        { pHead2 = pHead2->next; ++(*l2);}
    }
    ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) {
        if(!pHead1 || !pHead2)
            return nullptr;
        ListNode *pub, *p1=pHead1,*p2=pHead2;
        int l1,l2;
        length(p1,p2,&l1,&l2);
        int tmp =(l1>l2)?(l1-l2):(l2-l1);
        while(tmp--){
            if(l1>l2)
                p1 = p1->next;
            else
                p2 = p2->next;
        }
        while(p1!=p2){
            p1 = p1->next;
            p2 = p2->next;
        }
        return p1;
    }
};

8.鏈表中環的入口結點(單鏈表)

給一個鏈表,若其中包含環,請找出該鏈表的環的入口結點,否則,輸出null。

class Solution {
public:
    bool HasCircle(ListNode* phead,ListNode** meet){
        if(phead==nullptr || phead->next==nullptr)
            return false;
        ListNode *slow=phead->next;
        ListNode *fast=slow->next; 
        while(fast&&slow && fast!=slow){
            if(fast->next)
                fast = fast->next->next;
            else
                break;
            slow = slow->next;
        }
        (fast==slow)?((*meet)=fast):((*meet)=nullptr);
        return (fast==slow);
    }
    int NumberofCircle(ListNode* phead){
        ListNode *meet, *p;
        int num=1;
        if(!HasCircle(phead,&meet))
            return -1;
        p = meet->next;
        while(p!=meet){
            ++num;
            p = p->next;
        }
        return num;
    }
    ListNode* EntryNodeOfLoop(ListNode* pHead)
    {
        int nums ;
        if((nums=NumberofCircle(pHead))==-1)
            return nullptr;
        ListNode *front=pHead, *rear=pHead;
        while(nums--)
            front = front->next;
        while(front != rear){
            front = front->next;
            rear = rear->next;
        }
        return front;
    }
};

9. 刪除鏈表中重複的結點

在一個排序的鏈表中,存在重複的結點,請刪除該鏈表中重複的結點,重複的結點不保留,返回鏈表頭指針。 例如,鏈表1->2->3->3->4->4->5 處理後爲 1->2->5

class Solution {
public:
    ListNode* deleteDuplication(ListNode* pHead)
    {
        if(pHead==nullptr || pHead->next==nullptr)
            return pHead;
        ListNode* preNode = nullptr;
        ListNode* pNode = pHead;
        while(pNode!=nullptr){
            ListNode* next = pNode->next;
            bool needDelete = false;
            if(next && next->val==pNode->val)
                needDelete = true;
            if(!needDelete){
                preNode = pNode;
                pNode = next;
            }else{
                int val = pNode->val;
                ListNode* delNode = pNode;
                while(delNode!=nullptr && delNode->val==val){
                    next = delNode->next;
                    delete delNode;
                    delNode = next;
                }
                if(preNode==nullptr)
                    pHead = next;
                else
                    preNode->next = next;
                pNode =  next;
            }
        }
        return pHead;
    }
};

10. 數值的整數次方

給定一個double類型的浮點數base和int類型的整數exponent。求base的exponent次方。
保證base和exponent不同時爲0(要考慮全面)

class Solution {
public:
    double PowerWithexp(double base,int absexp){
        if(absexp==0)
            return 1;
        if(absexp==1)
            return base;
        double res = PowerWithexp(base,absexp>>1);
        res *=res;
        if(absexp&0x1==1)
            res *=base;
        return res;
    }
    double Power(double base, int exponent) {
        if(base==0 && exponent<0 || base==0)
            return 0;
        int absexp; 
        (exponent>=0)?(absexp=exponent):(absexp=-exponent);
        double res = PowerWithexp(base,absexp);
        if(exponent<0)
            res = 1.0/res;
        return res;
    }
};

下一篇

發佈了39 篇原創文章 · 獲贊 7 · 訪問量 4397
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章