代码随想录算法训练营第四天| 24. 两两交换链表中的节点 、19.删除链表的倒数第N个节点、面试题 02.07. 链表相交、142.环形链表II

24. 两两交换链表中的节点

文档讲解 : 代码随想录 - 24. 两两交换链表中的节点
状态:再次回顾。

虚拟头结点 + 双指针 (接下来的题目都可以用到双指针,双指针是链表题目中的常客,一般用于辅助判断索引位置)。

此题一定要画图,不然容易乱。

初始时,cur指向虚拟头结点,然后进行如下三步:
三步骤
操作之后,链表如下:
操作后

本题代码(ACM):

#include <iostream>
#include <vector>;
using namespace std;

struct ListNode {
	int val;
	ListNode* next;
	ListNode(int val): val(val), next(NULL) {}
};

ListNode* swapPairs(ListNode* head) {
	ListNode* dummyHead = new ListNode(0); // 设置一个虚拟头结点
	dummyHead->next = head; // 将虚拟头结点指向head,这样方面后面做删除操作
	ListNode* cur = dummyHead;
	while (cur->next != nullptr && cur->next->next != nullptr) {
		ListNode* tmp = cur->next; // 记录临时节点
		ListNode* tmp1 = cur->next->next->next; // 记录临时节点

		cur->next = cur->next->next;    // 步骤一
		cur->next->next = tmp;          // 步骤二
		cur->next->next->next = tmp1;   // 步骤三

		cur = cur->next->next; // cur移动两位,准备下一轮交换
	}
	return dummyHead->next;
}

int main() {
	/*
		输入描述:
		第一行一个整数,表示链表长度。如果n <= 0, 链表为空链表;
		第二行n个整数,表示链表内元素;
	*/
	int n;
	cin >> n;

	ListNode* head = NULL;
	if (n > 0) {
		vector<int> listNode(n);
		for (int i = 0; i < n; i++) cin >> listNode[i];
		head = new ListNode(listNode[0]);
		ListNode* cur = head;
		for (int i = 1; i < n; i++) {
			ListNode* node = new ListNode(listNode[i]);
			cur->next = node;
			cur = cur->next;
		}
		cur->next = NULL;
	}


	head = swapPairs(head);
	ListNode* newCur = head;
	while (newCur != NULL) {
		cout << newCur->val << " ";
		newCur = newCur->next;
	}
	cout << endl;
	return 0;
}
  • 时间复杂度:O(n)
  • 空间复杂度:O(1)

19.删除链表的倒数第N个节点

文档讲解 : 代码随想录 - 19.删除链表的倒数第N个节点
状态:再次回顾。注意快指针得再前进一步,才能使慢指针指向倒数第N个节点前节点。

掌握双指针法后,没啥难度

本题代码(ACM)

#include <iostream>
#include <vector>;
using namespace std;

struct ListNode {
	int val;
	ListNode* next;
	ListNode(int val) : val(val), next(NULL) {}
};

ListNode* removeNthFromEnd(ListNode* head, int n) {
	ListNode* dummyHead = new ListNode(0);
	dummyHead->next = head;
	ListNode* fast = dummyHead->next; // 快指针得前进一步才能让慢指针指向第n个结点前结点
	ListNode* slow = dummyHead;
	while (n-- && fast) {
		fast = fast->next;
	}
	while (fast) {
		slow = slow->next;
		fast = fast->next;
	}
	ListNode* node = slow->next;
	slow->next = node->next;
	delete node;
	head = dummyHead->next;
	delete dummyHead;
	return head;
}

int main() {
	/*
		输入描述:
		第一行一个整数,表示链表长度。如果num <= 0, 链表为空链表;
		第二行num个整数,表示链表内元素;
		第三行一个整数,表示倒数第n个节点。
	*/
	int num;
	cin >> num;

	ListNode* head = NULL;
	if (num > 0) {
		vector<int> listNode(num);
		for (int i = 0; i < num; i++) cin >> listNode[i];
		head = new ListNode(listNode[0]);
		ListNode* cur = head;
		for (int i = 1; i < num; i++) {
			ListNode* node = new ListNode(listNode[i]);
			cur->next = node;
			cur = cur->next;
		}
		cur->next = NULL;
	}

	int n;
	cin >> n;


	head = removeNthFromEnd(head, n);
	ListNode* newCur = head;
	while (newCur != NULL) {
		cout << newCur->val << " ";
		newCur = newCur->next;
	}
	cout << endl;
	return 0;
}

面试题 02.07. 链表相交

文档讲解 : 代码随想录 - 面试题 02.07. 链表相交
状态:再次回顾。

非常经典的双指针题目,得想到链表相连

思路和算法(参考力扣官方题解

本题代码

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        if (headA == NULL || headB == NULL) return NULL;
        ListNode* pA = headA;
        ListNode* pB = headB;
        while (pA != pB) {
            pA = pA == NULL ? headB : pA->next;
            pB = pB == NULL ? headA : pB->next;
        }
        return pA;
    }
};

142.环形链表II

文档讲解 : 代码随想录 - 142.环形链表II
状态:再次回顾。

还是双指针法,链表题目基本离不开双指针法,双指针法起到定位索引作用。
具体解题思路看 代码随想录 - 142.环形链表II

本题代码

class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        ListNode* fast = head;
        ListNode* slow = head;
        while(fast != NULL && fast->next != NULL) {
            slow = slow->next;
            fast = fast->next->next;
            // 快慢指针相遇,此时从head 和 相遇点,同时查找直至相遇
            if (slow == fast) {
                ListNode* index1 = fast;
                ListNode* index2 = head;
                while (index1 != index2) {
                    index1 = index1->next;
                    index2 = index2->next;
                }
                return index2; // 返回环的入口
            }
        }
        return NULL;
    }
};
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值