代码随想录第九期day4 24 两两交换链表中的节点 19 删除链表的倒数第N个节点 02.07链表相交 142 环形链表

代码随想录第九期第四天打卡记录

链表基础:

struct ListNode {
    int val;  //结点上存储元素
    ListNode *next;  //指向下一个节点的指针
    ListNode(int x) : val(x), next(nullptr) {}  //结点的构造函数
};

注意:不写构造函数的话,C++会自动的生成这样的一个构造函数,单数不会生成任何的成员变量。

插入/删除(时间复杂度)查询(时间复杂度)使用场景
数组 O ( n ) O(n) O(n) O ( 1 ) O(1) O(1)数据量固定,频繁查询,较少增删
链表 O ( 1 ) O(1) O(1) O ( n ) O(n) O(n)数据量不固定,频繁增删,较少查询

19 删除链表第N个节点: link

以下部分为 c++相关的测试代码
题目:给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode* dummyHead = new ListNode(0); // 创建虚拟节点
         dummyHead->next = head;  
         ListNode* fast = head; // 快指针
         ListNode* slow = dummyHead;  // 慢指针 
         while(n>0&&fast != NULL){
             fast = fast->next;
             n--;
         }
         while(fast != NULL){
             fast = fast->next;
             slow = slow->next;
         }
         slow->next = slow->next->next;
         return dummyHead->next;

    }
};

203.移除元素 链接: link

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

02.07 链表相交 link

题目要求:给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* getIntersectionNode(ListNode *headA, ListNode *headB) {
        ListNode* curA = headA;
        ListNode* curB = headB;
        int lenA = 0, lenB = 0;
        while(curA != NULL) {  //求链表A的长度
            lenA++;
            curA = curA->next;
        }
        while(curB != NULL) {  //求链表B的长度
            lenB++;
            curB = curB->next;
        }
        curA = headA;
        curB = headB;
        //使得curA为最长链表的头结点,lenA为其长度
        if(lenB > lenA) {
            swap(lenA, lenB);
            swap(curA,curB);
        }
        int gap = lenA - lenB;  //求长度差
        while(gap--) {
            curA = curA->next;  //剔除
        }
        while(curA != NULL) {
            if(curA == curB) {
                return curA;
            }
            curA = curA->next;
            curB = curB->next;
        }
        return NULL;
    }
};

142.环形链表: link

以下部分为 c++相关的测试代码
题目:给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。

不允许修改 链表

输入:head = [3,2,0,-4], pos = 1
输出:返回索引为 1 的链表节点
解释:链表中有一个环,其尾部连接到第二个节点。

输入:head = [1,2], pos = 0
输出:返回索引为 0 的链表节点
解释:链表中有一个环,其尾部连接到第一个节点。

输入:head = [1], pos = -1
输出:返回 null
解释:链表中没有环。

注意:

  • 链表中节点的数目范围在范围 [0, 104] 内
  • -105 <= Node. val <= 105
  • pos 的值为 -1 或者链表中的一个有效索引
    解题思路
  • 证明有环,设置双指针(快慢指针),当快慢指针相遇的时候,代表指针是有环存在的。
  • 寻找节点位置,假设head距离环开始的位置距离为x,
    详解
    假设链表节点位置为x(起始位置为0),相遇点距离起始点的位置为y,链表环内的总长度为y+z
    设置快指针的速度为慢指针速度的两倍
    那么在两个指针相遇的时候满指针走过x+y的距离
    快指针走过 x+y + n(y+z)多走了n圈
    根据两指针相遇时间相同,那么有 2(x+y) = x+y+n(y+z)
    化简可以得到 x+y = (n-1)(y+z) - z
    当n = 1的时候,可以的到 x = z
    那么就是说,当在相交的位置,设置一个从head开始走的指针,那么,相交点的指针只需按照新指针的速度继续往后移动即可得到环形链表入口的位置。
public class Solution{
public ListNode detectCycle(ListNode head){
// 养成习惯,首先需判断出事条件是否满足
if (!head) return head;
// fast and slow poiner
	ListNode* fast = head;
	ListNode* slow = head;
while(fast && fast->next){ // 注意此处需要注意先后
	fast = fast->next->next;
	slow = slow->next;
	if (fast == slow){
	ListNode* index1 = fast;  // 这里只需要保留一个即可
	ListNode* index2 = head;  // 这里设置只想head的指针
	while(index1 != index2){
	index1 = index1->next;
	index2 = index2->next;
}
return index2;
}
	}
	return NULL;
}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值