2021-09-29每日刷题打卡
力扣——链表
61. 旋转链表
给你一个链表的头节点 head ,旋转链表,将链表每个节点向右移动 k 个位置。
示例 1:
输入:head = [1,2,3,4,5], k = 2
输出:[4,5,1,2,3]
想着一个个把结尾的结点移到头部太麻烦了,因为要找到结尾的结点只能从头部一个个遍历,相当于每移动一个结点就要遍历一遍链表,太慢了,所以我直接把尾部结点和头部结点连在了一起,形成一个环,这样要移动多少给结点,头结点就往前挪:k-链表长度 次就可以了,最后把链表尾部断开,直接返回head。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* rotateRight(ListNode* head, int k) {
ListNode* p, * end;
if (head == NULL)
{
return NULL;
}
else if (head->next == NULL)
{
return head;
}
int num = 1;
p = head;
while (p->next != NULL)
{
p = p->next;
num++;
}
end = p;
end->next = head;
int math = k % num;
int n = num - math-1;
while (n--)
{
head = head->next;
}
end = head->next;
head->next = NULL;
head = end;
return head;
}
};
21. 合并两个有序链表
将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
示例 1:
输入:l1 = [1,2,4], l2 = [1,3,4]
输出:[1,1,2,3,4,4]
用两个结点p,q去维护插入结点的那个链表,一个q.next指向链表的头,一个p直接就是链表的头,然后依次和另一个链表的结点比较,当p的值大于等于结点的值时,就把结点插入p、q之间,然后继续遍历。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
if (l1 == NULL && l2 != NULL)
{
return l2;
}
else if (l2 == NULL && l1 != NULL)
{
return l1;
}
else if (l1 == NULL && l2 == NULL)
{
return NULL;
}
ListNode* p, * q, * o;
int num;
q = (ListNode*)malloc(sizeof(ListNode));
o = l1;
p = l2;
q->val = -100000000;
q->next = l2;
while (q != NULL && l1 != NULL)
{
if (p != NULL)
{
if (p->val <= l1->val)
{
p = p->next;
q = q->next;
}
else
{
o = l1->next;
l1->next = p;
q->next = l1;
p = l1;
l1 = o;
if (q->val == -100000000)
{
l2 = q->next;
}
}
}
else
{
o = l1->next;
l1->next = p;
q->next = l1;
p = l1;
l1 = o;
}
}
return l2;
}
};
面试题 02.07. 链表相交
剑指 Offer 52. 两个链表的第一个公共节点
160. 相交链表
剑指 Offer II 023. 两个链表的第一个重合节点
这四道题题目基本是一模一样的,连代码我都用的是同一个,故把这四题放在一起。
给定两个单链表的头节点 headA 和 headB ,请找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。
图示两个链表在节点 c1 开始相交:
题目数据 保证 整个链式结构中不存在环。
注意,函数返回结果后,链表必须 保持其原始结构 。
示例 1:
输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,1,8,4,5], skipA = 2, skipB = 3
输出:Intersected at ‘8’
解释:相交节点的值为 8 (注意,如果两个链表相交则不能为 0)。
从各自的表头开始算起,链表 A 为 [4,1,8,4,5],链表 B 为 [5,0,1,8,4,5]。
在 A 中,相交节点前有 2 个节点;在 B 中,相交节点前有 3 个节点。
拿一个链表的结点一个个和另一个链表比,如果有相同的就说明有交叉
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
vector<ListNode*>v;
while(headA!=NULL)
{
v.push_back(headA);
headA=headA->next;
}
while(headB!=NULL)
{
for(auto i:v)
{
if(i==headB)
{
return i;
}
}
headB=headB->next;
}
return NULL;
}
};
1721. 交换链表中的节点
给你链表的头节点 head 和一个整数 k 。
交换 链表正数第 k 个节点和倒数第 k 个节点的值后,返回链表的头节点(链表 从 1 开始索引)。
示例 1:
输入:head = [1,2,3,4,5], k = 2
输出:[1,4,3,2,5]
用一个vector容器把链表的各个结点都存进去,通过数组下标交换第k个和倒数第k个的结点,再把他们依次穿起来形成链表,返回那个链表即可。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* swapNodes(ListNode* head, int k) {
if(head==NULL||head->next==NULL)
{
return head;
}
vector<ListNode*>v;
ListNode* p;
while (head != NULL)
{
v.push_back(head);
head = head->next;
}
int left = k - 1, right = v.size() - k;
p = v[left];
v[left] = v[right];
v[right] = p;
for (int i = 0; i < v.size()-1; i++)
{
v[i]->next = v[i + 1];
}
v[v.size() - 2]->next = v[v.size() - 1];
v[v.size() - 1]->next = NULL;
head = v[0];
return head;
}
};