第一题:调整数组顺序使奇数位于偶数前面
题目:
输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。
解析:
这里是引用
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;
}
};