有一个整数数组,请你根据快速排序的思路,找出数组中第K大的数。
给定一个整数数组a,同时给定它的大小n和要找的K(K在1到n之间),请返回第K大的数,保证答案存在。
测试样例:
[1,3,5,2,2],5,3
返回:2
主体思路就是利用快速排序每次能将比某个哨兵小的数放在左侧,大的数放在右侧,代码如下:
class Finder {
public:
int findKth(vector<int> a, int n, int K) {
return quickfind(a, 0, n-1, K);
}
int quickfind(vector<int>& a, int left, int right, int k) {
int i = left;
int j = right;
int mark = a[left];
while (i < j) {
while (i < j && a[j] >= mark)
--j;
if (i < j)
a[i++] = a[j];
while (i < j && a[i] <= mark)
++i;
if (i < j)
a[j--] = a[i];
}
a[i] = mark;
//哨兵右侧比他大的数字个数
int big_num = right - i;
//如果哨兵刚好是第K大的数
if (k - big_num - 1 == 0)
return mark;
else if (k - big_num - 1 > 0) {
//如果右侧数字个数不够K个,则从左侧找第k-big_num-1大的数
return quickfind(a, left, i - 1, k - big_num - 1);
} else {
//如果右侧数字个数比K多,则在右侧找第K大的数
return quickfind(a, i + 1, right, k);
}
}
};
小明陪小红去看钻石,他们从一堆钻石中随机抽取两颗并比较她们的重量。这些钻石的重量各不相同。在他们们比较了一段时间后,它们看中了两颗钻石g1和g2。现在请你根据之前比较的信息判断这两颗钻石的哪颗更重。
给定两颗钻石的编号g1,g2,编号从1开始,同时给定关系数组vector,其中元素为一些二元组,第一个元素为一次比较中较重的钻石的编号,第二个元素为较轻的钻石的编号。最后给定之前的比较次数n。请返回这两颗钻石的关系,若g1更重返回1,g2更重返回-1,无法判断返回0。输入数据保证合法,不会有矛盾情况出现。
测试样例:
2,3,[[1,2],[2,4],[1,3],[4,3]],4
返回: 1
int cmp(int g1, int g2, vector<vector<int> > records, int n) {
int maxNum = -99999;
for(int i=0; i<n; i++){
maxNum = maxNum>records[i][0]?maxNum:records[i][0];
maxNum = maxNum>records[i][1]?maxNum:records[i][1];
}
//构造有向图
int map[maxNum+1][maxNum+1];
for(int i=1; i<=maxNum; i++){
for(int j=1; j<=maxNum; j++){
if(i == j) map[i][j] = 1;
else map[i][j] = 0;
}
}
for(int i=0; i<n; i++){
map[records[i][0]][records[i][1]] = 1;
}
for(int k=1; k<=maxNum; k++){
for(int j=1; j<=maxNum; j++){
for(int i=1; i<=maxNum; i++){
if(map[i][k] == 1 && map[k][j] == 1){
map[i][j] = 1;
}
}
}
}
if(map[g1][g2] == 1)
return 1;
else if(map[g2][g1] == 1)
return -1;
else
return 0;
}
//就是一个森林,关系存在就是以g2为根节点的树下面的节点中有g1,
//或者以g1为根节点的树的下面的节点包含g2
//我们采取层序遍历的方式遍历以g1开头的整棵树,和以g2开头的整棵树.
#include<unordered_map>
class Cmp {
bool judge(int g1,int g2,unordered_map<int,vector<int>> ans){
//查找g1是否比g2重.
queue<int>q;
unordered_map<int, bool>mark;//用于标记当前节点是否遍历过
q.push(g1);
while (!q.empty()) {
int cur = q.front();
q.pop();
mark[cur] = true;
if(cur==g2)
return true;
for(int i=0;i<ans[cur].size();++i){
if(!mark[ans[cur][i]])//没有遍历过
q.push(ans[cur][i]);
}
}
return false;
}
public:
int cmp(int g1, int g2, vector<vector<int> > records, int n) {
unordered_map<int,vector<int>>ans;
for (int i=0; i<n; ++i)
ans[records[i][0]].push_back(records[i][1]);
if(judge(g1, g2, ans))
return 1;
else{
if(judge(g2, g1, ans))
return -1;
else
return 0;
}
}
};
有一棵二叉树,树上每个点标有权值,权值各不相同,请设计一个算法算出权值最大的叶节点到权值最小的叶节点的距离。二叉树每条边的距离为1,一个节点经过多少条边到达另一个节点为这两个节点之间的距离。
给定二叉树的根节点root,请返回所求距离。
//1注意点 权值最大的叶子节点到权值最小的叶子节点,不是所有的节点,自己就因为这个卡了好久
//2.用俩个变量标记俩个节点的位置,求出根节点到他们的路径,如果有重复的路径就减去重复的路径的长度.
class Tree {
void Inorder(TreeNode *root,vector<int>&v,int &small,int &big){
//中序遍历获得最小的叶节点和最大的叶节点的索引
if(!root)
return;
Inorder(root->left, v, small, big);
v.push_back(root->val);
if(root->left==NULL&&root->right==NULL){//叶子节点
if(small==-1||big==-1)
small = big =(int)v.size()-1;
else{
if(root->val<v[small]) small = (int)v.size()-1;
if(root->val>v[big]) big = (int)v.size()-1;
}
}
Inorder(root->right, v, small, big);
}
public:
int getDis(TreeNode* root) {
int small = -1,big = -1;
vector<int>v;
Inorder(root, v, small, big);
TreeNode * p = root;
vector<int>v1,v2;
int pos;
while (true) {//寻找路径
pos = (int)(find(v.begin(), v.end(),p->val)-v.begin());
v1.push_back(v[pos]);
if(small>pos)
p = p->right;
else if(small<pos)
p = p->left;
else
break;
}
p = root;
while (true) {
pos = (int)(find(v.begin(), v.end(),p->val)-v.begin());
v2.push_back(v[pos]);
if(big>pos)
p = p->right;
else if(big<pos)
p = p->left;
else
break;
}
int i,j;
for (i=0,j=0;j<v2.size()-1&&i<v1.size()-1; ++i,++j) {//去重
if(!(v1[i]==v2[j]&&v1[i+1]==v2[j+1]))
break;
}
return (int)v1.size()-1+(int)v2.size()-1-2*i;
}
};