数据结构和算法 leetcode链表刷题007

链表数据结构刷题

leetcode206: Reverse Linked List 将链表反序

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        //创建三个指针
        ListNode *pre=NULL;
        ListNode *curr=head;
        if(head==NULL){
            return head;
        }
        ListNode *Next=curr->next;
        while(Next!=NULL){
            ListNode *temp=Next->next;
            curr->next=pre;
            Next->next=curr;
            pre=curr;
            curr=Next;
            Next=temp;
        }
        return curr;
    }
};

时间复杂度为O(n);


leetcode83:Remove Duplicates from Sorted List 删除链表中的重复元素

ListNode* deleteDuplicates(ListNode* head) {
        //时间复杂度为o(n) 空间复杂度为O(1)的算法的实现
        ListNode *temp;
        ListNode* returnhead=head;
        if(head==NULL){
            return NULL;
        }
        while(head->next!=NULL){
            if(head->val == head->next->val){
                temp=head->next;
                head->next=head->next->next;
                delete temp;
            }
            else{
                head=head->next;}
        }
        return returnhead;
    }

leetcode86:选取链表中的partion:将小于partion的值放在链表的开头,大于partion的值放在链表的后半部分

class Solution {
public:
    ListNode* partition(ListNode* head, int x) {
       //没有空间限制的代码  也就是不考虑空间复杂度的情况
        ListNode *curr=head;
        ListNode *less=new ListNode(-1);
        ListNode *more=new ListNode(-1);
        ListNode *l=less;
        ListNode *m=more;
        if(head==NULL||head->next==NULL){
            return head;
        }
        while(curr!=NULL){
            if(curr->val<x){
                l->next=curr;
                l=l->next;
            }
            else{
                m->next=curr;
                m=m->next;
            }
            curr=curr->next;
        }
        l->next=more->next;
        m->next=NULL;
        return less->next;
    }
};

时间复杂度为O(n),空间复杂度为O(n)

算法改进:空间复杂度为O(1)的算法;需要注意边界条件,还是采用两个指针的方式;

class Solution {
public:
    ListNode* partition(ListNode* head, int x) {
        //考虑到空间复杂度的使用,使用O(1)的空间复杂度
        //添加两个头结点
        ListNode *first=new ListNode(0);
        first->next=head;
        ListNode *p=first;
        ListNode *q=p->next;//设置好两个指针变量;
        while(q!=NULL&&q->val<x){
            p=p->next;
            q=q->next;
        }
        while(q!=NULL){
            ListNode *temp=q->next;
            if(temp==NULL){
                break;
            }
            if(temp->val>=x){
                q=q->next;
            }
            else{
                q->next=temp->next;
                temp->next=p->next;
                p->next=temp;
                p=p->next;
            }
        }
        return first->next;
        
    }
};

leetcode 82,关于leetcode83的改进

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* deleteDuplicates(ListNode* head) {
    //     //递归的思想来解决问题
    //     if(head==NULL||head->next==NULL){
    //         return head;
    //     }
    //     ListNode* p=head->next;
    //     if(p->val!=head->val){
    //         head->next=deleteDuplicates(p);
    //         return head;
    //     }
    //     else{
    //         //找到第一个不相等的结点
    //         while(p&&p->val==head->val){
    //             p=p->next;
    //         }
    //         return deleteDuplicates(p);
    //     }
    // }
        
    //不使用递归的方式
        //使用一个头结点的指针
        if(head==NULL || head->next==NULL)
            return head;
        ListNode* node=new ListNode(-1);
        node->next=head;
        ListNode* re=node;
        ListNode *curr=head;//用于遍历的指针
       while(curr->next!=NULL){
            if(curr->next->val!=curr->val){
                if(node->next==curr)
                    node=curr;
                else
                    node->next=curr->next;
            }
            curr=curr->next;
        }
        if(node->next!=curr)
            node->next=curr->next;
        
        return re->next;
    }
};

leetcode86: 将链表进行排序,将小于x的链接结点放置在链表的前面,将大于x的链接结点放置在其后面;

使用两个指针来进行模拟,然后再将两个结点合并;

