其他链表简单题
160. Intersection of Two Linked Lists
Write a program to find the node at which the intersection of two singly linked lists begins.
For example, the following two linked lists:
A: a1 → a2
↘
c1 → c2 → c3
↗
B: b1 → b2 → b3
begin to intersect at node c1.
Notes:
- If the two linked lists have no intersection at all, return null.
- The linked lists must retain their original structure after the function returns.
- You may assume there are no cycles anywhere in the entire linked structure.
- Your code should preferably run in O(n) time and use only O(1) memory.
要求两链表的交集(不是严格意义上的交集,而是从某个结点开始到链表尾元素都相同)。
解法1:分别求两链表的长度len1、len2。然后对齐两链表尾:让指针从较长的链表头部先移动 |len1-len2| 步,然后和较短的链表逐一比较。
解法2:不需要求链表长度。用快慢指针找到两链表尾对齐时,长链表对应短链表头部的位置。然后接下来进行逐一比较了。
网上看了很多版本,包括leetcode的discuss,大多都是找到第一个交点就结束后续检查了,但我觉得这样不是很严谨,万一之后存在结点的值不一样的情况呢?下面的写法啰嗦了一点,但效率不差。
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
if (!headA || !headB) return NULL;
ListNode *pA1 = headA, *pB1 = headB;
ListNode *p2 = NULL, *subHead = NULL;
if (!pA1)
{
p2 = headB;
while (pB1)
{
pB1 = pB1->next;
p2 = p2->next;
}
pA1 = headA;
subHead = p2;
while (p2)
{
if (p2->val != pA1->val) subHead = p2->next;
p2 = p2->next;
pA1 = pA1->next;
}
}
else if (!pB1) {
p2 = headA;
while (pA1)
{
pA1 = pA1->next;
p2 = p2->next;
}
subHead = p2;
pB1 = headB;
while (p2)
{
if (p2->val != pB1->val) subHead = p2->next;
p2 = p2->next;
pB1 = pB1->next;
}
}
return subHead;
}
203. Remove Linked List Elements
删除链表中值为val的元素
class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
if (!head) return head;
ListNode **pp = &head;
while (*pp)
{
if ((*pp)->val == val) {
ListNode *del = *pp;
*pp = del->next;
delete del;
}
else
{
pp = &((*pp)->next);
}
}
return head;
}
};
234. Palindrome Linked List
Given a singly linked list, determine if it is a palindrome.
Follow up:
Could you do it in O(n) time and O(1) space?
判断一个链表是否是回文链表(即顺着读和倒着读是一样的)。
根据回文的特点,首先要找到链表的中点,然后比较对应位置的数是否相等。找中点可以利用快慢指针来实现(慢指针跑一步,快指针就跑两步,当快指针走完时慢指针就到达链表中点了)。然后很容易想到栈先进后出的特点,把慢指针每走一步的值都压进栈,最后栈中存入的是链表前半部分的值。之后就可以和链表后半部分的值进行顺序比较判断是否回文了。
但是这道题Follow Up让我们用O(1)的空间,显然上述上述方法不能达到要求,那么不能使用栈那应该怎么做呢?我们利用的是栈先进后出的特点,如果把链表后半部分进行反转也可以达到相同的目的。之后我们把前半部分、后半部分链表按顺序比较即可判断是否回文了:
bool isPalindrome(ListNode* head) {
if (!head || !head->next) return true;
//找链表中点
ListNode *slow = head, *fast = head;
while (fast->next && fast->next->next)
{
slow = slow->next;
fast = fast->next->next;
}
//逆序后半部分
ListNode *subHead = slow->next ,*cur;
while ((cur = subHead->next))
{
subHead->next = cur->next;
cur->next = slow->next;
slow->next = cur;
}
//比较
ListNode *p = head;
while (slow->next)
{
if (p->val != slow->next->val) return false;
p = p->next;
slow = slow->next;
}
return true;
}
237. Delete Node in a Linked List
Write a function to delete a node (except the tail) in a singly linked list, given only access to that node.
Supposed the linked list is 1 -> 2 -> 3 -> 4 and you are given the third node with value 3, the linked list should become 1 -> 2 -> 4 after calling your function.
删除一个链表中给定的结点(除尾结点外),唯一的参数就是要删除的那个结点。
void deleteNode(ListNode* node) {
node->val = node->next->val;
ListNode *del = node->next;
node->next = node->next->next;
delete del;
}