出题:定义一个复杂链表:在单向链表的基础上,每个节点附加一个指向链表中其他任意节点的指针sibling,实现CNode* Clone(Cnode *head)函数复制这个复杂链表;

分析:

  • 解法1:将head复制到CHead中,第一次遍历创建CHead中对应head的各个节点(next),第二次遍历创建CHead中对应head各个节 点的sibling链接,由于需要在CHead中找到对应head中的sibling节点,所以需要遍历CHead链表,但是可以用空间换时间的方法:使 用Hash Table存储CHead和head对应的节点对,这样head中定位了sibling之后,就可以知道CHead中对应sibling节点,时间复杂度 为O(N),空间复杂度为O(N);
  • 解法2:注意给出的函数头中参数并没有使用const,而一般情况下的copy函数的参数都是const,所以可以推断可能需要改变原始数据的结构。使用 奇偶链表实现,将新创建的CHead中的各个节点对应安插到head中各个节点之后,这样CHead中与head中对等的节点就在head中节点的后面, 所以可以很容易确定sibling节点,最后仅读取偶数节点就是CHead,时间复杂度为O(N),空间复杂度为O(1)。海涛老师再次威武!此方法参考 海涛老师的博客:
    http://zhedahht.blog.163.com/blog/static/254111742010819104710337/

解题:

 struct CNode {
int value;
CNode *next;
CNode *sibling;
};
CNode* Clone(CNode *head) {
if(head==NULL) return NULL; CNode *CHead=new CNode();
CHead->value=head->value;
CNode *cur, *pre=CHead, *temp=head->next, *CTemp;
/**
* 以next指针为线索创建链表节点
* */
while(temp!=NULL) {
cur=new CNode();
cur->value=temp->value;
pre->next=cur;
pre=cur; temp=temp->next;
}
/**
* 以next指针为线索创建sibling链接
* */
temp=head;CTemp=CHead;
while(temp!=NULL) {
/**
* 将下面这句代码换成HashTable存储的head和CHead中
* 对等节点的存储对
* */
//CTemp->sibling=temp->sibling;
temp=temp->next;
CTemp=CTemp->next;
}
return CHead;
}
/**
* 在head中每个节点的后面创建一个新节点,
* 并复制之前节点的value,链接之前节点的
* next节点
* */
void CreateNewNode(CNode *head) {
CNode *index=head, *nNode, *next;
while(index!=NULL) {
nNode=new CNode();
nNode->value=index->value;
nNode->sibling=NULL; next=index->next;
index->next=nNode;
nNode->next=next;
index=next;
}
}
/**
* 顺序遍历head中奇数索引的节点,如果其sibling非NULL,则
* 其sibling的next节点就是CHead中的对应节点的sibling
* */
void CopySibling(CNode *head) {
CNode *index=head;
while(index!=NULL) {
if(index->sibling!=NULL) {
index->next->sibling=
index->sibling->next;
}
index=index->next->next;
}
}
/**
* 将head拆分成奇数索引节点和偶数索引节点,后者就是新clone
* 的复杂链表
* */
CNode* Separate(CNode *head) {
CNode *index=head, *clone;
if(index!=NULL) {
clone=index->next;
index->next=index->next->next;
index=index->next;
} else
return NULL;
CNode *temp;
while(index!=NULL) {
temp=index->next;
clone->next=temp;
index->next=temp->next; clone=temp;
index=temp->next;
} return clone;
}
void Deletion(CNode *head) {
CNode *cur=head, *next;
if(cur!=NULL) {
next=cur->next;
delete cur;
cur=next;
}
}

出题:输入两棵二元树的根节点A和B,判断B是否是A的一个子树结构;

分析:

  • 首先在A中找到与B根节点的值相同的节点AB1(注意处理节点值相同的情况,首先判断当前找到的AB1是否匹配,如果不匹配则继续寻找下一个AB1),然 后同时递归AB1和B,如果B中某节点的值与AB1某节点的值不等,则返回false;
  • 如果B中某节点有子节点(左右),而AB1中没有,则返回 false;当B递归完全之后(也就是到达NULL)返回true;

解题:

 struct Node {
int value;
Node *left;
Node *right;
};
/**
* son只能是father的一部分,其他情况都返回false
* */
bool compare(Node *father, Node *son) {
if(son==NULL) return true;
if(father==NULL) return false;
if(father->value != son->value)
return false;
else
return compare(father->left,son->left) &&
compare(father->right,son->right);
}
/**
* 注意处理节点值重复的情况,因为只能找到第一个节点,而正确
* 的匹配可能发生在之后的拥有相同节点值的节点
* */
Node* findNode(Node *root, Node *target) {
Node *temp=NULL; bool ismatch=true;
if(root->value==target->value) {
if(compare(root, target)) {
printf("\nb1 is part of a1");
exit();
} else
ismatch=false;
}
if(!ismatch && root->left!=NULL)
temp=findNode(root->left,target);
if(temp==NULL && root->right!=NULL)
temp=findNode(root->right,target);
return temp;
}

