前言:基于对链表初步理解及经典算法题(1)(具体内容参考往期博客),我们继续完成几道链表经典算法题
1,输入一个链表,输出该链表中倒数第k个结点
面试题 02.02. 返回倒数第 k 个节点 - 力扣(LeetCode)
实现一种算法,找出单向链表中倒数第 k 个节点。返回该节点的值。
注意:本题相对原题稍作改动
示例:
输入: 1->2->3->4->5 和 k = 2 输出: 4
说明:
给定的 k 保证是有效的。
思路
快慢指针 快必慢多走k步
参考代码
int kthToLast(struct ListNode* head, int k)
{
struct ListNode* fast = head, *slow = head;
//快指针先走k步
while(k--)
{
fast = fast->next;
}
//同时走
while(fast)
{
slow = slow->next;
fast = fast->next;
}
return slow->val;
}
2,链表的回文结构
链表的回文结构_牛客题霸_牛客网 (nowcoder.com)
描述
对于一个链表,请设计一个时间复杂度为O(n),额外空间复杂度为O(1)的算法,判断其是否为回文结构。
给定一个链表的头指针A,请返回一个bool值,代表其是否为回文结构。保证链表长度小于等于900。
测试样例:
1->2->2->1
返回:true
思路
先找到中间节点
再将中间节点往后反转链表
最后将头结点与中间节点依次比较,若值相同则依次比较下一个节点的值
参考代码
#include <algorithm>
class PalindromeList {
public:
struct ListNode* middleNode(struct ListNode* head)
{
struct ListNode* slow = head;
struct ListNode* fast = head;
while(fast && fast->next)
{
slow = slow->next;
fast = fast->next->next;
}
return slow;
}
struct ListNode* reverseList(struct ListNode* head)
{
if(head == NULL)
{
return head;
}
struct ListNode* n1,*n2,*n3;
n1 = NULL,n2 = head,n3 = n2->next;
while(n2)
{
n2->next = n1;
n1 = n2;
n2 = n3;
if(n3)
{
n3 = n3->next;
}
}
return n1;
}
bool chkPalindrome(ListNode* A)
{
// write code here
struct ListNode* mid = middleNode(A);
struct ListNode* rmid = reverseList(mid);
while(rmid && A)
{
if(rmid->val != A->val)
{
return false;
}
rmid = rmid->next;
A = A->next;
}
return true;
}
};
注:找中间节点及反转链表相关函数参照《单链表经典算法-CSDN博客》
3,输入两个链表,找出它们的第一个公共结点
给你两个单链表的头节点 headA
和 headB
,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null
。
图示两个链表在节点 c1
开始相交:
题目数据 保证 整个链式结构中不存在环。
注意,函数返回结果后,链表必须 保持其原始结构 。
自定义评测:
评测系统 的输入如下(你设计的程序 不适用 此输入):
intersectVal
- 相交的起始节点的值。如果不存在相交节点,这一值为0
listA
- 第一个链表listB
- 第二个链表skipA
- 在listA
中(从头节点开始)跳到交叉节点的节点数skipB
- 在listB
中(从头节点开始)跳到交叉节点的节点数
评测系统将根据这些输入创建链式数据结构,并将两个头节点 headA
和 headB
传递给你的程序。如果程序能够正确返回相交节点,那么你的解决方案将被 视作正确答案 。
思路
1,判断是否相交
判断尾指针,注意要用地址判断
2,若相交,找出第一个交点
思路一
A链表的节点依次跟B链表所有节点比较,A某个节点跟B链表某个节点相等,则这个节点即为交点
时间复杂度O(N^2)
思路二
大链表节点数减去小链表节点数 即为多出部分 依次可以借助减数一个一个比较
时间复杂度O(N)
参考代码
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB)
{
struct ListNode * curA = headA,*curB = headB;
int lenA = 1, lenB = 1;
while(curA->next)
{
curA = curA->next;
++lenA;
}
while(curB->next)
{
curB = curB->next;
++lenB;
}
//尾结点不相等就不相交
if(curA != curB)
{
return NULL;
}
//长的先走差距步,再同时走,第一个相交的就是交点
//假设法
int gap = abs(lenA - lenB);
struct ListNode* longList = headA,*shortList = headB;
if(lenB > lenA)
{
longList = headB;
shortList = headA;
}
while(gap--)
{
longList = longList->next;
}
while(longList != shortList)
{
longList = longList->next;
shortList = shortList->next;
}
return longList;
}