链表中倒数第k个结点、反转链表、合并两个排序的链表、树的子结构、删除链表中重复的结点

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;
    }
};

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小朱同学..

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值