笔试算法题(25):复制拥有多个指针的链表 & 判断二元树B是否为A的子树的更多相关文章

  1. 笔试算法题(46):简介 - 二叉堆 & 二项树 & 二项堆 & 斐波那契堆

    二叉堆(Binary Heap) 二叉堆是完全二叉树(或者近似完全二叉树):其满足堆的特性:父节点的值>=(<=)任何一个子节点的键值,并且每个左子树或者右子树都是一 个二叉堆(最小堆或者 ...

  2. 笔试算法题(28):删除乱序链表中的重复项 & 找出已经排好序的两个数组中的相同项

    出题:给定一个乱序链表,节点值为ASCII字符,但是其中有重复项,要求去除重复项并保证不改变剩余项的原有顺序: 分析:创建一个256(2^8)大小的bool数组,初始化为false,顺序读取链表,将字 ...

  3. 笔试算法题(21):将stack内外颠倒 & 判断扑克牌顺子

    出题:要求用递归将一个栈结构的元素内外颠倒: 分析: 本题再次说明系统栈是程序员最好的帮手,但递归度较高所以时间复杂度较大,可以使用空间换时间的方法(额外数组保存栈元素,然后逆向压入): 第一层递归( ...

  4. 【IT笔试面试题整理】判断一个树是否是另一个的子树

    [试题描述]定义一个函数,输入判断一个树是否是另一个对的子树 You have two very large binary trees: T1, with millions of nodes, and ...

  5. 前端如何应对笔试算法题?(用node编程)

    用nodeJs写算法题 咱们前端使用算法的地方不多,但是为了校招笔试,不得不针对算法题去练习呀! 好不容易下定决心 攻克算法题.发现js并不能像c语言一样自建输入输出流.只能回去学习c语言了吗?其实不 ...

  6. 笔试算法题(24):找出出现次数超过一半的元素 & 二叉树最近公共父节点

    出题:数组中有一个数字出现的次数超过了数组长度的一半,请找出这个数字: 分析: 解法1:首先对数组进行排序,时间复杂度为O(NlogN),由于有一个数字出现次数超过了数组的一半,所以如果二分数组的话, ...

  7. 笔试算法题(06):最大连续子数组和 & 二叉树路径和值

    出题:预先输入一个整型数组,数组中有正数也有负数:数组中连续一个或者多个整数组成一个子数组,每个子数组有一个和:求所有子数组中和的最大值,要求时间复杂度O(n): 分析: 时间复杂度为线性表明只允许一 ...

  8. 笔试算法题(57):基于堆的优先级队列实现和性能分析(Priority Queue based on Heap)

    议题:基于堆的优先级队列(最大堆实现) 分析: 堆有序(Heap-Ordered):每个节点的键值大于等于该节点的所有孩子节点中的键值(如果有的话),而堆数据结构的所有节点都按照完全有序二叉树 排.当 ...

  9. 笔试算法题(53):四种基本排序方法的性能特征(Selection,Insertion,Bubble,Shell)

    四种基本算法概述: 基本排序:选择,插入,冒泡,希尔.上述算法适用于小规模文件和特殊文件的排序,并不适合大规模随机排序的文件.前三种算法的执行时间与N2成正比,希尔算法的执行时间与N3/2(或更快)成 ...

随机推荐

  1. 3198: [Sdoi2013]spring【容斥原理+hash】

    容斥是ans= 至少k位置相等对数C(k,k)-至少k+1位置相等对数C(k+1,k)+至少k+2位置相等对数*C(k+2,k) -- 然后对数的话2^6枚举状态然后用hash表统计即可 至于为什么要 ...

  2. Xposed 集成 Android 6.0.1环境中,总结

    由于工作需要,需要将xposed集成到android源码中,生成新的ROM就自带xposed的功能. 下面大体上说一下步骤和遇到的问题. 1.下载,并编译android源码,成功. 2.下载 http ...

  3. python之计数统计

    前言: 计数统计,简单的说就是统计某一项出现的次数.实际应用中很多需求都需要用到这个模型,如检测样本中某一值出现的次数.日志分析某一消息出现的频率.分析文件中相同字符串出现的概率等等.以下是实现的不同 ...

  4. 洛谷 P3332 [ZJOI2013]K大数查询 || bzoj3110

    用树套树就很麻烦,用整体二分就成了裸题.... 错误: 1.尝试线段树套平衡树,码农,而且n*log^3(n)慢慢卡反正我觉得卡不过去 2.线段树pushdown写错...加法tag对于区间和的更新应 ...

  5. Spring中bean的五个作用域简介(转载)

    Spring上个版本的IoC容器支持两个不同的bean作用域(单例与原型).Spring 2.0改进了这一点,不仅提供了一些依赖于Spring部署环境(比如说,在web环境中的request和sess ...

  6. Xcode7 使用AFNetWorking 报错 添加Security.framework

    Undefined symbols for architecture x86_64: "_SecCertificateCopyData", referenced from: _AF ...

  7. 事件模型的介绍与Button的ActionListener

    事件监听: 这是个很重要的概念,也是个很重要的模型,vb,vc都是这样用,甚至后面学的web框架也在用.    现在我们可以做很多按钮了吧,但是我们的按钮按它是没反应的,现在我们来看看怎么样才能让它有 ...

  8. poj2573Bridge(过桥问题)

    链接 A,B为最快和次快 有两种方式可以使c,d过桥 一是a与c一起走,a回来接d再与d一起走,一直到对岸人为0为止 而是 a与b一起走 a回来送灯 c与d一起走 b回来送灯 重复此过程. 只剩2人时 ...

  9. 树莓派 VNC 远程桌面 同一个桌面

    如何在ssh登录的情况下配置好vino 1.传输文件 2.ssh sudo dpkg -i ~/swap/deb/tight* sudo cp ~/swap/vino.desktop /etc/xdg ...

  10. commons-lang常用工具类StringEscapeUtils使用--转

    https://my.oschina.net/ydsakyclguozi/blog/341496 在apache commons-lang(2.3以上版本)中为我们提供了一个方便做转义的工具类,主要是 ...