链表刷题总结

class Solution {
public:
    ListNode* ReverseList(ListNode* pHead) {
		ListNode*p1=nullptr;
		ListNode*p2=pHead;//定义p1为空指针,p2为开始节点
		while(p2){//循环结束是p2为空
		ListNode*temp=p2;//保存p2
		p2=p2->next;//p2先走,防止反转后失去下一个节点
		temp->next=p1;//原p2的位置反转
		p1=temp;//反转后p1去原p2的位置
		}
		return p1;//最后返回的是p1,因为p2为空了
    }
};

 

class Solution {
public:
    /**
     * 
     * @param head ListNode类 
     * @param m int整型 
     * @param n int整型 
     * @return ListNode类
     */
    ListNode* reverseBetween(ListNode* head, int m, int n) {
        // write code here
        ListNode* res = new ListNode(-1);//建立头节点,不然首节点反转的话返回节点得重新赋值
        res->next = head;
        //前序节点
        ListNode* pre = res;//在头节点
        //当前节点
        ListNode* cur = head;//在首节点
        //找到m
        for(int i = 1; i < m; i++){//令cur到链表的m位置,pre到链表的m-1位置
            pre = cur;
            cur = cur->next;
        }
        //从m反转到n(反转一次相当于m和m+1反转)
        for(int i = m; i < n; i++){//反转方式为(以m与m+1节点反转为例)
            ListNode* temp = cur->next;//保存m+1位置节点
            cur->next = temp->next;//m+1节点的下一个节点连到m节点后面
            temp->next = pre->next;//m位置的节点连到原m+1节点后面
            pre->next = temp;//最后把原m+1连到m-1节点后面,完成相邻反转
        }//循环
        //返回去掉表头
        return res->next;
    }
};

 

 

class Solution {
  public:
    /**
     *
     * @param head ListNode类
     * @param k int整型
     * @return ListNode类
     */
    ListNode* reverse(ListNode* head, int m, int n) {
        ListNode* phead = new ListNode(0);
        phead->next = head;
        ListNode* p1 = phead;
        ListNode* p2 = head;
        for (int i = 1; i < m; i++) {
            p1 = p2;
            p2 = p2->next;
        }
        for (int i = m; i < n; i++) {
            ListNode* temp = p2->next;
            p2->next = p2->next->next;
            temp->next = p1->next;
            p1->next = temp;
        }
        return phead->next;
    }//和前面带位置反转一样
    ListNode* reverseKGroup(ListNode* head, int k) {
        if (!head)return nullptr;
        // write code here
        ListNode* point = head;
        //双指针,记录反转区间边界节点的坐标
        int j = 1;
        int i = 1;
        int num=1;
        //记录链表节点的数目
        while (point->next) {
            point=point->next;
            num++;
        }
        for(int i=1;i<=num;i++){
            if (i % k == 0) {//到k,2k,3k节点时停
                head = reverse(head, j, i);//反转区间,注意head需要赋值,因为反转时原首节点变化了
                j = i + 1;//左边界更新
            }
        }
        return head;
    }
};

ListNode* Merge(ListNode* pHead1, ListNode* pHead2) {
        ListNode*p1=pHead1;
		ListNode*p2=pHead2;
		ListNode*point=new ListNode(0);//新建头节点
		ListNode*p=point;
		while(p1&&p2){//都不为空时,一个为空说明要结束比较了
			if(p1->val>p2->val){
				p->next=p2;//后面接小的
				p2=p2->next;//更新比较节点
				p=p->next;//更新位置节点
			}
			else{
				p->next=p1;
				p1=p1->next;
				p=p->next;
			}
		}
		//不为空的直接复制
		if(!p1){
			p->next=p2;
		}
		if(!p2){
			p->next=p1;
		}
		return point->next;
    }

 

ListNode* Merge(ListNode* pHead1, ListNode* pHead2) {
        ListNode* p1 = pHead1;
        ListNode* p2 = pHead2;
        ListNode* point = new ListNode(0);
        ListNode* p = point;
        while (p1 && p2) {
            if (p1->val > p2->val) {
                p->next = p2;
                p2 = p2->next;
                p = p->next;
            } else {
                p->next = p1;
                p1 = p1->next;
                p = p->next;
            }
        }
        if (!p1) {
            p->next = p2;
        }
        if (!p2) {
            p->next = p1;
        }
        return point->next;
    }
    //利用归并排序思想,将容器内二分到只有一个链表,然后再拼接,这样后面拼接的都是有序链表
    ListNode* merge(vector<ListNode*>& lists, int l, int r) {//返回一个链表节点
        if (l > r)return nullptr;
        else if (l == r)return lists[l];//当分到只有一个链表时可以停止了
        int mid = (l + r) / 2;
        ListNode* p1 = merge(lists, l, mid);//记录分开的链表
        ListNode* p2 = merge(lists, mid + 1, r);
        return Merge(p1, p2);//合并

    }
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        return merge(lists, 0, lists.size() - 1);//返回最后合并的链表

    }

 

 

