leetcode刷题纪实(二)

leetcode141

给定一个链表,判断链表中是否有环。

class Solution 
{
public:    
    bool hasCycle(ListNode *head) {        //判断链表中是否有环        
        if(head==NULL){            
            return false;        
        }        
        ListNode *l1=head;        
        ListNode *l2=l1->next;        
        while(l1!=NULL){            
            while(l2!=NULL){                
                if(l2->next==l1){                    
                    return true;                
                }                
                else{                    
                    l2=l2->next;                
                }            
            }            
        l1=l1->next;        
        }        
    return false;    
    }
};

上来想到的还是这种两个指针两重循环的垃圾写法,结果不出所料的超时了,再想想好一点的写法。。。

class Solution 
{
public:
    bool hasCycle(ListNode* head) {    //两个运动员位于同意起点head    
        ListNode* faster{ head };  //快的运动员    
        ListNode* slower{ head };  //慢的运动员
        if (head == NULL)  //输入链表为空,必然不是循环链表        
            return false;
        while (faster != NULL && faster->next != NULL)    {        
            faster = faster->next->next;  //快的运动员每次跑两步        
            slower = slower->next;  //慢的运动员每次跑一步        
            if (faster == slower)  //他们在比赛中相遇了            
            return true;  //可以断定是环形道,直道不可能相遇    
            }    
        return false;  //快的运动员到终点了,那就是直道,绕圈跑不会有终点
    }
};

利用这种快慢指针,非常容易的转化成了一遍循坏,还有没有更快一点的呢?

class Solution {
public:
    bool hasCycle(ListNode* head) {    
        class Solution {public:    
        bool hasCycle(ListNode *head) {        
            if(!head) 
                return false;        
            auto pt = head;        
            unordered_set<ListNode*> s;        
            while(s.find(pt) == s.end()) {            
                s.insert(pt);            
                pt = pt->next;            
                if(!pt)                
                    return false;        
                }        
            return true;    
        }
    };

利用hash表来完成,也同样不难

leetcode160

编写一个程序,找到两个单链表相交的起始节点。
第一个想到的是之前做王道数据结构书上的算法
遍历得到两个链表的长度,求长度差diff;
两个指针分别指向两个链表的头结点,让更长的那个链表的指针先走diff步后,两个指针在同时移动,遇到的第一个相同的节点就是他们的公共节点。

ListNode *getIntersectionNode(ListNode *headA, ListNode *headB){    
    ListNode *CommomNode = nullptr;    
    if(headA != nullptr && headB != nullptr)    {        
        int countA = 0;        
        int countB = 0;        
        ListNode *pNodeA = headA;        
        ListNode *pNodeB = headB;        
        while(pNodeA != nullptr)        {            
            countA++;            
            pNodeA = pNodeA->next;        
        }        
        while(pNodeB != nullptr)        {            
            countB++;            
            pNodeB = pNodeB->next;        
        }        //长的链表先走        
        pNodeA = headA;        
        pNodeB = headB;        
        int diff = abs(countA - countB);        
        if(countA > countB)        {            
            for(int i = 0;i < diff;i++)            {                
                pNodeA = pNodeA->next;            
            }        
        }        
        else if(countA < countB)        {            
            for(int i = 0;i < diff;i++)            {                
                pNodeB = pNodeB->next;            
            }        
        }
        while(pNodeA!= nullptr && pNodeB != nullptr)        {            
            if(pNodeA == pNodeB)            {                
                CommomNode = pNodeA;                
                break;            
            }            
        pNodeA = pNodeA->next;            
        pNodeB = pNodeB->next;        
        }    
    }    
    return CommomNode;
}

当然也可以用双指针暴力破解法,就不写了
再想想其他方法

class Solution {
public:    
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB){
    unordered_set<ListNode *> st;        
    while(headA!=NULL){            
        st.insert(headA);            
        headA=headA->next;        
    }         
    while(headB!=NULL){            
        if(st.count(headB)) 
            return headB;            
        headB=headB->next;        
    }        
    return NULL;    
    }
};

看leetcode官方给出的一种答案真的给惊艳到了,代码竟然可以这么浪漫,真的好遗憾自己以前不曾发现过代码的美妙和乐趣

public:    
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {        //
        if (headA == NULL || headB == NULL) 
            return NULL;        
        ListNode *pA = headA, *pB = headB;        
        while (pA != pB) {            
        pA = pA == NULL ? headB : pA->next;            
        pB = pB == NULL ? headA : pB->next;        
    }        
    return pA;    
    }
};

这个方法翻译成中文就是:
我来到 你的城市
走过你来时的路

leetcode203

删除链表中等于给定值 val 的所有节点。
很简单的题,就是一遍遍历呗

class Solution {
public:    
    ListNode* removeElements(ListNode* head, int val) {
        ListNode* dummy = new ListNode(0);        
        dummy->next = head;
        ListNode* prev = dummy;
        while(prev->next)        {            
            if(prev->next->val == val)            {                
                ListNode* tmp = prev->next;                
                prev->next = prev->next->next;                
                delete tmp;//对于链表来说要释放空间不要忘记了!            
                }            
            else            {                
                prev = prev->next;            
            }        
        }
        return dummy->next;    
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值