链表

1.环形链表插值

从小到大环形列表,测试用例:

[1,3,4,5,7],[1,2,3,4,0],2
返回:{1,2,3,4,5,7}

方法一

class InsertValue {
public:
    ListNode* insert(vector<int> A, vector<int> nxt, int val) {
        if(A.size()==0){
            ListNode *node=new ListNode(val);
            node->next=node;
            return node;
        }
        ListNode *head=new ListNode(A[0]);
        ListNode *h1=head;
        for(int i=1;i<A.size();i++){
            h1->next=new ListNode(A[i]);
            h1=h1->next;
        }
        h1->next=NULL;
        ListNode *pre=head,*cur=head->next;
         
        if(pre->val>=val){
            ListNode *node=new ListNode(val);
            node->next=head;
            head=node;
            return head;
        }
        while(cur!=NULL){
            if(pre->val<=val&&val<=cur->val){
                ListNode *node=new ListNode(val);
                pre->next=node;
                node->next=cur;
                break;
            }
            pre=pre->next;
            cur=cur->next;
        }
         
        if(cur==NULL){
            ListNode *node=new ListNode(val);
            pre->next=node;
            node->next=NULL;
        }
        return head;
    }
};

方法二

class InsertValue {
public:
    ListNode* insert(vector<int> A, vector<int> nxt, int val) {
        
        ListNode* root = NULL;
        if (A.empty()) return root;
        
        root = new ListNode(A[0]);
        ListNode *p = root;
        
        for (int i = 1; i < A.size(); ++i) {
            ListNode* tmp = new ListNode(A[nxt[i-1]]);
            p->next = tmp;
            p = tmp;
        }
        //p->next = root;
        p->next = NULL;
        if (root->val > val) {
            ListNode *tmp = new ListNode(val);
            tmp->next = root;
            root = tmp;
            //p->next = root;
            p->next = NULL;
            return root;
        }
        p = root;

        //while (p->next != root) {

        while (p->next) {
            if (val >= p->val && val <= p->next->val) {
                ListNode *tmp = new ListNode(val);
                tmp->next = p->next;
                p->next = tmp;
                return root;
            }
            p = p->next;
        }
        ListNode *tmp = new ListNode(val);
        p->next = tmp;
        //tmp->next = root;
        tmp->next = NULL;
        return root;
    }
};

题目中说是环形链接,但是实际返回返回环形链表在牛客网却通不过,而且觉得数组作用不大。

2.删除单链表中的一个节点

给出头节点和被删除的数字

class Remove {
public:
    ListNode* removeNode(ListNode* pHead, int delVal) {
        
        ListNode* pre=pHead;
        ListNode* cur=pHead->next;
        if(delVal==pre->val)
        {
            pHead=cur;
            delete pre;
            return pHead;
        }
        while(cur!=NULL)
        {
            if(delVal==cur->val)
            {
                pre->next=cur->next;
                delete cur;
                return pHead;
            }
            pre=cur;
            cur=cur->next;
        }
        return pHead;
    }
};

3.链表的分化

小的元素放前面,大的放后面

class Divide {
public:
    ListNode* listDivide(ListNode* head, int val) {
        
        ListNode small(0);//记得分配内存
        ListNode big(0);
        ListNode *cur=head;
        ListNode *psmall=&small,*pbig=&big;
        while(cur)
        {
            if(val>=cur->val)
            {
                psmall->next=cur;
                psmall=psmall->next;
            }
            else
            {
                pbig->next=cur;
                pbig=pbig->next;
            }
            cur=cur->next;
        }
        psmall->next=big.next;
        pbig->next=NULL;
        return small.next;
    }
};

4.链表k逆序

方法一

每k个元素逆序一下

class KInverse {
public:
    ListNode* inverse(ListNode* head, int k) {
        
        if(head==NULL||k<2)
            return head;
        ListNode* p=head;
        int count=0;
        while(p!=NULL)
            {
            count++;
            p=p->next;
        }
        ListNode* node=new ListNode(0);
        ListNode* pre=node;
        node->next=head;
        ListNode* cur=head;
        ListNode* temp=head->next;
        for(int i=0;i<count/k;i++)
            {
            for(int j=0;j<k-1;j++)
                {
                cur->next=temp->next;
                temp->next=pre->next;
                pre->next=temp;
               // pre=temp;
                temp=cur->next;
            }
            pre=cur;
            cur=cur->next;
            temp=cur->next;
        }
        return node->next;
         
    }
};

方法二