bool hasCycle(ListNode *head) {
        //先判断链表为空的情况
        if(head == NULL) 
            return false;
        //快慢双指针
        ListNode* fast = head; 
        ListNode* slow = head;
        //如果没环快指针会先到链表尾
        while(fast != NULL && fast->next != NULL){ //如果循环条件改为fast==slow的话,开始节点就相等了
            //快指针移动两步
            fast = fast->next->next; //条件判断就是fast->next存在才行
            //慢指针移动一步
            slow = slow->next;
            //相遇则有环 
            if(fast == slow) 
                return true;
        }
        //到末尾则没有环
        return false; 
    }

//判断有没有环,返回相遇的地方
    ListNode* hasCycle(ListNode *head) { 
        //先判断链表为空的情况
        if(head == NULL) 
            return NULL;
        //快慢双指针
        ListNode* fast = head; 
        ListNode* slow = head;
        //如果没环快指针会先到链表尾
        while(fast != NULL && fast->next != NULL){ //如果条件改为相等就需要开始走
            //快指针移动两步
            fast = fast->next->next; 
            //慢指针移动一步
            slow = slow->next; 
            //相遇则有环
            if(fast == slow) 
                //返回相遇的地方
                return slow; 
        }
        //到末尾则没有环
        return NULL; 
    }
    
    ListNode* EntryNodeOfLoop(ListNode* pHead) {
        ListNode* slow = hasCycle(pHead);
        //没有环
        if(slow == NULL) 
            return NULL;
        //快指针回到表头
        ListNode* fast = pHead; 
        //再次相遇即是环入口
        while(fast != slow){ 
            fast = fast->next;
            slow = slow->next;
        }
        return slow;
    }

 

ListNode* FindKthToTail(ListNode* pHead, int k) {
        ListNode* fast = pHead; 
        ListNode* slow = pHead;
        //快指针先行k步
        for(int i = 0; i < k; i++){  
            if(fast != NULL)
                fast = fast->next;
            //达不到k步说明链表过短,没有倒数k
            else 
                return slow = NULL;
        }
        //快慢指针同步,快指针先到底,慢指针指向倒数第k个
        while(fast != NULL){ 
            fast = fast->next;
            slow = slow->next;
        }
        return slow;
    }

 

ListNode* removeNthFromEnd(ListNode* head, int n) {
        // write code here
        ListNode*phead=new ListNode(0);//删除的话,需要头节点
        phead->next=head;
        ListNode*p1=phead;
        ListNode*p2=phead;
        for(int i=1;i<=n;i++){
            p2=p2->next;
        }
        p2=p2->next;//多走一步,因为需要删除
        while(p2){
            p2=p2->next;
            p1=p1->next;
        }
        p1->next=p1->next->next;
        return phead->next;
    }

ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) {
        if(!pHead1||!pHead2)return nullptr;
		ListNode*quick=pHead1;
		ListNode*slow=pHead2;
		int res=0;
		while(quick!=slow){
			if(quick->next){
				quick=quick->next;
			}
			else{
				quick=pHead2;
				res++;//指示变量,记录循环找的次数
			}
			if(slow->next){
				slow=slow->next;
			}
			else{
				slow=pHead1;
			}
			if(res==2){
				return nullptr;
			}
		}
		return quick;
    }

bool isPail(ListNode* head) {
        vector<int> nums;
        //将链表元素取出一次放入数组
        while(head != NULL){
            nums.push_back(head->val);
            head = head->next;
        }
        vector<int> temp = nums;
        //准备一个数组承接翻转之后的数组
        reverse(temp.begin(), temp.end());
        for(int i = 0; i < nums.size(); i++){
            //正向遍历与反向遍历相同
            if(nums[i] != temp[i])
                return false;
        }
        return true;
    }

 

 

ListNode* oddEvenList(ListNode* head) {
        // write code here
        if(!head)return nullptr;//为空
        ListNode*p1=head;//记录第一个奇节点
        ListNode*p2=head->next;//记录第一个偶节点
        ListNode*point=p2;//记录奇偶交界处
        while(p2&&p2->next){//p2是快节点,因此用它来判断是否结束
            p1->next=p2->next;//把偶节点的下一个节点(奇)接到上奇节点后
            p1=p1->next;//更新奇节点
            p2->next=p1->next;//新奇节点下一个接到原偶节点
            p2=p2->next;//更新偶节点
        }
        p1->next=point;//奇偶连接
        return head;
    }

 

 ListNode* deleteDuplicates(ListNode* head) {
        //空链表
        if(head == NULL) 
            return NULL;
        //遍历指针
        ListNode* cur = head; 
        //指针当前和下一位不为空
        while(cur != NULL && cur->next != NULL){ 
            //如果当前与下一位相等则忽略下一位
            if(cur->val == cur->next->val) 
                cur->next = cur->next->next;
            //否则指针正常遍历
            else 
                cur = cur->next;
        }
        return head;
    }

 

ListNode* deleteDuplicates(ListNode* head) {
        //空链表
        if(head == NULL) 
            return NULL;
        ListNode* res = new ListNode(0);
        //在链表前加一个表头
        res->next = head; 
        ListNode* cur = res;
        while(cur->next != NULL && cur->next->next != NULL){ //这个条件保证cur后面至少有两个节点
            //遇到相邻两个节点值相同
            if(cur->next->val == cur->next->next->val){ 
                int temp = cur->next->val;
                //将所有相同的都跳过
                while (cur->next != NULL && cur->next->val == temp) 
                    cur->next = cur->next->next;
            }
            else 
                cur = cur->next;
        }
        //返回时去掉表头
        return res->next; 
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值