题目十一
输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。
思路:遍历数组
void reOrderArray(vector &array) {
vector res;
int size = array.size();
for (int i = 0;i < size;i++){
if (array[i]%2 ==1){
res.push_back(array[i]);
}
}
for (int i = 0;i < size;i++){
if (array[i]%2 ==0){
res.push_back(array[i]);
}
}
array = res;
}
题目十二
输入一个链表,输出该链表中倒数第k个结点。
思路:可以假想两个指针,让指针1先走k-1步,然后指针1,2同时走,这样当指针1指向最后一个节点时,指针2刚好指向倒数第k个节点。
ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {
if (pListHead == nullptr || k == 0){
return nullptr;
}
ListNode *phead1 = pListHead;
ListNode *phead2 = nullptr;
for (int i = 0;i < k-1;i++){
if (phead1->next != nullptr){
phead1 = phead1->next;
}else{
return nullptr;
}
}
phead2 = pListHead;
while(phead1->next != nullptr){
phead1 = phead1->next;
phead2 = phead2->next;
}
return phead2;
}
题目十三
输入一个链表,反转链表后,输出新链表的表头。
思路:翻转链表时,我们需要设置两个临时变量,pre记录当前节点的上一个节点,next记录当前节点的下一个节点,遍历链表,将当前节电的next指针指向pre。
ListNode* ReverseList(ListNode* pHead) {
if (pHead == nullptr){
return nullptr;
}
ListNode *pNode = pHead;
ListNode *pre = nullptr;
ListNode *reverseHead = nullptr;
while (pNode != nullptr){
ListNode *next = pNode->next;
if (next == nullptr){
reverseHead = pNode;
}
pNode->next = pre;
pre = pNode;
pNode = next;
}
return reverseHead;
}
题目十四
输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。
思路:可以对两个链表的每个节点值进行比较,递归进行链表的合并
ListNode* Merge(ListNode* pHead1, ListNode* pHead2)
{
if (pHead1 == nullptr){
return pHead2;
}
if (pHead2 == nullptr){
return pHead1;
}
ListNode *mergeListHead = nullptr;
if (pHead1->val < pHead2->val){
mergeListHead = pHead1;
mergeListHead->next = Merge(pHead1->next,pHead2);
}else{
mergeListHead = pHead2;
mergeListHead->next = Merge(pHead1,pHead2->next);
}
return mergeListHead;
}
题目十五
输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)
思路:递归思想,先比较A,B的根节点是否相同,相同再去判断左右子树,不同则去A的子节点中寻找与B根节点相同的节点,重复上述步骤。
class Solution {
public:
bool HasSubtree(TreeNode* pRoot1, TreeNode* pRoot2)
{
if (pRoot1 == nullptr || pRoot2 == nullptr){
return false;
}
bool result = false;
if (pRoot1!= nullptr && pRoot2 != nullptr){
if (pRoot1->val == pRoot2->val){
result = doesHave(pRoot1,pRoot2);
}
//两树根节点不同,则遍历A的子树
if (!result){
result = HasSubtree(pRoot1->left,pRoot2);
}
if (!result){
result = HasSubtree(pRoot1->right,pRoot2);
}
}
return result;
}
private:
bool doesHave(TreeNode *proot1,TreeNode *proot2){
//因为遍历到此时还没有return false说明确定是子树
if (proot2 == nullptr){
return true;
}
if (proot1 == nullptr){
return false;
}
if (proot1->val != proot2->val){
return false;
}
return doesHave(proot1->left,proot2->left)&&doesHave(proot1->right,proot2->right);
}
};
题目十六
操作给定的二叉树,将其变换为源二叉树的镜像。
思路:递归操作,交换左右子树
void Mirror(TreeNode *pRoot) {
if (pRoot == nullptr){
return;
}
TreeNode *temp = pRoot->left;
pRoot->left = pRoot->right;
pRoot->right = temp;
if (pRoot->left){
Mirror(pRoot->left);
}
if (pRoot->right){
Mirror(pRoot->right);
}
}
题目十七
输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下4 X 4矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 则依次打印出数字1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10.
思路:设置上下左右四个变量,控制当前打印的坐标,从外到里进行打印,注意控制条件的判断
vector printMatrix(vector > matrix) {
int rows = matrix.size();
int cols = matrix[0].size();
vector res;
if (rows == 0 && cols == 0){
return res;
}
int left = 0;
int right = cols-1;
int top = 0;
int btm = rows-1;
while (left <= right && top <= btm){
//从左往右打印
for (int i = left;i <= right;i++){
res.push_back(matrix[top][i]);
}
//从上往下打印
if (top < btm){
for (int i = top+1;i <= btm;i++){
res.push_back(matrix[i][right]);
}
}
//从右往左打印,一定要多于一行不然没有打印的意义
if (left < right&&top= left;i--){
res.push_back(matrix[btm][i]);
}
}
//从下往上打印
if (left < right&&top+1 top;i--){
res.push_back(matrix[i][left]);
}
}
left++;right--;top++;btm--;
}
return res;
}
题目十八
定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的min函数(时间复杂度应为O(1))。
注意:保证测试中不会当栈为空的时候,对栈调用pop()或者min()或者top()方法。
思路:可以定义两个栈,一个栈就是普通的栈(mainStack),另一个的栈(minStack)我们让它的栈顶始终保持为最小数字,如果新push的数字小于minStack的top,则同时push到两个栈中,在pop的时候要注意,如果mainStack中把当前最小的数pop掉了,要同时将minStack的top也pop掉。
class Solution {
public:
void push(int value) {
if (minStk.empty()||value < minStk.top()){
minStk.push(value);
}
mainStk.push(value);
}
void pop() {
if (mainStk.top() == minStk.top()){
minStk.pop();
}
mainStk.pop();
}
int top() {
return mainStk.top();
}
int min() {
return minStk.top();
}
private:
stack mainStk;
stack minStk;
};
题目十九
输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的)
思路:这个问题我们需要借助一个辅助栈,根据pop的结果来模拟push的情况。
bool IsPopOrder(vector pushV,vector popV) {
stacktemp;
int index = 0;
for (int i = 0;i < pushV.size();i++){
while (temp.empty()||temp.top()!= popV[i]){
temp.push(pushV[index++]);
if (index > pushV.size()){
return false;
}
}
temp.pop();
}
if (temp.empty()){
return true;
}else{
return false;
}
}
题目二十
从上往下打印出二叉树的每个节点,同层节点从左至右打印
思路:从上往下打印二叉树,每一层从左往右,我们可以使用队列来暂存每一层的数据,因为它是先入先出,我们按照这个特点将节点从左到右加入队列中。
vector PrintFromTopToBottom(TreeNode* root) {
vectorres;
queueque;
if (root == nullptr){
return res;
}
TreeNode *temp = root;
que.push(temp);
while(!que.empty()){
temp = que.front();
res.push_back(temp->val);
if (temp->left != nullptr){
que.push(temp->left);
}
if (temp->right != nullptr){
que.push(temp->right);
}
que.pop();
}
return res;
}