剑指Offer66题之每日6题 - 第三天

第一题:调整数组顺序使奇数位于偶数前面

题目:

输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。

解析:

这里是引用

 class Solution {
 public:
	 void reOrderArray(vector<int>& array) {
		 vector<int> reso;
		 vector<int> resj;
		 for (int i = 0; i < array.size(); i++) {
			 array[i] % 2 == 0 ? reso.push_back(array[i]) : resj.push_back(array[i]);
		 }
		 for (int i = 0; i < resj.size(); i++) {
			 array[i] = resj[i];
		 }
		 for (int i = 0; i < reso.size(); i++) {
			 array[resj.size()+i] = reso[i];
		 }
	 }
 };

第二题:链表中倒数第k个结点

题目:

输入一个链表,输出该链表中倒数第k个结点。

解析:

前后指针法,让第一个指针先向前走k-1步,然后第二个指针和第一个指针同时向后走,直到第二个指针后面没有结点,第二个指针指向的就是第k个结点。

不过要注意,如果链表的结点个数少于k,就要返回空指针

class Solution {
public:
	ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {
		auto pre = pListHead;
		for (int i = 0; i < k-1 && pre != nullptr; i++) {
			pre = pre->next;
		}
		if (pre == nullptr) return nullptr;
		auto now = pListHead;
		while (pre->next != nullptr) {
			now = now->next;
			pre = pre->next;
		}
		return now;
	}
};

学习:1、第一个指针不能先走k步,否则临界情况会不好处理

第三题:反转链表

题目:

输入一个链表,反转链表后,输出链表的所有元素。

解析:

这里是引用

struct ListNode {
	int val;
	struct ListNode *next;
	ListNode(int x) :
			val(x), next(NULL) {
	}
};
class Solution {
public:
	ListNode* ReverseList(ListNode* pHead) {
		if (pHead == nullptr || pHead->next == nullptr)
			return pHead;
		ListNode* pre = ReverseList(pHead->next);
		pHead->next->next = pHead;
		pHead->next = nullptr;
		return pre;
	}
};

第四题:合并两个排序的链表

题目:

输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。

解析:

同上题一样,也是有递归做法和非递归做法。

递归做法:两个链表中,哪个头结点的值小就返回哪个头结点,然后合并剩下的链表,最后令头结点的值较小的那个头结点的next指向合并后的剩余链表,一样的,怎么想的,代码就怎么写。

class Solution {
public:
	ListNode* Merge(ListNode* pHead1, ListNode* pHead2)
	{
		if (pHead1 == nullptr) return pHead2;
		if (pHead2 == nullptr) return pHead1;
		ListNode* res;
		if (pHead1->val > pHead2->val) {
			res = pHead2;
			res->next = Merge(pHead1, pHead2->next);
		}
		else
		{
			res = pHead1;
			res->next = Merge(pHead1->next, pHead2);
		}
		return res;
	}
};

第五题:树的子结构

题目:

输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)。

解析:

这题我只想到递归解法,递归其实解决问题的时候是很好思考的,代码也很好写。
首先,判断B是不是A的子结构,然后再判断B是不是A的左子树的子结构,B是不是A的右子树的子结构;
编写isTheSameTree函数时要注意下面这两个判断条件:

  • pRoot2 == nullptr;
  • pRoot1 == nullptr && pRoot2 != nullptr。

两个条件都不满足保证了两个指针都不为空,在草稿纸上画一下就清楚了。

struct TreeNode {
	int val;
	struct TreeNode *left;
	struct TreeNode *right;
	TreeNode(int x) :
			val(x), left(NULL), right(NULL) {
	}
};
class Solution {
public:
	bool HasSubtree(TreeNode* pRoot1, TreeNode* pRoot2)
	{
		if (pRoot1 == nullptr || pRoot2 == nullptr)
			return false;
		return isSamTree(pRoot1, pRoot2) || HasSubtree(pRoot1->left, pRoot2) || HasSubtree(pRoot1->right, pRoot2);
	}
	bool isSamTree(TreeNode* pRoot1, TreeNode* pRoot2) {
		if (pRoot2 == nullptr) return true;
		if (pRoot1 == nullptr && pRoot2 != nullptr) return false;
		return pRoot1->val == pRoot2->val && isSamTree(pRoot1->left, pRoot2->left)
			&& isSamTree(pRoot1->right, pRoot2->right);
	}
};

学习:1、pRoot1 == nullptr || pRoot2 == nullptr,任意一个为空,则返回false

第六题:二叉树的镜像

题目:

操作给定的二叉树,将其变换为源二叉树的镜像。

解析:

还是递归求解,把根节点的左右子树都转化成镜像二叉树,然后再交换左右指针就行了。

struct TreeNode {
	int val;
	struct TreeNode *left;
	struct TreeNode *right;
	TreeNode(int x) :
			val(x), left(NULL), right(NULL) {
	}
};
class Solution {
public:
	void Mirror(TreeNode* pRoot) {
		if (pRoot == nullptr) return;
		Mirror(pRoot->left);
		Mirror(pRoot->right);
		TreeNode* cur = pRoot->left;
		pRoot->left = pRoot->right;
		pRoot->right = cur;
	}
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值