笔试算法题(24):找出出现次数超过一半的元素 & 二叉树最近公共父节点
出题:数组中有一个数字出现的次数超过了数组长度的一半,请找出这个数字;
分析:
- 解法1:首先对数组进行排序,时间复杂度为O(NlogN),由于有一个数字出现次数超过了数组的一半,所以如果二分数组的话,划分元素肯定就是这个数字;
- 解法2:首先创建1/2数组大小的Hash Table(哈希表可以替代排序时间,由于一个数字出现超过了数组的一半,所以不同元素个数肯定不大于数组的一半),空间复杂度O(N),顺序扫描映射数 组元素到Hash Table中并计数,最后顺序扫描Hash Table,计数超过数组大小一半的元素就是这个数字,时间复杂度O(N);
- 解法3:由于一个数字的出现次数超过了数组的一半,所以这个数字的次数减去其他数字的总和的值仍旧大于0;定义两个变量,一个存储数字A,一个进行计数 C;当下一个数字与A相同,则C+1,当下一个数字与A不同,则C-1;当C等于0的时候,A初始化为下一个数字。最终A就是这个数字,时间复杂度 O(N);
- 扩展问题:如果有三个数字出现的次数均超过了数字总数的1/4,则如何快速找到这三个数字。同样使用解法3的思想,同时删除4个不同的数字,直到找不到4个不同的数字,剩下的数字就是由三个不同数字重复出现组成的。时间复杂度O(N);
解题:
int HalfElementArray(int *array, int length) {
int num=array[];
int count=; for(int i=;i<length;i++) {
if(array[i]==num)
count++;
else {
if(count==)
num=array[i+];
else
count--;
}
}
return num;
}
void QuarterElementsArray(int *array, int length) {
int num1=array[],num2=array[],num3=array[];
int count1=,count2=,count3=; for(int i=;i<length;i++) {
if(array[i]==num1)
count1++;
else if(array[i]==num2)
count2++;
else if(array[i]==num3)
coun3++;
else {
if(count1==)
num1=array[i+];
else if(count2==)
num2=array[i+];
else if(count3==)
num3=array[i+];
else {
num1--;num2--;num3--;
}
}
printf("%D, %d, %d\n",num1,num2,num3);
}
}
出题:给定一棵二叉树,以及两个节点,要求找到两个节点最近的公共父节点;
分析:
- 解法1:遍历整棵树分别查找两个节点,并分别使用两个Stack(Queue)结构保存根节点到查找节点的路径,然后查找路径中的第一个公共节点(最后一个公共节点),时间复杂度为O(N),空间复杂度为O(logN);
- 解法2:使用递归方法,从当前节点的左右子树中确定是否包含两个节点A和B,如果A和B都在左子树中则递归,如果A和B都在右子树中则递归,如果一个在左 子树一个在右子树则当前节点就是第一个公共节点,由于每次都需要判断子树是否包含某个节点,所以时间复杂度为O(N^2),没有额外的空间复杂度;
解题:
struct Node {
int value;
Node *left;
Node *right;
}; /**
* 使用stack结构保存root到target节点的路径的解法
* 算法复杂度为O(N),空间复杂度为O(NlogN)
* */ /**
* stack实现
* */
class MyStack {
private:
Node **array;
int capability;
int top;
public:
MyStack(int cap=): array((Node**)malloc(sizeof(Node)*cap)), capability(cap), top() {}
~MyStack() {delete [] array;} bool isFull() {
return top == capability;
}
bool isEmpty() {
return top == ;
}
int freeSlot() {
return capability - top;
} /**
* top当前的位置就是下一个push元素所在的slot
* */
bool push(Node *n) {
if(isFull()) return false;
array[top++]=n;
return true;
}
bool pop(Node **n) {
if(isEmpty()) return false;
*n=array[--top];
return true;
}
void ShowStack() {
int temp=top-;
printf("\n");
for(int i=;i<=temp;i++)
printf("%d, ",array[i]->value);
printf("\n");
}
}; Node* GetLowerFather(MyStack *sfirst, MyStack *ssecond) { } bool FindTargetPath(Node *root, Node *target, MyStack *mstack) {
if(root==NULL)
return false;
mstack->push(root); if(root==target)
return true;
else if(FindTargetPath(root->left,target, mstack))
return true;
else if(FindTargetPath(root->right,target, mstack))
return true;
else {
mstack->pop(NULL);
return false;
}
} Node* FindCommonFather1(Node *root, Node *first, Node *second) {
if(first==NULL || second==NULL)
return NULL;
MyStack *sfirst=new MyStack();
MyStack *ssecond=new MyStack(); if(FindTargetPath(root, first, sfirst) &&
FindTargetPath(root, second, ssecond))
return GetLowerFather(sfirst, ssecond);
else {
printf("\nbad input");
return NULL;
}
} /**
* 直接使用递归的解法
* 算法复杂度为O(N^2)
* */ bool HasNode(Node *root, Node *target) {
if(root==NULL) return false;
if(root==target) return true;
/**
* 仅当左子树没有找到target的时候,才处理右子树
* */
bool bleft=HasNode(root->left,target);
if(!bleft) {
return HasNode(root->right,target);
} else {
return true;
}
} Node* FindCommonFather(Node *cur, Node *first, Node *second) {
/**
* 如果当前节点为NULL,返回NULL
* */
if(cur == NULL) return NULL;
/**
* 判断是否first和second都在左子树
* 注意处理first和second为同一个节点的情况
* 注意处理first和second中一个节点是另一个节点的父节点的情况
* */
bool bfirstleft=false, bsecondleft=false;
if(cur->left != NULL) {
bfirstleft=HasNode(cur->left,first);
bsecondleft=HasNode(cur->left,second);
if(bfirstleft && bsecondleft) {
/**
* 这里的||操作可以处理当一个节点是另一个节点的
* 父节点的情况
* */
if(cur->left==first || cur->left==second)
return cur;
else
return FindCommonFather(cur->left,first,second);
}
}
/**
* 判断是否first和second都在右子树
* 注意处理first和second为同一个节点的情况
* 注意处理first和second中一个节点是另一个节点的父节点的情况
* */
bool bfirstright=false, bsecondright=false;
if(cur->right != NULL) {
bfirstright=HasNode(cur->right,first);
bsecondright=HasNode(cur->right,second);
if(bfirstright && bsecondright) {
/**
* 这里的||操作可以处理当一个节点是另一个节点的
* 父节点的情况
* */
if(cur->right==first || cur->right==second)
return cur;
else
return FindCommonFather(cur->right,first,second);
}
}
/**
* 判断是否first在左且second在右,或者first在右且
* second在左
* */
if((bfirstleft && bsecondright) ||
(bfirstright && bsecondleft))
return cur;
return NULL;
}
笔试算法题(24):找出出现次数超过一半的元素 & 二叉树最近公共父节点的更多相关文章
- majority element(数组中找出出现次数最多的元素)
Given an array of size n, find the majority element. The majority element is the element that appear ...
- 算法题之找出数组里第K大的数
问题:找出一个数组里面前K个最大数. 解法一(直接解法): 对数组用快速排序,然后直接挑出第k大的数.这种方法的时间复杂度是O(Nlog(N)).N为原数组长度. 这个解法含有很多冗余,因为把整个数组 ...
- 前端算法题:找出数组中第k大的数字出现多少次
题目:给定一个一维数组,如[1,2,4,4,3,5],找出数组中第k大的数字出现多少次. 例如:第2大的数是4,出现2次,最后输出 4,2 function getNum(arr, k){ // 数组 ...
- 笔试算法题(19):判断两条单向链表的公共节点 & 字符集删除函数
出题:给定两个单向链表的头结点,判断其是否有公共节点并确定第一个公共节点的索引: 分析: 由于是单向链表,所以每个节点有且仅有一个后续节点,所以只可能是Y型交叉(每条链表中的某个节点同时指向一个公共节 ...
- 剑指Offer:找出数组中出现次数超过一半的元素
题目:找出数组中出现次数超过一半的元素 解法:每次删除数组中两个不同的元素,删除后,要查找的那个元素的个数仍然超过删除后的元素总数的一半 #include <stdio.h> int ha ...
- 从一亿个ip找出出现次数最多的IP(分治法)
/* 1,hash散列 2,找到每个块出现次数最多的(默认出现均匀)—–>可以用字典树 3,在每个块出现最多的数据中挑选出最大的为结果 */ 问题一: 怎么在海量数据中找出重复次数最多的一个 算 ...
- 笔试算法题(42):线段树(区间树,Interval Tree)
议题:线段树(Interval Tree) 分析: 线段树是一种二叉搜索树,将一个大区间划分成单元区间,每个单元区间对应一个叶子节点:内部节点对应部分区间,如对于一个内部节点[a, b]而言,其左子节 ...
- 一个N*M的矩阵,找出这个矩阵中所有元素的和不小于K的面积最小的子矩阵
题目描述: 一个N*M的矩阵,找出这个矩阵中所有元素的和不小于K的面积最小的子矩阵(矩阵中元素个数为矩阵面积) 输入: 每个案例第一行三个正整数N,M<=100,表示矩阵大小,和一个整数K 接下 ...
- 9.11排序与查找(三)——给定一个排序后的数组,包括n个整数,但这个数组已被旋转过多次,找出数组中的某个元素
/** * 功能:给定一个排序后的数组.包括n个整数.但这个数组已被旋转过多次,次数不详.找出数组中的某个元素. * 能够假定数组元素原先是按从小到大的顺序排列的. */ /** * 思路:数组 ...
随机推荐
- webpack 4.0 相关
Webpack 4.0发布了!! https://www.jianshu.com/p/3a13f1b37300 webpack详解 https://juejin.im/post/5aa3d2056fb ...
- (DP)51NOD 1183 编辑距离
编辑距离,又称Levenshtein距离(也叫做Edit Distance),是指两个字串之间,由一个转成另一个所需的最少编辑操作次数.许可的编辑操作包括将一个字符替换成另一个字符,插入一个字符,删除 ...
- Luogu P1330 封锁阳光大学【Dfs】 By cellur925
题目传送门 这道题我们很容易去想到二分图染色,但是这个题好像又不是一个严格的二分图. 开始的思路:dfs每个点,扫与他相邻的每个点,如果没访问,染相反颜色:如果访问过,进行检查,如果不可行,直接结束程 ...
- mybatis 批量insert,update报错 The error occurred while setting parameters
数据脚本执行正常,但是报错,搜索关键信息 The error occurred while setting parameters ,发现了解决帖子: http://blog.csdn.net/jing ...
- ElasticSearch | centos7 上安装ES
0 参考博客文章(感谢!!!) [1] https://www.jianshu.com/p/10949f44ce9c 在linux服务器上安装jdk [2] https://www.elastic ...
- 51nod 1213 二维曼哈顿距离最小生成树
1213 二维曼哈顿距离最小生成树 基准时间限制:4 秒 空间限制:131072 KB 分值: 160 难度:6级算法题 收藏 关注 二维平面上有N个坐标为整数的点,点x1 y1同点x2 y2之间 ...
- java垃圾回收体制
JVM分代垃圾回收策略的基础概念 为什么要分代 分代的垃圾回收策略,是基于这样一个事实:不同的对象的生命周期是不一样的.因此,不同生命周期的对象可以采取不同的收集方式,以便提高回收效率. 在Java程 ...
- Hadoop 之Pig的安装的与配置之遇到的问题---待解决
1. 前提是hadoop集群已经配置完成并且可以正常启动:以下是我的配置方案: 首先配置vim /etc/hosts 192.168.1.64 xuegod64 192.168.1.65 xuegod ...
- 自定义button上传按钮
<div class="upload_files"> <input type="file" class="upload_icon&q ...
- JS操作CSS
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...