day4-代码随想录算法训练营(19)-链表

今天的三道题感觉都比较简单(当然我借用了其他数据结构),因为之前碰到好多次

24.两两交换链表中的节点

思路一:使用哈希表保存节点和下标,根据下标直接对节点进行交换

class Solution {
public:
    unordered_mapans;
    ListNode* swapPairs(ListNode* head) {
        if(head==nullptr)
            return head;
        //思路:使用哈希表保存,然后根据下标交换
        ListNode*p=head;
        int index=0;
        while(p)
        {
            ans[++index]=p;
            p=p->next;
        }
        // cout<next=head;
        ListNode*pre=newHead;
        //需要三个指针
        int count=index/2,l=1,r=2;
        while(count>0)
        {

            ans[l]->next=ans[r]->next;
            ans[r]->next=ans[l];
            pre->next=ans[r];
            pre=ans[l];
            l+=2;
            r+=2;
            
            count--;
        }
        return newHead->next;
    }
};

这一题感觉使用哈希表清晰明了一些。

思路二:看了录友的题解,确实直接用指针查找更省空间一些,时间上也快一点

class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        //思路:使用指针直接交换
        if(head==nullptr)
            return head;
        ListNode*newHead=new ListNode();
        newHead->next=head;
        ListNode*pre=newHead;
        while(pre->next!=nullptr && pre->next->next!=nullptr)
        {
            ListNode*node1=pre->next;
            ListNode*node2=pre->next->next;

            //交换位置
            node1->next=node2->next;
            node2->next=node1;
            pre->next=node2;
            pre=node1;
        }
        return newHead->next;
    }
};

 19.删除链表的倒数第N个节点 

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        //思路:先遍历链表算出长度,然后根据n求出是正数第几个,然后直接删除
        int count=0;
        ListNode*newHead=new ListNode();
        newHead->next=head;
        ListNode*pre=newHead;
        ListNode*cur=head,*p=head;
        while(p)
        {
            count++;
            p=p->next;
        }
        int mid=0;
        while(cur)
        {
            if(mid==count-n)
            {
                if(cur->next==nullptr)
                {
                    pre->next=nullptr;
                    break;
                }
                pre->next=cur->next;
                cur=nullptr;
                break;
            }
            cout<val<next;
        }
        return newHead->next;
    }
};

这一题没啥好说的,应该是逻辑上比较简单吧

 面试题 02.07. 链表相交 

class Solution {
public:
    unordered_mapans;
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        //思路:利用哈希表直接加入第一个头结点的链表,第二个头结点之后查看是否存在,第一个存在的就是相交节点
        ListNode*pa=headA,*pb=headB;
        while(pa)
        {
            ans[pa]++;
            pa=pa->next;
        }
        while(pb)
        {
            if(ans[pb]>0)
                return pb;
            pb=pb->next;
        }
        return nullptr;
    }
};
本题做过多次,只要将节点直接比较,就可以找出相交点

142.环形链表II

class Solution {
public:
    unordered_mapans;
    ListNode *detectCycle(ListNode *head) {
        //思路:跟相交链表异曲同工,直接用哈希表
        ListNode*p=head;
        while(p)
        {

            ans[p]++;
            if(ans[p]>1)
                return p;
            p=p->next;
        }
        return nullptr;
    }
};

本地跟上一题一样,直接使用节点进行比较

328.奇偶链表

思路一:第一眼看到的时候直接想到哈希表加进去,然后根据下标的奇偶性直接连接
class Solution {
public:
    ListNode* oddEvenList(ListNode* head) {
        //思路:先使用两个头指针指向第一个节点和第二个节点,用一个变量index记录节点位置,用一个指针遍历链表,
        //思路二:突然想到可以直接遍历两次链表,第一次拿出来奇数节点链表,找到尾节点,
        //第二次直接把偶数节点放在尾节点后面
        //需要:一个头结点指针,一个遍历指针,一个pre指针
        //问题:实践起来发现一次遍历会改变链表,无法进行第二次遍历
        //思路三:使用哈希表记录节点和下标,一次遍历后
        //问题:节点的next指针改变前要先置空,不然很容易起冲突
        ListNode*newHead=new ListNode(),*newHead2=new ListNode();
        vectorans={newHead};
        ListNode*cur=head,*pre=newHead,*Op=newHead2;
        int index=1;
        while(cur)
        {
            ans.push_back(cur);
            cur=cur->next;
        }
        for(auto it:ans)
        {
            it->next=nullptr;
        }
        for(int i=1;inext=ans[i];
                pre=ans[i];     
            }
            else
            {
                Op->next=ans[i];
                Op=ans[i];
            }
        }
        //cout<val;
        pre->next=newHead2->next;
        return newHead->next;

    }
};
思路二:直接再链表中原地操作

看了题解发现原来还能这样,我的思路一开始就想复杂了

class Solution {
public:
    ListNode* oddEvenList(ListNode* head) {
        //思路:先使用两个头指针指向第一个节点和第二个节点,用一个变量index记录节点位置,用一个指针遍历链表,(未完成)
        //思路二:突然想到可以直接遍历两次链表,第一次拿出来奇数节点链表,找到尾节点,
        //第二次直接把偶数节点放在尾节点后面
        //需要:一个头结点指针,一个遍历指针,一个pre指针
        //问题:实践起来发现一次遍历会改变链表,无法进行第二次遍历(未完成)
        //思路三:使用哈希表记录节点和下标,一次遍历后
        //问题:节点的next指针改变前要先置空,不然很容易起冲突(完成,复杂度过高)
        //直接指针交换:变量index,当前指针cur,上一个指针pre(未完成)
        //思路四:分离节点后合并,C指针记录第二个节点,A指针指向头结点,B指针指向第二个节点
        //        在B指针指向的节点存在并且B指针的下一个节点存在时
        //        把A指针指向的节点的next指向B指针的next,再把A指针的next赋值给A指针
        //        此时再把B指针指向的节点的next指向A指针的next,把B指针的next赋值给B指针
        if(head==nullptr)
            return head;
        ListNode*newHead=head->next;
        ListNode*curOdd=head,*curEven=newHead;
        while(curEven && curEven->next)
        {
            curOdd->next=curEven->next;
            curOdd=curOdd->next;
            curEven->next=curOdd->next;
            curEven=curEven->next;
        }
        curOdd->next=newHead;
        return head;
    }
};

重点:奇偶节点是分开连接的

你可能感兴趣的:(代码随想录算法训练营(19期),算法,链表,leetcode)