class KInverse {
public:
    ListNode* inverse(ListNode* head, int k) {
        
        if(head==NULL||k<2)
            return head;
        ListNode* p=head;
        int count=0;
        while(p!=NULL)
        {
            count++;
            p=p->next;
        }
        ListNode* root=new ListNode(0);
        p = root;
        int cnt = (count % k) ? (count-(count%k)-1) : (count-1);
        for(int i=0;i<=cnt;i++){
            ListNode *node = new ListNode(head->val);//头插法建立链表
            node->next = p->next;
            p->next = node;
            if ((i+1)%k==0) {//移动k的位置
                int j = k;
                while (j--) {
                    p = p->next;
                }
            }
            ListNode *tmp = head;
            head = head->next;
            delete tmp;
        }
        p->next = head;
        return root->next;
         
    }
};

5.删除指定值

class ClearValue {
public:
    ListNode* clear(ListNode* head, int val) {
        
        ListNode* pre=new ListNode(0);
        ListNode* cur=pre;
        while(head)
        {
            if(val!=head->val)
            {
               cur->next=head;
               cur=cur->next;
            } else {
                ListNode *tmp = head;
                head=head->next;
                delete tmp;
                continue;
            }
            head=head->next;
        }
        cur->next=NULL;
        return pre->next;
    }
};

6.判断回文

方法一

使用一个栈

class Palindrome {
public:
    bool isPalindrome(ListNode* pHead) {
        
        stack<int> s;
        int x;
        ListNode* p=pHead;
        ListNode* cur=pHead;
        if(pHead==NULL||pHead->next==NULL)
            return true;
        while(p){
            s.push(p->val);
            p=p->next;    
        }
        p=pHead;
        while(p){
            x=s.top();
            if(p->val!=x)
                return false;
            s.pop();
            p=p->next;
        }
        return true;
         
    }
};

方法二

使用vector数组

class Palindrome {
public:
    bool isPalindrome(ListNode* pHead) {
      
        vector<int> vec;
        int x;
        ListNode* p=pHead;
        ListNode* cur=pHead;
        if(pHead==NULL||pHead->next==NULL)
            return true;
        while(p){
            vec.push_back(p->val);
            p=p->next;    
        }
        int i = 0;
        int j = vec.size() - 1;
        while(i<=j){
            if (vec[i] == vec[j]) {
                ++i;
                --j;
                continue;
            }
            return false;
        }
        return true;
         
    }
};

方法三

不需要额外空间,直接逆转后半部分链表

class Palindrome {
public:
    bool isPalindrome(ListNode* pHead) {
       
        vector<int> vec;
        int x;
        ListNode* p=pHead;
        ListNode* cur=pHead;
        if(pHead==NULL||pHead->next==NULL)
            return true;
        int len = 0;
        while(p){
            vec.push_back(p->val);
            p=p->next;
            ++len;
        }
        int i = 0;
        p = pHead;
        while(p){
            if (i >= len/2) {
                //逆转
                ListNode* p1 = p->next;
                p->next = NULL;
                while (p1) {
                    ListNode* tmp = p1->next;
                    p1->next = p;
                    p = p1;
                    p1 = tmp;
                }
                break;
            }
            ++i;
            p = p->next;
        }
        ListNode*head = pHead;
        ListNode*end = p;
        while(head&&end){
            if (head->val == end->val) {
                head = head->next;
                end = end->next;
                continue;
            }
            return false;
        }
        return true;
         
    }
};

7.复制复杂链表


struct RandomListNode {
    int label;
    struct RandomListNode *next, *random;
    RandomListNode(int x) :
            label(x), next(NULL), random(NULL) {
    }
};

class Solution {
public:
    RandomListNode* Clone(RandomListNode* pHead)
    {
        if(!pHead) return NULL;
        RandomListNode* cur=pHead;
        while(cur)
        {
            RandomListNode* node=new RandomListNode(cur->label);
            node->next=cur->next;
            cur->next=node;
            cur=node->next;
        }
        cur=pHead;
        RandomListNode* fol=cur->next;
        while(cur)
        {
            if(cur->random==NULL) fol->random=NULL;
            else fol->random=cur->random->next;//指向random指针的下个节点
            cur=fol->next;//等价于cur->next->next;
            fol=cur->next;//等价于fol->next->next;
        }
        cur=pHead;
        RandomListNode* pre=cur->next;
        //RandomListNode* fol1=pre;
        fol=pre;//这里用老指针新指针都行!!
        while(cur)
        {
            if(cur->next->next)
            {
                
            cur->next=fol->next;//必须先维持旧链表
            fol->next=cur->next->next;//才能建立新链表
            }
            else
            {
                
                fol->next=NULL;//这里两者的先后顺序无区别
                cur->next=NULL;
            }
            
            cur=cur->next;//这里也是两者的先后顺序无区别;
            fol=fol->next;
        }
        return pre;
    }
};

8.链表判环

判断链表是否有环,并且返回入环节点的值

