BM8 链表中倒数最后k个结点
输入一个长度为 n 的链表,设链表中的元素的值为 ai ,返回该链表中倒数第k个节点。
如果该链表长度小于k,请返回一个长度为 0 的链表。
数据范围:0≤n≤1050≤n≤105,0≤ai≤1090≤a**i≤109,0≤k≤1090≤k≤109
要求:空间复杂度 O(n)O(n),时间复杂度 O(n)O(n)
进阶:空间复杂度 O(1)O(1),时间复杂度 O(n)O(n)
思考:
设置双指针,让第一个指针先移动k个长度,然后两个指针一起移动。
当第一个指针移动到最后时,第二个指针指的就是目标节点。
代码:
/**
* struct ListNode {
* int val;
* struct ListNode *next;
* ListNode(int x) : val(x), next(nullptr) {}
* };
*/
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param pHead ListNode类
* @param k int整型
* @return ListNode类
*/
ListNode* FindKthToTail(ListNode* pHead, int k) {
// write code here
ListNode* p1 = pHead;
ListNode* p2 = pHead;
for (int i = 0;i < k;i++) {
if (p1 == nullptr) return nullptr;
p1 = p1->next;
}
while (p1) {
p1 = p1->next;
p2 = p2->next;
}
return p2;
}
};
BM9 删除链表的倒数第n个节点
给定一个链表,删除链表的倒数第 n 个节点并返回链表的头指针
例如,
给出的链表为: 1→2→3→4→51→2→3→4→5, n=2n=2.
删除了链表的倒数第 nn 个节点之后,链表变为1→2→3→51→2→3→5.
数据范围: 链表长度 0≤n≤10000≤n≤1000,链表中任意节点的值满足 0≤val≤1000≤val≤100
要求:空间复杂度 O(1)O(1),时间复杂度 O(n)O(n)
备注:
题目保证 nn 一定是有效的
思考:
代码:
BM10 两个链表的第一个公共结点
输入两个无环的单向链表,找出它们的第一个公共结点,如果没有公共节点则返回空。(注意因为传入数据是链表,所以错误测试数据的提示是用其他方式显示的,保证传入数据是正确的)
数据范围: n≤1000n≤1000
要求:空间复杂度 O(1)O(1),时间复杂度 O(n)O(n)
思考:
如果存在公共链表的话,那么一定存在等长的链表。
因此先将长的链表移动指针,至二者等长的区域,在一起遍历,查看是否相同。
代码:
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};*/
class Solution {
public:
ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) {
ListNode* p1 = pHead1;
ListNode* p2 = pHead2;
int len1 = 0, len2 = 0;
for (;p1;p1 = p1->next) len1++;
for (;p2;p2 = p2->next) len2++;
p1 = pHead1;
p2 = pHead2;
// ListNode* res = new ListNode(0);
if (len1 >= len2) {
for (int i = 0;i< len1-len2;i++) p1 = p1->next;
for (int i = 0;i< len2;i++)
{
if (p1 == p2) return p1;
p1 = p1->next;
p2 = p2->next;
}
}
else {
for (int i = 0;i< len2-len1;i++) p2 = p2->next;
for (int i = 0;i< len1;i++)
{
if (p1 == p2) return p1;
p1 = p1->next;
p2 = p2->next;
}
}
return nullptr;
}
};
BM11 链表相加(二)
假设链表中每一个节点的值都在 0 - 9 之间,那么链表整体就可以代表一个整数。
给定两个这种链表,请生成代表两个整数相加值的结果链表。
数据范围:0≤n,m≤10000000≤n,m≤1000000,链表任意值 0≤val≤90≤val≤9
要求:空间复杂度 O(n)O(n),时间复杂度 O(n)O(n)
思考:
对于两个链表,找到相同长度的子段,二者相加即可
本题难点在于如何进行后续的进位操作,比如:
1-9-3-7 和 6-3
我们选择相同子段,3-7 6-3相加,获得1-9-9-9
使用尾插法得到链表,9-9-9-1
遍历并进位,0-0-0-2
在使用头插法,还原顺序2-0-0-0
代码:
/**
* struct ListNode {
* int val;
* struct ListNode *next;
* ListNode(int x) : val(x), next(nullptr) {}
* };
*/
#include <fstream>
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param head1 ListNode类
* @param head2 ListNode类
* @return ListNode类
*/
ListNode* addInList(ListNode* head1, ListNode* head2) {
// write code here
ListNode* p1 = head1;
ListNode* p2 = head2;
int len1 = 0,len2 = 0;
for (;p1;p1 = p1->next) len1++;
for (;p2;p2 = p2->next) len2++;
p1 = head1;
p2 = head2;
ListNode* res = new ListNode(0);
if (len1 >= len2) {
for (int i = 0;i< len1-len2;i++) p1 = p1->next;
for (int i = 0;i< len2;i++)
{
p1->val += p2->val;
p1 = p1->next;
p2 = p2->next;
}
res->next = head1;
}
else {
for (int i = 0;i< len2-len1;i++) p2 = p2->next;
for (int i = 0;i< len1;i++)
{
p2->val += p1->val;
p1 = p1->next;
p2 = p2->next;
}
res->next = head2;
}
ListNode* cur = new ListNode(0);
ListNode* tt = res->next;
while (tt) {
ListNode* tmp = tt;
tt = tt->next;
tmp->next = cur->next;
cur->next = tmp;
}
ListNode* dd = cur->next;
while (dd) {
if (dd->val >= 10) {
dd->val %= 10;
if (dd->next) dd->next->val += 1;
else {
ListNode* tmp = new ListNode(1);
dd->next = tmp;
tmp->next = nullptr;
tmp->val = 1;
}
}
dd = dd->next;
}
ListNode* ll = cur->next;
ListNode* lastRes = new ListNode(0);
// ListNode* go =lastRes;
while (ll) { // 头插法
ListNode* tmp = ll;
ll = ll->next;
tmp->next = lastRes->next;
lastRes->next = tmp;
}
return lastRes->next;
}
};