今天还是更新两个链表题,循序渐进慢慢来
给你两个单链表的头节点 headA
和 headB
,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null
思路:代码中都有注释
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
//若是两个链表中有一个为空,直接返回NULL
if(headA==NULL||headB==NULL)
return NULL;
//定义两个指针来遍历两个链表,求出链表长度,还要找到尾
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++;
}
//此时curA和curB都指向各自链表的尾节点,尾节点若不相等,则返回NULL
if(curA!=curB)
{
return NULL;
}
//开始求第一个交点
//首先要找出较长的那一个链表来
struct ListNode*shortList=headA,*longList=headB;
if(lenA>lenB)
{
shortList=headB;
longList=headA;
}
int gap=abs(lenA-lenB);
//长的走gap步,然后一起走,碰到地址相等就停下来,并返回
while(gap--)
{
longList=longList->next;
}
while(shortList!=longList)
{
shortList=shortList->next;
longList=longList->next;
}
//此时走到地址相等的节点了,返回即可
return longList;
}
给你一个单链表的头节点 head
,请你判断该链表是否为回文链表。如果是,返回 true
;否则,返回 false
。
这个题的思路还是不少的,可以用时间复杂度和空间复杂度来要求,这里就只讲一种时间复杂度为O(n),空间复杂度为O(1)的解法,代码还是比较复杂的,但是思路不是很难。
这里运用了分解的思想,将问题分解为找中点和逆置两个子问题,完成找中点和逆置后,只需要依次比较即可。至于如何找中点和逆置,看下面这篇文章就够了。
反转链表+链表中间节点(leetcode简单)_何以过春秋的博客-CSDN博客
直接把代码搬过来:
struct ListNode* middleNode(struct ListNode* head){
struct ListNode* slow, *fast;
slow = 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 NULL;
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;
}
之后的思路就是比较,若出现一次不相等,则返回false,若全部相等,则返回true
这里其实就是定义出来了两个指针分别指向正常的原来的链表的中点,利用这个中点,将中点后面的元素逆置,比如有一个链表是1 2 3 2 1 那么在定义好节点后,mid指向1 2 3 2 1 的3,rhead指向后面3 2 1 逆置之后的1,然后用head和rhead进行一一比较,从而完成。
bool isPalindrome(struct ListNode* head) {
struct ListNode* mid = middleNode(head);
struct ListNode* rhead = reverseList(mid);
while(head && rhead)
{
if(head->val != rhead->val)
{
return false;
}
else
{
head = head->next;
rhead = rhead->next;
}
}
return true;
};