1、链表中倒数第k个结点
本题考点: 链表,前后指针的使用,边界条件检测 牛客链接
题目描述:
输入一个链表,输出该链表中倒数第k个结点。
示例1
输入:1,{1,2,3,4,5}
返回值:{5}
解题思路:
代码:
class Solution {
public:
ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {
if(nullptr == pListHead)
return nullptr;
ListNode* fast = pListHead;
ListNode* slow = pListHead;
while(k > 0 && fast) //k值有可能不合法
{
fast = fast->next;
k--;
}
while(fast)
{
fast = fast->next;
slow = slow->next;
}
return k > 0 ? nullptr : slow;
}
};
2、反转链表
本题考点: 链表 牛客链接
题目描述:
给定一个单链表的头结点pHead(该头节点是有值的,比如在下图,它的val是1),长度为n,反转该链表后,返回新链表的表头。
数据范围: 0≤n≤1000
要求:空间复杂度 O(1) ,时间复杂度O(n) 。
如当输入链表{1,2,3}时,
经反转后,原链表变为{3,2,1},所以对应的输出为{3,2,1}。
解题思路:
代码:
class Solution {
public:
ListNode* ReverseList(ListNode* pHead) {
//三指针法
if(nullptr == pHead || pHead ->next == nullptr)
return pHead;
ListNode* prev = nullptr, *cur = pHead, *last = cur->next;
while(last)
{
cur->next = prev;
prev = cur;
cur = last;
last = last->next;
}
cur->next = prev;
return cur;
// //头插法
// if(pHead == nullptr || pHead->next == nullptr)
// return pHead;
// ListNode* new_head = nullptr;
// ListNode* cur = pHead;
// while(cur)
// {
// ListNode* temp = cur;
// cur = cur->next;
// temp->next = new_head;
// new_head = temp;
// }
// return new_head;
}
};
3、合并两个排序的链表
本题考点: 链表合并 牛客链接
题目描述:
输入两个递增的链表,单个链表的长度为n,合并这两个链表并使新链表中的节点仍然是递增排序的。
数据范围:0≤n≤1000,−1000≤节点值≤1000
要求:空间复杂度O(1),时间复杂度 O(n)
如输入{1,3,5},{2,4,6}时,合并后的链表为{1,2,3,4,5,6},所以对应的输出为{1,2,3,4,5,6},转换过程如下图所示:
解题思路:
代码:
class Solution {
public:
ListNode* Merge(ListNode* pHead1, ListNode* pHead2) {
//方法一:
if(pHead1 == nullptr)
return pHead2;
if(pHead2 == nullptr)
return pHead1;
//带头
ListNode* newHead = new ListNode(0);
ListNode* newTail = newHead;
while(pHead1 && pHead2)
{
newTail->next = pHead1->val < pHead2->val ? pHead1 : pHead2;
newTail = newTail->next;
if(newTail == pHead1)
pHead1 = pHead1->next;
else
pHead2 = pHead2->next;
}
if(pHead1 == nullptr)
newTail->next = pHead2;
if(pHead2 == nullptr)
newTail->next = pHead1;
return newHead->next;
}
ListNode* Merge(ListNode* pHead1, ListNode* pHead2) {
//方法二:迭代
//划分成子问题,也就是每一次找一个其中小的节点,然后递归链接
//返回条件
if(pHead1 == nullptr)
return pHead2;
if(pHead2 == nullptr)
return pHead1;
ListNode* newHead = nullptr;
if(pHead1->val < pHead2->val)
{
newHead = pHead1;
pHead1 = pHead1->next;
}
else
{
newHead = pHead2;
pHead2 = pHead2->next;
}
newHead->next = Merge(pHead1, pHead2);
return newHead;
}
};
4、树的子结构
本题考点: 二叉树理解,二叉树遍历 牛客链接
题目描述:
输入两棵二叉树A,B,判断B是不是A的子结构。(我们约定空树不是任意一个树的子结构)
假如给定A为{8,8,7,9,2,#,#,#,#,4,7},B为{8,9,2},2个树的结构如下,可以看出B是A的子结构
代码:
class Solution {
public:
bool isSame(TreeNode* root, TreeNode* subRoot)
{
if(subRoot == nullptr)
return true;
if(root == nullptr)
return false;
if(root->val != subRoot->val)
return false;
return isSame(root->left, subRoot->left) && isSame(root->right, subRoot->right);
}
bool HasSubtree(TreeNode* pRoot1, TreeNode* pRoot2) {
if(pRoot1 == nullptr || pRoot2 == nullptr)
return false;
if(isSame(pRoot1, pRoot2))
return true;
return HasSubtree(pRoot1->right, pRoot2) || HasSubtree(pRoot1->left, pRoot2);
}
};
5、 二叉树的镜像
本题考点: 二叉树操作 牛客链接
题目描述:
操作给定的二叉树,将其变换为源二叉树的镜像。
数据范围:二叉树的节点数 0≤n≤1000 , 二叉树每个节点的值 0≤val≤1000
要求: 空间复杂度 O(n) 。本题也有原地操作,即空间复杂度 O(1) 的解法,时间复杂度 O(n)
比如:
解题思路:
代码:
class Solution {
public:
TreeNode* Mirror(TreeNode* pRoot) {
if(pRoot == nullptr)
return nullptr;
TreeNode* temp = pRoot->left;
pRoot->left = pRoot->right;
pRoot->right = temp;
Mirror(pRoot->left);
Mirror(pRoot->right);
return pRoot;
}
};
6、删除链表中重复的结点
本题考点: 链表操作,临界条件检查,特殊情况处理 牛客链接
题目描述:
在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表 1->2->3->3->4->4->5 处理后为 1->2->5
数据范围:链表长度满足 0≤n≤1000 ,链表中的值满足 1≤val≤1000
进阶:空间复杂度 O(n) ,时间复杂度 O(n)
解题思路:
代码:
class Solution {
public:
ListNode* deleteDuplication(ListNode* pHead) {
if(pHead == nullptr || pHead->next == nullptr)
return pHead;
//带头结点
ListNode* newHead = new ListNode(0);
newHead->next = pHead;
ListNode* prev = newHead;
ListNode* last = prev->next;
while(last)
{
//1、确立重复区域起始位置
while(last->next != nullptr && last->val != last->next->val)
{
prev = last;
last = last->next;
}
//2、确立重复区域
while(last->next != nullptr && last->val == last->next->val)
{
last = last->next;
}
//1.last->next != nullptr , prev, last 确定一段范围, prev->next = last->next
//2.last->next == nullptr , prev, last 确定一段范围, prev->next = last->next
//3.last->next == nullptr , 链表没有重复节点
if(prev->next != last) //只处理有重复节点情况
prev->next = last ->next;
last =last->next;
}
return newHead->next;
}
};