zoukankan      html  css  js  c++  java
  • 链表专项刷题

    leetcode no.2 两数相加

    • 题目内容为求两个逆序链表的和(首位是个位数,越大越往后)
    • 直接加就可以,留一个存进位的
    • 只要l1,l2,tempnum里面有一个不是空,就要再存进去一个数字
    • 记得执行完以后->next
    • 有可能存在0,所以 每轮的tempnum%10即使是0也要存的
    • 如果已在struct里面给出了构造,那么ListNode*temp=new ListNode就不行了,就得ListNode*temp=new ListNode(0);
    /**
     * Definition for singly-linked list.
     * struct ListNode {
     *     int val;
     *     ListNode *next;
     *     ListNode(int x) : val(x), next(NULL) {}
     * };
     */
    class Solution {
    public:
        ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
            ListNode*ans=new ListNode(0);
            ListNode*anstemp=new ListNode(0);
            anstemp=ans;
            int tempnum=0;
            while(l1!=NULL || l2!=NULL||tempnum)
            {
                if(l1)
                {
                    tempnum+=l1->val;
                    l1=l1->next;
                }
                if(l2)
                {
                    tempnum+=l2->val;
                    l2=l2->next;
                }
                ListNode*tempnode=new ListNode(tempnum%10);
                anstemp->next=tempnode;
                tempnum=tempnum/10;
                anstemp=anstemp->next;
            }
            return ans->next;
        }
    };
    View Code

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

    • 给好的是头就有数据的链表,因此pre->next=head这样比较合适
    • 特判遇到删除头节点的情况
    • 在找完数字然后找的过程,因为node的起始点进循环就node->next,所以temp=num-n+1以后还要-1(序列五个数字,倒数第二个,正数4,但是只在循环走三次)
    /**
     * Definition for singly-linked list.
     * struct ListNode {
     *     int val;
     *     ListNode *next;
     *     ListNode(int x) : val(x), next(NULL) {}
     * };
     */
    class Solution {
    public:
        ListNode* removeNthFromEnd(ListNode* head, int n) {
            if(head->next==NULL)
                return NULL;
            ListNode*tail=new ListNode(0);
            ListNode*pre=new ListNode(0);
            tail=head;
            int num=0;
            while(tail->next!=NULL)
            {
                num++;
                tail=tail->next;
            }
            num++;
            ListNode*node=new ListNode(0);
            node=head;
            pre->next=head;
            if(n==num)
                return head->next;
            int temp=num+1-n;
            for(int i=1;i<=temp-1;i++)
            {
                node=node->next;
                pre=pre->next;
            }
            pre->next=node->next;
            delete node;
            return head;
        }
    };
    View Code

     leetcode no.19 更优秀的做法

    • 一轮遍历,使用两个指针,两个指针中间隔着n-2个数,即end先走n-1次,之后两个同步移动直至end走到尾巴上
    • 注意删除是head的情况
    /**
     * Definition for singly-linked list.
     * struct ListNode {
     *     int val;
     *     ListNode *next;
     *     ListNode(int x) : val(x), next(NULL) {}
     * };
     */
    class Solution {
    public:
        ListNode* removeNthFromEnd(ListNode* head, int n) {
            ListNode*first=new ListNode(0);
            ListNode*end=new ListNode(0);
            first=head;
            end=head;
            ListNode*pre=new ListNode(0);
            pre->next=head;
            int num=1;
            while(num<=n-1)
            {
                num++;
                end=end->next;
            }
            if(end->next==NULL)
                return head->next;
            while(end->next!=NULL)
            {
                first=first->next;
                end=end->next;
                pre=pre->next;
            }
            pre->next=first->next;
            delete first;
            return head;
        }
    };
    View Code

     leetcode no.23 合并k个排序链表

    • 注意特判整个vector空的情况
    • 里面每个链表都走到尽头退出循环
    • 注意!所有涉及到链表的题目一定要一个ans存结果。一个temp不断temp->next
    /**
     * Definition for singly-linked list.
     * struct ListNode {
     *     int val;
     *     ListNode *next;
     *     ListNode(int x) : val(x), next(NULL) {}
     * };
     */
    class Solution {
    public:
        ListNode* mergeKLists(vector<ListNode*>& lists) {
            ListNode*ans=new ListNode(0);
            ListNode*temp=new ListNode(0);
            if(lists.empty())
                return ans->next;
            temp=ans;
            int minnum=10000;
            int mindown=-1;
            bool notempty=true;
            while(notempty)
            {
                notempty=false;
                mindown=-1;
                minnum=10000;
                for(int i=0;i<=lists.size()-1;i++)
                {
                    if(lists[i]!=NULL)
                    {
                        notempty=true;
                        if(lists[i]->val<minnum)
                        {
                            minnum=lists[i]->val;
                            mindown=i;
                        }
                    }
                }
                if(!notempty)
                    break;
                temp->next=new ListNode(lists[mindown]->val);
                temp=temp->next;
                lists[mindown]=lists[mindown]->next;
            }
            return ans->next;
        }
    };
    View Code

     leetcode no.23合并k个排序链表

    • 可以采用分治的方法,每次计算两个链表,步长每次扩大而
    • 注意空的情况,这时候访问lists[0]也是违规的
    /**
     * Definition for singly-linked list.
     * struct ListNode {
     *     int val;
     *     ListNode *next;
     *     ListNode(int x) : val(x), next(NULL) {}
     * };
     */
    class Solution {
    public:
        ListNode*merge(ListNode*l1,ListNode*l2)
        {
            if(l1==NULL)
                return l2;
            if(l2==NULL)
                return l1;
            ListNode*ans=new ListNode(0);
            ListNode*temp=new ListNode(0);
            temp=ans;
            while(l1 && l2)
            {
                if(l1->val<=l2->val)
                {
                    ListNode*p=new ListNode(l1->val);
                    l1=l1->next;
                    temp->next=p; 
                    temp=temp->next;  
                }
                else
                {
                    ListNode*p=new ListNode(l2->val);
                    l2=l2->next;
                    temp->next=p;
                    temp=temp->next;
                }
            }
            if(l1)
            temp->next=l1;
            if(l2)
            temp->next=l2;
            return ans->next;
        }
        ListNode* mergeKLists(vector<ListNode*>& lists) {
            if(lists.empty()==true)
             return NULL;
            for(int step=1;step<=lists.size();step=step*2)
            {
                for(int i=0;i<=lists.size()-1;i=i+step)
                {
                    if(i+step<=lists.size()-1)
                    lists[i]=merge(lists[i],lists[i+step]);
                }
            }
            return lists[0];
        }
    };
    View Code

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

    • 如果只有一个或者为空直接返回
    • 前面两个节点的交换要拉出来,因为head发生变化要存储返回值
    • 后面的节点要存好pre是交换前的最后一个点,head代表当前要交换的第一个点
    • pre->next=head->next head->next=pre->next->next pre->next->next=head 保持原则,一个被用完了以后立即修改
    • 前两个点里面:newhead=head->next head->next=newhead->next newhead->next=head newhead成为新的起点。
    /**
     * Definition for singly-linked list.
     * struct ListNode {
     *     int val;
     *     ListNode *next;
     *     ListNode(int x) : val(x), next(NULL) {}
     * };
     */
    class Solution {
    public:
        ListNode* swapPairs(ListNode* head) {
            if(head==NULL||head->next==NULL)
                return head; 
            ListNode*newHead=new ListNode(0);
            newHead=head->next;
            head->next=newHead->next;
            newHead->next=head;
            ListNode*temp=new ListNode(0);
            temp=head;
            while(temp->next!=NULL && temp->next->next!=NULL)
            {
                head=temp->next;
                temp->next=head->next;
                head->next=temp->next->next;
                temp->next->next=head;
                temp=head;
            }
            return newHead;
        }
    };
    View Code

     leetcode no.25 K个一组翻转链表(修改指针指向的方法)

    • 注意如果刚好有k个,是需要反转的,即使后面没有了
    • count和nownode每次是对应的。指向这组的第几个点count就是几
    • prev标记的是k个一组这个组前一个点,nownode在next以后是k个一组的下一个点,中间的就是k个区间
    • 中间的每次修改next的指向
    • k个找到以后,执行k-1轮,因为最后一轮需要和prev单独标记,此时的cur指向k个一组的原来的最后一个点
    • 如果是第一组,那么需要修改head为cur的值
    • 不是第一组,那么prev->next=就是最后cur
    • 这组中第一个点的next是newnode
    • 新一轮的prev是这一组原始的第一个点,是需要标记好的,新一轮的cur就是nownode
    /**
     * Definition for singly-linked list.
     * struct ListNode {
     *     int val;
     *     ListNode *next;
     *     ListNode(int x) : val(x), next(NULL) {}
     * };
     */
    class Solution {
    public:
        ListNode* reverseKGroup(ListNode* head, int k) {
            ListNode*cur=new ListNode(0);
            ListNode*pre=new ListNode(0);
            ListNode*next=new ListNode(0);
            ListNode*nownode=new ListNode(0);
            ListNode*prev=new ListNode(0);
            ListNode*temp=new ListNode(0);
            bool pd=true;
            int count=1;
            cur=head;
            nownode=head;
            prev=NULL;
            while(nownode!=NULL)
            {
                if(count==k)
                {
                    nownode=nownode->next;
                    if(cur==head)
                        pd=true;
                    pre=nownode;
                    temp=cur;
                    for(int i=1;i<k;i++)
                    {
                        next=cur->next;
                        cur->next=pre;
                        pre=cur;
                        cur=next;
                    }
                    if(pd)
                    {
                        head=cur;
                        pd=false;
                    }
                    if(prev!=NULL)
                        prev->next=cur;
                    prev=temp;
                    //temp=cur->next;
                    cur->next=pre;
                    cur=nownode;
                    count=1;
                }
                else
                {
                    count++;
                    nownode=nownode->next;
                }
            }
            return head;
        }
    };
    View Code

     leetcode no.61 旋转链表

    • 链表后移k个单位,如果k大于len就取余
    • 双指针移动,对应temp2就是尾节点,next接原始头
    • temp1是倒数第k个点,是新的head
    • pre是新的尾节点
    • 注意k等于0的时候,不需要转动,这样必须直接返回,不能进到下面,不然pre会有问题。
    • 需要修改的点是,修改以后选temp1为新的head,原来的尾节点temp2加next是原来的head,新的head前面最后一个点pre的next成NULL。
    /**
     * Definition for singly-linked list.
     * struct ListNode {
     *     int val;
     *     ListNode *next;
     *     ListNode(int x) : val(x), next(NULL) {}
     * };
     */
    class Solution {
    public:
        ListNode* rotateRight(ListNode* head, int k) {
            if(head==NULL)
                return head;
            ListNode*temp1=new ListNode(0);
            ListNode*temp2=new ListNode(0);
            temp1=head;temp2=head;
            int len=0;
            while(temp1!=NULL)
            {
                len++;
                temp1=temp1->next;
            }
            k=k%len;
            if(k==0)
                return head;
            for(int i=1;i<=k-1;i++)
                temp2=temp2->next;
            ListNode*pre=new ListNode(0);
            pre->next=head;
            temp1=head;
            while(temp2->next!=NULL)
            {
                pre=pre->next;
                temp1=temp1->next;
                temp2=temp2->next;
            }
            temp2->next=head;
            pre->next=NULL;
            return temp1;
        }
    };
    View Code
    时间才能证明一切,选好了就尽力去做吧!
  • 相关阅读:
    lambda表达式
    Java的MongoDB驱动及读写策略
    MongDB主从复制、复制集
    PL/SQL练习
    MySQL数据库MyISAM和InnoDB存储引擎的比较(转)
    Java的垃圾回收概述
    springMVC源码浅析
    ActiveMQ使用总结
    常用的缓存产品比较
    Nginx+tomcat负载均衡并动静态分离
  • 原文地址:https://www.cnblogs.com/tingxilin/p/12519451.html
Copyright © 2011-2022 走看看