class ChkLoop {
public:
    int chkLoop(ListNode* head, int adjust) {
        
        if(head==NULL||head->next==NULL) return -1;
        ListNode* p1=head;
        ListNode* p2=head;
        //while(p2->next&&p2->next->next)
        while(p2&&p2->next)
        {
            p1=p1->next;
            p2=p2->next->next;
            if(p1==p2)
            {
                p2=head;
                while(p2!=p1)
                {
                    p2=p2->next;
                    p1=p1->next;
                }
                return p2->val;
            }

        }
        return -1;
    }
};

9.无环单链表相交练习

方法一

先走多出来的长度

class CheckIntersect {
public:
    bool chkIntersect(ListNode* headA, ListNode* headB) {
        
        if(!headA||!headB) return 0;
        ListNode* pa=headA;
        ListNode* pb=headB;
        int ia=0,ib=0;
        while(pa)
        {
            pa=pa->next;
            ++ia;
        }
        while(pb)
        {
            pb=pb->next;
            ++ib;
        }
        pa=headA;
        pb=headB;
        if(ia>ib)
        {
            //int n=ia-ib;
            //while(n)
            int n=0;
            while(n<(ia-ib+1))
            {
                pa=pa->next;
                //--n
                ++n;
            }
            while(pa&&pb)
            {
                if(pa==pb)
                    return true;
                else
                {
                    pa=pa->next;
                    pb=pb->next;
                }
            }
            return false;
        }
        else
        {
            //int n=ib-ia;
            //while(n)
            int n=0;
            while(n<(ib-ia+1))
            {
                pb=pb->next;
                //--n;
                ++n;
            }
            while(pa&&pb)
            {
                if(pa==pb)
                    return true;
                else
                {
                    pa=pa->next;
                    pb=pb->next;
                }
            }
            return false;
        }
    }
};

方法二

直接判断有没有重复的节点即可

class ChkLoop {
public:
    int chkLoop(ListNode* head, int adjust) {
     
        set<ListNode*> tmp_set;
        while(head) {
            if (tmp_set.count(head)) {
                return head->val;
            }
            tmp_set.insert(head);
            head = head->next;
        }
        return -1;
    }
};

10.有环单链表相交

先找到入环节点,然后判断这两个入环节点是否一样

class ChkIntersection {
public:
    bool chkInter(ListNode* head1, ListNode* head2, int adjust0, int adjust1) {
        
        ListNode* cy1=entry(head1);
        ListNode* cy2=entry(head2);
        if(cy1==cy2) return true;//即如果在入环之前前相交,则入环节点必定相等,
        //如果有不同的入环节点,则遍历cy1/cy2,则必定等于另一个,否则没相交;
        ListNode* trycy1=cy1->next;
        while(trycy1!=cy1)
        {
            if(trycy1==cy2)
                return true;
            trycy1=trycy1->next;
        }
        return false;
    }
    ListNode* entry(ListNode *&head)
    {
        ListNode* first=head;
        ListNode* slow=head;
        while(first&&first->next)
        {
            first=first->next->next;
            slow=slow->next;
            if(first==slow)
            {
                first=head;
                while(first!=slow)
                {
                    first=first->next;
                    slow=slow->next;
                }
                return first;
            }
        }
        return NULL;
    }
};

11.单链表相交判断

分为无环和有环两种来判断

class ChkIntersection {
public:
    bool chkInter(ListNode* head1, ListNode* head2, int adjust0, int adjust1) {
        
        if(head1==NULL||head2==NULL) return false;
        ListNode* cy1=checkcyc(head1);
        ListNode* cy2=checkcyc(head2);
        if(cy1&&cy2)
        {
            if(cy1==cy2) return true;
            ListNode* trycy1=cy1->next;
            while(trycy1!=cy1)
            {
                if(trycy1==cy2)
                    return true;
                trycy1=trycy1->next;
            }
            return false;
        }
        //要不都有环,而且是同一个环;要不都没有环;
        else
        {
            return nocyccut(head1,head2);
        }
    }
    //判断无环时是否相交
     bool nocyccut(ListNode*& head1, ListNode*& head2)
     {
        ListNode* p=head1;
        ListNode* q=head2;
        while(p->next!=NULL)
            p=p->next;
        while(q->next!=NULL)
            q=q->next;
        if(p==q)
            return true;
        else
            return false;
     }
    //判断有无环
    ListNode* checkcyc(ListNode *&head)
    {
        ListNode* first=head;
        ListNode* slow=head;
        while(first&&first->next)
        {
            first=first->next->next;
            slow=slow->next;
            if(first==slow)
            {
                first=head;
                while(first!=slow)
                {
                    first=first->next;
                    slow=slow->next;
                }
                return first;
            }
        }
        return NULL;//这里必须存在,少一个return 编译不通过,可能逻辑上没什么问题;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值