链表

简介: 预备知识构建链表——尾插法ListNode * CreateNode(int n) { ListNode *head = NULL, *pnew = NULL, *ptail = NULL; int nu...

预备知识

构建链表——尾插法

ListNode * CreateNode(int n)  {
	ListNode *head = NULL, *pnew = NULL, *ptail = NULL; 
	int num, i = 1;
	while (i <= n)
	{
		pnew = new ListNode(0);
		cout << "输入第" << i << "个结点:" << endl;
		cin >> num;
		pnew->val = num;
		pnew->next = NULL;
		if (head == NULL)
			head = pnew;
		else
		{
			ptail->next = pnew;
		}
		ptail = pnew;
		i++;
	}
	pnew = NULL;
	delete pnew;
	return head;
}

 

 

LeetCode 92

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* reverseBetween(ListNode* head, int m, int n) {
        //需要逆置的总长度
        int change_len = n-m+1;
        //初始化开始逆置的节点前驱
        ListNode *pre_head = NULL;
        //最终转换后的链表头节点
        ListNode *result = head;
        //将head向前移动m-1个位置
        while(head && --m){
            //记录head的前驱
            pre_head=head;
            head=head->next;
        }
        //modify_list_tail指向逆置后的链表尾
        ListNode *modify_list_tail = head;
        ListNode *new_head =NULL;
        //逆置change_len个节点
        while(head && change_len){
            ListNode *next =head->next;
            head->next=new_head;
            new_head=head;
            head=next;
            change_len--;
        }
        //链接逆置后的链表尾与逆置段的后一个节点
        modify_list_tail->next = head;
        //如果pre_head不为空,说明不是从第一个节点开始逆置的
        if(pre_head){
            pre_head->next = new_head;
        }else{
            result=new_head;
        }
        return result;
        
    }
};

 

 

 

LeetCode 21

申请的临时空间只要不和你问题的规模成正比,复杂度就是O(1)。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
       if(l1 == nullptr){
            return l2;
        }
        else if(l2 == nullptr){
            return l1;
        }
        
        ListNode * head = new ListNode(0);
        ListNode * ptr = head;
        while(l1 && l2){
            if(l1->val < l2->val){
                ptr->next = l1;
                l1 = l1->next;
            }else{
                ptr->next = l2;
                l2 = l2->next;
            }
            ptr = ptr->next;
        }
        
        if(l1)ptr->next = l1;
        else if(l2)ptr->next = l2;
        ptr = head;
        head = head->next;
        delete ptr;
        return head;  
    }
};

 

 

 

leetcode  142

 

 

思路一:双指针

这个博客讲得不错:https://blog.csdn.net/zhoufen12345/article/details/76390278

 

思路二:存储访问过的节点(申请了额外空间,并且时间效率不如方法一)

ListNode *detectCycle(ListNode *head) {
        unordered_set<ListNode*> visit;
        ListNode * p = head;
        while(p&&p->next)
        {
            if(visit.find(p)==visit.end())
            {
                visit.insert(p);
                p=p->next;
            }
            else
            {
                return p;
            }
        }
        return NULL;
    }

 

LeetCode 160  

 

思路1:遍历两个链表,求两个链表的长度差x,下次遍历的时候,让长的那个先走x步,之后查看两个链表有没有访问相同节点的时候,如果有,证明有交点。

class Solution {
    public:
        ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
            int len1 = 0,len2 = 0;
            ListNode *pA,*pB;
            pA = headA;
            // 统计第一个链表节点数
            while(pA){
                ++len1;
                pA = pA->next;
            }//while
            pB = headB;
            // 统计第一个链表节点数
            while(pB){
                ++len2;
                pB = pB->next;
            }//while
            pA = headA;
            pB = headB;
            // 长度相等且只一个节点一样
            if(len1 == len2 && pA == pB){
                return pA;
            }//if
            // pA指向长链表 pB指向短链表
            if(len1 < len2){
                pA = headB;
                pB = headA;
            }//if
            // pA,Pb指向相同大小位置的节点上
            int as = abs(len1- len2);
            for(int i = 0;i < as;++i){
                pA = pA->next;
            }//while
            // 比较是不是相交点
            while(pA){
                if(pA == pB){
                    return pA;
                }//if
                pA = pA->next;
                pB = pB->next;
            }//while
            return nullptr;
        }
    };

 

