返回链表中倒数第K个节点
题目描述 链接:倒数第K个节点
实现一种算法,找出单向链表中倒数第 k 个节点。返回该节点的值。
注意:本题相对原题稍作改动
示例:
输入: 1->2->3->4->5 和 k = 2
输出: 4
说明:
给定的 k 保证是有效的。
这道题我们可以用快慢指针的方式来解决,这里的快慢指针不是fast走两步,或者slow走一步的那种快慢指针,而是快指针先走K步,走完之后在让慢指针走,为什么这样做,因为我们这样做先让两个指针拉开K步的差距,让两个指针同时走,等到快指针走完链表最后,走完链表,最后slow就距离链表尾部就差k个距离,因为他们两个之间的距离是恒等不变的。
下面画图来看看
下面是代码
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
typedef struct ListNode ListNode;
int kthToLast(struct ListNode* head, int k){
ListNode* fast = head;
ListNode* slow = head;
for(int i = 0;i<k;i++)
{
fast = fast->next;
}
while(fast != NULL)
{
fast = fast->next;
slow = slow->next;
}
return slow->val;
}
链表的回文结构
链表的回文
描述
对于一个链表,请设计一个时间复杂度为O(n),额外空间复杂度为O(1)的算法,判断其是否为回文结构。
给定一个链表的头指针A,请返回一个bool值,代表其是否为回文结构。保证链表长度小于等于900。
测试样例:
1->2->2->1
返回:true
这道题我们的思路是先找到链表的中点,在反转链表中间节点后面的部分,最后让两个链表一个从中间节点开始,另一个从头节点开始,同时往后面遍历,当从中间节点往后遍历为空的时候就结束。这里链表分奇数和偶数个的情况,我们这里偶数恰好满足题目要求,返回后一个节点。
下面我们画图来看看
我们链表的反转用的是,改变指针的指向来反转的,下面是思路
代码
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};*/
struct ListNode* find_mid(struct ListNode* head)
{
struct ListNode* fast = head;
struct ListNode* slow = head;
while(fast->next !=NULL && fast)
{
fast = fast->next->next;
slow = slow->next;
}
return slow;
}
struct ListNode* revse_mid(struct ListNode* mid)
{
struct ListNode* p1 = NULL;
struct ListNode* p2 = mid;
struct ListNode* p3 = p2->next;
while(p2)
{
p2->next = p1;
p1 = p2;
p2 = p3;
if(p3 != NULL)
{
p3 = p3->next;
}
}
return p1;
}
class PalindromeList {
public:
bool chkPalindrome(ListNode* A) {
struct ListNode* mid = find_mid(A);
struct ListNode* rervse = revse_mid(mid);
struct ListNode* pcur1 = rervse;
while(A != NULL && pcur1 != NULL)
{
if(A->val != pcur1->val)
{
return false;
}
A = A->next;
pcur1 = pcur1->next;
}
return true;
}
};
相交链表
相交链表
题目描述;
给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null 。
图示两个链表在节点 c1 开始相交:
题目数据 保证 整个链式结构中不存在环。
注意,函数返回结果后,链表必须 保持其原始结构 。
自定义评测:
评测系统 的输入如下(你设计的程序 不适用 此输入):
intersectVal - 相交的起始节点的值。如果不存在相交节点,这一值为 0
listA - 第一个链表
listB - 第二个链表
skipA - 在 listA 中(从头节点开始)跳到交叉节点的节点数
skipB - 在 listB 中(从头节点开始)跳到交叉节点的节点数
评测系统将根据这些输入创建链式数据结构,并将两个头节点 headA 和 headB 传递给你的程序。如果程序能够正确返回相交节点,那么你的解决方案将被 视作正确答案 。
这道题我们采用的方法是,先判断链表中,那个链表是长链表,哪个链表是短链表,在拿长链表的节点数去减短链表的节点数,获得差值,最后让长链表先走差值,走完之后让短链表和长链表一起走,他们相遇的地方就是交点,如果没有就是没有交点
下面是代码
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
typedef struct ListNode listnode;
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
listnode* pcur1 = headA;
listnode* pcur2 = headB;
int leng1 = 0;
int leng2 = 0;
while(pcur1 != NULL)
{
pcur1 = pcur1->next;
leng1++;
}
while(pcur2 != NULL)
{
pcur2 = pcur2->next;
leng2++;
}
if(pcur1 != pcur2)
{
return NULL;
}
listnode* longlist = headA;
listnode* shortlist = headB;
int gap = abs(leng1 - leng2);//取绝对值,长度不可能是负数,假设法第一个链表是长链表,第二个是短链表
if(leng1>leng2)
{
longlist = headA;
shortlist = headB;
}
else
{
longlist = headB;
shortlist = headA;
}
while(gap--)
{
longlist = longlist->next;
}
while(longlist != shortlist)
{
longlist = longlist->next;
shortlist = shortlist->next;
}
return longlist;
}
以上就是本文的内容了,如果有什么错误欢迎指正。