一、题目:输入一个链表的头结点,按照 从尾到头 的顺序返回节点的值。返回的结果用数组存储。
// 链表节点的定义
struct ListNode {
int val;
struct ListNode* next;
};
int* printListReversingly(struct ListNode* head) {
int counter = 0;
struct ListNode* current = head;
// 计算链表长度
while (current != NULL) {
counter++;
current = current->next;
}
// 分配数组内存
int *array = (int*)malloc(counter * sizeof(int));
// 将链表节点值逆序存储在数组中
for (int j = counter - 1; head != NULL && j >= 0; j--) {
array[j] = head->val;
head = head->next;
}
return array;
}
二、题目输入一个链表,输出该链表中倒数第 k 个结点。
解析:为了找到链表中倒数第 k 个节点,可以使用双指针法。具体步骤如下:
- 定义两个指针,一个称为快指针(fast),另一个称为慢指针(slow)。
- 让快指针先走 k 步。
- 然后同时移动快指针和慢指针,直到快指针到达链表尾部。
- 此时慢指针所指向的节点就是倒数第 k 个节点。
struct ListNode* findKthToTail(struct ListNode* head, int k) {
if (head == NULL || k <= 0) {
return NULL; // 输入参数无效,返回空指针
}
struct ListNode* fast = head;
struct ListNode* slow = head;
// 快指针先走 k 步
for (int i = 0; i < k; i++) {
if (fast == NULL) {
return NULL; // 链表长度小于 k,返回空指针
}
fast = fast->next;
}
// 同时移动快指针和慢指针,直到快指针到达链表尾部
while (fast != NULL) {
fast = fast->next;
slow = slow->next;
}
// 此时慢指针所指向的节点就是倒数第 k 个节点
return slow;
}
三、题目:定义一个函数,输入一个链表的头结点,反转该链表并输出反转后链表的头结点。(反转链表是一个常见的问题,可以通过遍历链表并逐个改变节点的指针方向来实现。)
struct ListNode* reverseList(struct ListNode* head) {
struct ListNode* prev = NULL;
struct ListNode* current = head;
struct ListNode* nextNode = NULL;
while (current != NULL) {
// 保存当前节点的下一个节点
nextNode = current->next;
// 反转当前节点的指针方向
current->next = prev;
// 更新prev和current指针
prev = current;
current = nextNode;
}
// prev指向反转后的链表头
return prev;
}
四、题目:给定一个链表,若其中包含环,则输出环的入口节点。若其中不包含环,则输出null
。(快慢指针法)
struct ListNode* detectCycle(struct ListNode* head) {
if (head == NULL || head->next == NULL) {
return NULL; // 链表为空或只有一个节点时,不存在环
}
// 定义快慢指针
struct ListNode* slow = head;
struct ListNode* fast = head;
// 判断是否存在环
while (fast != NULL && fast->next != NULL) {
slow = slow->next;
fast = fast->next->next;
if (slow == fast) {
// 快慢指针相遇,说明存在环
// 将慢指针重新指向链表头,然后快慢指针以相同速度移动,相遇点即为环的入口节点
slow = head;
while (slow != fast) {
slow = slow->next;
fast = fast->next;
}
return slow; // 返回环的入口节点
}
}
return NULL; // 链表中不存在环
}
五、题目:输入两个递增排序的链表,合并这两个链表并使新链表中的结点仍然是按照递增排序的。
// 合并两个递增排序的链表
struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2) {
// 创建一个哑结点作为合并后链表的头结点
struct ListNode* dummy = (struct ListNode*)malloc(sizeof(struct ListNode));
dummy->val = 0;
dummy->next = NULL;
// 使用指针curr来遍历合并后的链表
struct ListNode* curr = dummy;
// 循环直到其中一个链表遍历完成
while (l1 != NULL && l2 != NULL) {
if (l1->val < l2->val) {
// 将l1的结点加入合并后链表
curr->next = l1;
l1 = l1->next;
} else {
// 将l2的结点加入合并后链表
curr->next = l2;
l2 = l2->next;
}
// 移动curr指针到新加入的结点
curr = curr->next;
}
// 如果其中一个链表还有剩余结点,将其直接加入合并后链表
if (l1 != NULL) {
curr->next = l1;
} else {
curr->next = l2;
}
// 保存合并后链表的头结点
struct ListNode* result = dummy->next;
// 释放哑结点的内存
free(dummy);
return result;
}