思路2:双指针遍历两个链表,当链表B遍历到尾部时,使其next指向链表A的表头;同理,当链表A遍历到尾部时,使其next指向链表B的表头。如此遍历,有重合就证明有交点。最多遍历 链表A的长度+链表B的长度 即可判断出是否有相交的节点。

 

 class Solution {
    public:
        ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
            ListNode *pA = headA;
            ListNode *pB = headB;
            // 有空链表肯定无交点
            if(pA == nullptr || pB == nullptr){
                return nullptr;
            }//if
            while(pA && pB){
                // 交点
                if(pA == pB){
                    return pA;
                }
                if(pA->next && pB->next){
                    pA = pA->next;
                    pB = pB->next;
                }
                // 到达pA末尾,pB未到达
                else if(!pA->next && pB->next){
                    pA = headB;
                    pB = pB->next;
                }
                // 到达pB末尾,pA未到达
                else if(pA->next && !pB->next){
                    pA = pA->next;
                    pB = headA;
                }
                // 同时到达pA,pB末尾
                else{
                    return nullptr;
                }
            }
        }
    };

 

 

 

LeetCode 86

思路:创建两个指针,小的存一个指针里,大的存另一个,最后将两个链表连接起来。

class Solution {
public:
    ListNode *partition(ListNode *head, int x) {  
        ListNode *leftHead = (ListNode*)malloc(sizeof(ListNode));  
        ListNode *rightHead = (ListNode*)malloc(sizeof(ListNode)); 
        //小的都存lpre后面,其余的都存rpre后面。之后把这俩链接就可以了
        ListNode *lpre = leftHead,*rpre = rightHead;  
        while(head != NULL){  
            if(head->val < x){  
                lpre->next = head;  
                //使得lpre指向head,新的小点都查到lpre后面
                lpre = head;  
            }  
            else{  
                rpre->next = head;  
                rpre = head;  
            }  
            head = head->next;  
        }  
        rpre->next = NULL;  
        lpre->next = rightHead->next;  
        return leftHead->next;  
    }  
};

 

 

 

 

相关文章
|
3月前
|
存储 缓存 C语言
链表修炼指南
链表修炼指南
|
5月前
|
存储
07 链表
07 链表
19 0
|
8月前
|
存储 C++
链表相关问题的实现
链表相关问题的实现
|
10月前
|
存储 索引
关于链表我所知道的
关于链表我所知道的
47 0
|
10月前
|
存储 算法 Java
【JavaOj】链表十连问
【JavaOj】链表十连问
77 0
|
12月前
|
存储 算法 Java
一文带你深入了解链表(C)
📖作者介绍:22级树莓人(计算机专业),热爱编程<目前在c阶段>——目标C++、Windows,MySQL,Qt,数据结构与算法,Linux,多线程,会持续分享学习成果和小项目的 📖作者主页:热爱编程的小K 📖专栏链接:C 🎉欢迎各位→点赞👏 + 收藏💞 + 留言🔔​ 💬总结:希望你看完之后,能对你有所帮助,不足请指正!共同学习交流 🐾 ———————————————— 版权声明:本文为CSDN博主「热爱编程的小K」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/qq_7215744
|
存储 JavaScript 前端开发
链表
链表
71 0
|
存储 API
链表——初识链表
链表是一种物理存储单元上非连续、非顺序的存储结构,其物理结构不能只管的表示数据元素的逻辑顺序,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。
82 0
链表——初识链表

热门文章

最新文章