扫描二维码关注公众号,回复: 1546729 查看本文章
class Solution {
public:
    ListNode* partition(ListNode* head, int x) {
        //题目的意思 就是将相应的代码所有值小于相应值x的结点都放置到器前面,将所有的值大于x都放置到相应的后面
        //通过两个链表 先分开,再合并
        ListNode *list1=new ListNode(-1);
        ListNode *list2=new ListNode(-1);
        ListNode* head2=list2;
        ListNode* head1=list1;
        if(head==NULL||head->next==NULL){
            return head;
        }
        while(head!=NULL){
            if(head->val<x){
                list1->next=head;
                head=head->next;
                list1=list1->next;
                list1->next=NULL;
            }
            else{
                list2->next=head;
                head=head->next;
                list2=list2->next;
                list2->next=NULL;
            }
              
        }
        list1->next=head2->next;
        return head1->next;
    }
};

链表加法:

class Solution {
public:
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        //思路很简单将两个结点进行相加,然后将链表反转即可
        if(l1==NULL){
            return l2;
        }
        else if(l2==NULL){
            return l1;
        }
        int cnt=0;
        ListNode *ans=new ListNode(-1);
        ListNode *head=ans;
        while(l1!=NULL&&l2!=NULL){
            int num=(l1->val+l2->val+cnt)%10;
            cnt=(l1->val+l2->val+cnt)/10;
            ListNode *temp=new ListNode(num);
            ans->next=temp;
            ans=ans->next;
            l1=l1->next;
            l2=l2->next;
        }
        if(l1!=NULL){
            while(l1!=NULL){
            int num=(l1->val+cnt)%10;
            cnt=(l1->val+cnt)/10;
            ListNode *temp=new ListNode(num);
            ans->next=temp;
            ans=ans->next;
            l1=l1->next;
            }
        }
        if(l2!=NULL){
            while(l2!=NULL){
            int num=(l2->val+cnt)%10;
            cnt=(l2->val+cnt)/10;
            ListNode *temp=new ListNode(num);
            ans->next=temp;
            ans=ans->next;
            l2=l2->next;
            }
        }
        if(cnt==1){
            ans->next=new ListNode(1);
        }
        return head->next;
    }
};


leetcode21:将两个有序链表进行merge,使其任然有序(通过递归的方式来构建,或者使用新的存储空间);


ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        //将两个链表进行连接
        //一种使用递归的方式
        if(l1==NULL){
            return l2;
        }
        if(l2==NULL){
            return l1;
        }
        ListNode* head=new ListNode(-1);
        ListNode* head2=head;
        if(l1->val<l2->val){
            head->next=l1;
            head=head->next;
            head->next=mergeTwoLists(l1->next,l2);
        }
        else{
            head->next=l2;
            head=head->next;
            head->next=mergeTwoLists(l1,l2->next);
        }
        return head2->next;
    }


leetcode23 合并多个链表的方式:比较难 需要采用的是优先队列来保存结点

leetcode24 Swap Nodes in Pairs 交换两个结点成对

多个指针穿针引线,注意边界条件等

ListNode* swapPairs(ListNode* head) {
        if(head==NULL){
            return NULL;
        }
        if(head->next==NULL){
            return head;
        }
        ListNode* pre=new ListNode(-1);
        ListNode* re=pre;
        ListNode* curr=head;
        // ListNode* Next=curr->next;
        while(curr->next!=NULL){
            ListNode* Next=curr->next;
            ListNode* temp=Next->next;
            pre->next=Next;
            Next->next=curr;
            curr->next=temp;
            pre=curr;
            curr=temp;
            if(curr==NULL){
                break;
            }
        }
        return  re->next;
    }


leetcode148 对链表的排序(和数组中的排序的基本思想是一样的 但是在链表实现的时候归并排序可以是原址排序)

