剑指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 myPow(double x, int n) {
        if(n<0 && (x==0||x==1))
               return x;
        double res = 1.0; int tmp=n;
        while(n){
                if(n&1) res *= x;
                x *= x;
                n = n/2;//常常不知道的是/是向0取整,而>>则是对负数来说则是向负无穷取整
        }
        return tmp<0?1/res:res;
    }
};

下一篇

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值