剑指offer-链表

面试题18:删除链表中重复的节点

在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。
思路1:递归版

class Solution {
public:
    ListNode* deleteDuplication(ListNode* pHead)
    {
        if(pHead==nullptr||pHead->next==nullptr)//节点数为0和1时,返回
            return pHead;
        if(pHead->val == pHead->next->val) //只分两种,当前节点和下一个节点重复,不重复
        {
            while(pHead!=nullptr&&pHead->next!=nullptr&&pHead->val==pHead->next->val)
            {
                pHead = pHead->next;
            }//找到当前节点与下一个节点不重复的点,从不重复的点开始递归
            return deleteDuplication(pHead->next);
        }
        else
        {
            pHead->next = deleteDuplication(pHead->next);
            return pHead;
        }
    }
};

思路2 非递归版

class Solution {
public:
    ListNode* deleteDuplication(ListNode* pHead)
{
    if( pHead == NULL ) return pHead;

    ListNode *pre = NULL; //指向前面最晚访问过的不重复结点
    ListNode *p = pHead; //指向当前处理的结点
    ListNode *q = NULL; //指向当前处理结点后面结点

    while( p != NULL )
    {
        //当前结点p,(其实是p指向当前结点),与它下一个结点p->next的val相同,说明要删掉有这个val的所有结点
        if( p->next != NULL && p->next->val == p->val )
        {
            q = p->next;

            //找到q,它指向最后一个与p val相同的结点,那p 到 q (包含) 都是要删除的
            while( q != NULL && q->next != NULL && q->next->val == p->val )
            {
                q = q->next;
            }

            //如果p指向链表中第一个元素,p -> ... -> q ->... , 要删除p到q, 将指向链表第一个元素的指针pHead指向q->nextif( p == pHead )
            {
                pHead = q->next;
            }
            else//如果p不指向链表中第一个元素,pre -> p ->...->q ->... ,要删除p到q,即pre->next = q->next
            {
                pre->next = q->next;
            }
            //当前处理的p要向链表尾部移动
            p = q->next;
        }
        else
        {
            pre = p;
            p = p->next;
        }
    }
    return pHead;
}

};

面试题22:输入一个链表,输出该链表中倒数第k个结点。

class Solution {
public:
    ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {
        //头指针为空,输入参数为空时返回空
        if(pListHead==NULL||k==0)
            return NULL;
        ListNode*pTail=pListHead,*pHead=pListHead;
        //先让第一个指针向前走k-1步到达第k个节点
        for(int i=1;i<k;++i)
        {
            if(pHead->next!=NULL)
                pHead=pHead->next;
            else
                return NULL;//节点总数小于k
        }
        //第二个指针也从链表的头指针开始,
        //第一个指针到达尾节点时,第二个到达倒数第k个
        while(pHead->next!=NULL)
        {
            pHead=pHead->next;
            pTail=pTail->next;
        }
        return pTail;
    }
};

面试题6 从尾到头打印链表

面试题24 反转链表

输入一个链表,从尾到头打印链表每个节点的值。
思路1:
把节点的值从头节点开始放到vector里
反转vector。

/**
*  struct ListNode {
*        int val;
*        struct ListNode *next;
*        ListNode(int x) :
*              val(x), next(NULL) {
*        }
*  };
*/
class Solution {
public:
    vector<int> printListFromTailToHead(ListNode* head) {
       vector<int> v;
        ListNode *p =head;
        while (p != nullptr) {
           v.push_back(p->val);
           p = p->next;
        }
        reverse(v.begin(),v.end());
        return v;
    }
};

思路2
把链表反转,在从反转后的链表的头结点遍历

class Solution {
public:
    vector<int> printListFromTailToHead(ListNode* head) {
       vector<int> v;
        ListNode *p =head;    //当前节点
        ListNode *pre = nullptr;  //前一个节点
        //反转链表
        while(p!=nullptr)
        {
            ListNode *pnext = p->next; //把后一个节点存起来防止断链 
            p->next = pre;  
            pre = p;
            p = pnext; 
        }
        //这时的pre 是反转链表的头节点
        while(pre!=nullptr)
        {
            v.push_back(pre->val);
            pre = pre->next;
        }
        return  v;
    }
};

面试题25 合并两个排序的链表

思路:递归版

class Solution {
public:
    ListNode* Merge(ListNode* pHead1, ListNode* pHead2)
    {
        if(pHead1==nullptr)return pHead2;//递归的边界
        if(pHead2==nullptr)return pHead1;
        if(pHead1->val < pHead2->val)
        {
            pHead1->next =Merge(pHead1->next, pHead2);
            return pHead1;//返回头指针
        }
        else
        {
            pHead2->next =Merge(pHead1, pHead2->next);
            return pHead2;//返回头指针
        }
    }
};

思路2:非递归版

class Solution {
public:
    ListNode* Merge(ListNode* pHead1, ListNode* pHead2)
    {
        if(pHead1==nullptr)return pHead2;
        if(pHead2==nullptr)return pHead1;
        ListNode *mergeHead=nullptr;
        if(pHead1->val < pHead2->val)
        {
             mergeHead = pHead1;   //头指针先赋给值小的
             pHead1 = pHead1->next; 
        }
        else
        {
             mergeHead = pHead2;
             pHead2 = pHead2->next;
        }
        ListNode *p = mergeHead;  //头指针先留着要返回,p是工作指针
        while(pHead1&&pHead2)     //有一个链表到结尾时,结束
        {
            if(pHead1->val < pHead2->val)
            {
              p->next = pHead1;
              p = p->next;
              pHead1 = pHead1->next; 
             }
            else
            {
              p ->next = pHead2;
              p = p->next;
              pHead2 = pHead2->next;
             }
        }
        if(pHead1==nullptr)p->next = pHead2;//链表1遍历完了
        if(pHead2==nullptr)p->next = pHead1;
        return mergeHead;
    }
};

面试题52: 两个链表的第一个公共节点

计算两连表的长度差
如果链表1的长度大于链表2的长度
先遍历链表1,遍历的长度就是两链表的长度差
如果链表2的长度大于链表1的长度
先遍历链表2,遍历的长度就是两链表的长度差
开始齐头并进,直到找到第一个公共结点

ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) 
{
    ListNode* cur1 = pHead1;
    ListNode* cur2 = pHead2;
    int len1 = getList_len(cur1);
    int len2 = getList_len(cur2);
    if(len1>len2)
    {
        int len = len1-len2;
        while(len--)
            cur1 = cur1->next;
    }  
    else
    {
        int len = len2-len1;
        while(len--)
            cur2 = cur2->next;
    }
    while(cur1!=cur2)
    {
        cur1=cur1->next;
        cur2=cur2->next;
    }
    return cur1;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值