ListNode* sortList(ListNode* head) {
        //使用链表的排序,使用mergesort采用的是的排序的方式 将在两个结点的中点开始切分
        
        if(head==NULL){
            return NULL;
        }
        if(head->next==NULL){
            return head;
        }
        int size=get_list_size(head);
        
        ListNode* mid=reach_mid(head,size/2-1);
        ListNode* right=mid->next;
        mid->next=NULL;
        ListNode* l=sortList(head);
        ListNode* r=sortList(right);
        return merge(l,r);
        
        
    }
    int get_list_size(ListNode* head){
        int i=0;
        while(head!=NULL){
            i++;
            head=head->next;
        }
        return i;
    }
    ListNode* reach_mid(ListNode* head,int step){
        for(int i=0;i<step;i++){
            head=head->next;
        }
        return head;
    }
    ListNode* merge(ListNode* left,ListNode* right){
        if(left==NULL){
            return right;
        }
        if(right==NULL){
            return left;
        }
        ListNode* head=new ListNode(-1);
        ListNode* ans=head;
        if(left->val<right->val){
            head->next=left;
            head=head->next;
            head->next=merge(left->next,right);
        }
        else{
            head->next=right;
            head=head->next;
            head->next=merge(left,right->next);
        }
        return ans->next;
    }
    

leetcode160:

求两个链表的公共结点的方式:

A:          a1 → a2
                   ↘
                     c1 → c2 → c3
                   ↗            
B:     b1 → b2 → b3

ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        //只能说都好强啊, 通过走两轮来进行达到终点
        ListNode *curr1=headA;
        ListNode *curr2=headB;
        while(curr1!=curr2){
            curr1=curr1?curr1->next:headB;
            curr2=curr2?curr2->next:headA;
        }
        return curr1;
    }

leetcode328:将奇数和偶数的链表分离然后重新merge

ListNode* oddEvenList(ListNode* head) {
        //肯定是使用两个指针的方式
        //一个奇数指针,一个偶数指针
        if(head==NULL||head->next==NULL){
            return head;
        }
        ListNode* first=head;
        ListNode* second=head->next;
        ListNode* cur=second;
        while(second!=NULL&&second->next!=NULL){
            first->next=second->next;
            first=first->next;
            second->next=first->next;
            second=second->next;
        }
        first->next=cur;
        return head;
    }


leetcode141:判断一个链表是否有环:

 bool hasCycle(ListNode *head) {
        //判断一个链表是否有环;
        //太强大了,真是聪明啊通过快慢指针的方式来进行操作,一个指针走两步,一个指针走一步,看有没有相交
        //凡是能走到终点就是false
        if(head==NULL){
            return false;
        }
        if(head->next==head){
            return true;
        }
        if(head->next==NULL){
            return false;
        }
        ListNode* fast=head->next;
        ListNode* slow=head;
        while(fast&&fast->next!=NULL){
            if(slow==fast){
                return true;
            }
            slow=slow->next;
            fast=fast->next->next;
            
        }
        return false;
        
    }


leetcode142:判断链表中环的入口:

思路:首先是判断链表是否有环,如果有环,得到环的长度(根据慢指针的步数来判断),然后再利用两个指针,第一个指针先走k步(k为链表中环的长度);代码如下:

ListNode *detectCycle(ListNode *head) {
        //检测环的入口,首先要判断是否有环;
        if(hashCircle(head)){
            //首先得到环的长度,走了多少步相交 就是多少长度的环
            ListNode* fast=head->next;
            ListNode* slow=head;
            int cnt=0;
            while(fast!=slow){
                fast=fast->next->next;
                slow=slow->next;
                cnt++;
            }
            ListNode* first=head;
            ListNode* second=head;
            for(int i=0;i<cnt+1;i++){
                first=first->next;
            }
            //然后让first指针首先前进cnt+1步,然后再和后指针 一步一步的前进直到相交(画图分析一下就行)
            while(first!=second){
                first=first->next;
                second=second->next;
            }
            return first;
        }
        else{
            return NULL;
        }
    }
    bool hashCircle(ListNode* head){
        
        if(head==NULL){
            return false;
        }
        if(head->next==NULL){
            return false;
        }
        ListNode* slow=head;
        ListNode* fast=head->next;
        while(fast!=NULL&&fast->next!=NULL){
            if(slow==fast){
                return true;
            }
            else{
                slow=slow->next;
                fast=fast->next->next;
            }
        }
        return false;
    }


猜你喜欢

转载自blog.csdn.net/hufanglei007/article/details/79495625