http://topic.csdn.net/u/20081006/16/75461d49-6a8f-4684-84b6-aceee56c832f.html
(1)
一个整数数列,元素取值可能是0~65535中的任意一个数,相同数值不会重复出现。0是例外,可以反复出现。
请设计一个算法,当你从该数列中随意选取5个数值,判断这5个数值是否连续相邻。
注意:
- 5个数值允许是乱序的。比如: 8 7 5 0 6
- 0可以通配任意数值。比如:8 7 5 0 6 中的0可以通配成9或者4
- 0可以多次出现。
- 复杂度如果是O(n2)则不得分。
(2)
设计一个算法,找出二叉树上任意两个结点的最近共同父结点。
复杂度如果是O(n2)则不得分。
(3)
一棵排序二叉树,令 f=(最大值+最小值)/2,设计一个算法,找出距离f值最近、大于f值的结点。
复杂度如果是O(n2)则不得分。
(4)
一个整数数列,元素取值可能是1~N(N是一个较大的正整数)中的任意一个数,相同数值不会重复出现。设计一个算法,找出数列中符合条件的数对的个数,满足数对中两数的和等于N+1。
复杂度最好是O(n),如果是O(n2)则不得分。
自己做了一下,程序如下
(1)
(2)
(3)
(4)
用到的Node类
(1)
一个整数数列,元素取值可能是0~65535中的任意一个数,相同数值不会重复出现。0是例外,可以反复出现。
请设计一个算法,当你从该数列中随意选取5个数值,判断这5个数值是否连续相邻。
注意:
- 5个数值允许是乱序的。比如: 8 7 5 0 6
- 0可以通配任意数值。比如:8 7 5 0 6 中的0可以通配成9或者4
- 0可以多次出现。
- 复杂度如果是O(n2)则不得分。
(2)
设计一个算法,找出二叉树上任意两个结点的最近共同父结点。
复杂度如果是O(n2)则不得分。
(3)
一棵排序二叉树,令 f=(最大值+最小值)/2,设计一个算法,找出距离f值最近、大于f值的结点。
复杂度如果是O(n2)则不得分。
(4)
一个整数数列,元素取值可能是1~N(N是一个较大的正整数)中的任意一个数,相同数值不会重复出现。设计一个算法,找出数列中符合条件的数对的个数,满足数对中两数的和等于N+1。
复杂度最好是O(n),如果是O(n2)则不得分。
自己做了一下,程序如下
(1)
- // 返回0表示正确,否则返回失败的索引值
- int Check(int* p_data, int p_nCount)
- {
- int i, end, zeroCount=0;
- // 对数据进行从小到大排序
- Sort(p_data, p_nCount);
- // 检查0的个数
- for(i=0; i<p_nCount; i++)
- {
- if(p_data[i]==0) zeroCount++;
- else break;
- }
- // 从5开始,到非0值的循环
- i = p_nCount;
- end = zeroCount+1;
- while(i-- > end)
- {// 如果前后相差大于1,表示不连续
- if((p_data[i] - p_data[i-1]) != 1)
- {// 看能否用足够的0不上,计算剩余的0个数
- zeroCount -= p_data[i] - p_data[i-1]-1;
- if(zeroCount < 0) return i;
- }
- }
- return 0;
- }
(2)
- void swap(Node** a, Node** b)
- {
- Node * p = *a;
- *b = *a;
- *a = p;
- }
- void Check(Node * root, Node* a, Node* b)
- {
- Node * parent = NULL;
- if (a == NULL || b == NULL) printf("NULL/r/n");
- printf("a=%d, b=%d, parent=", a->value, b->value);
- if (a->GetLevel() < b->GetLevel()) // 检查两个节点深度,如果b比a深,交换a、b,让a的深度比b大
- {
- swap(&a, &b);
- }
- while(a->GetLevel() > b->GetLevel()) //对齐深度,这样才好比较
- {
- a = a->parent;
- }
- if (a == b) parent = a; //对齐后如果是同一节点,那么共同父节点取a
- else
- {
- while(a->parent != b->parent) //检查a、b的父节点,如果不是,同时提升a、b节点
- {
- a = a->parent;
- b = b->parent;
- }
- parent = a->parent;//最后得到共同父节点
- }
- printf("%d/r/n", parent->value);
- }
(3)
- #include <stdio.h>
- #include <stdlib.h>
- #include <conio.h>
- #include "node.h"
- int sum = 0; // 比较次数总数
- Node * Check(Node * p, int f)
- {
- sum++;
- if (p==NULL) return NULL;
- sum++;
- if (p->value >= f) // 当前节点大于f时,要检查左节点是否有更接近的值
- {
- Node* q = Check(p->left,f);
- sum++;
- return (q!=NULL)?q:p; // 左节点没合适的值时,用当前节点,否则要返回的节点
- }
- else // 当前节点小于f时,检查右节点是否有更接近的值
- {
- return Check(p->right,f);
- }
- }
- // 给出根节点,计算最接近 f=(最大值+最小值)/2 的节点
- void Check(Node * root)
- {
- Node * min = root->GetMinNode();
- Node * max = root->GetMaxNode();
- int f = (max->value + min->value)/2;
- printf("min=%d, max=%d, f=%d , ", min->value, max->value, f);
- sum=0;
- Node* p = Check(root, f);
- printf("target=%d/t/t%d/r/n", p->value,sum);
- }
- // 生成测试数据
- Node * CreateTestTree(void)
- {
- int data[]={100,50,30,20,40,70,60,80,150,130,120,140,170,160,180};
- int len = 15;
- Node * root= new Node(data[0]);
- for(int i = 1; i < len; i++)
- {
- root->Insert(data[i]);
- }
- return root;
- }
- // 主测试函数
- void main(void)
- {
- clrscr();
- Node * treeRoot = CreateTestTree();
- treeRoot->PrintTree(40,1,3);
- Node * p = NULL;
- // 单独测试 Node * Check(Node * p, int f)
- for (int i=10;i<=200 ;i+=5)
- {
- p = Check(treeRoot, i);
- printf ("f=%d, node=%d/r/n",i,p->value);
- }
- // 测试题目3
- Check(treeRoot);
- delete treeRoot;
- treeRoot = NULL;
- return ;
- }
(4)
- #include <stdio.h>
- // 题目4:
- //一个整数数列,元素取值可能是1~N(N是一个较大的正整数)中的任意一个数,相同数值不会重复出现。设计一个算法,找出数列中符合条件的数对的个数,满足数对中两数的和等于N+1。
- //复杂度最好是O(n),如果是O(n2)则不得分。
- // buf中数据应该已经排序
- // 返回匹配数对数量
- // 算法中遍历1次数组,复杂度O(N)
- int c4(int* buf, int count)
- {
- const int *p = buf; // 前指针
- const int *q = buf+count-1; // 后指针
- int n=*q+1; // N值
- int c = 0; // 匹配数量
- int compare = 0; //比较次数
- while (p<q) // 当前指针小于后指针时,循环数组
- { compare++;
- if ((*p + *q) == n) // 命中,计数加1,移动指针
- { compare++; printf("%d,%d; ", *p,*q);
- c++; p++; q--;
- }
- else
- {
- if ((*q + *p ) > n )
- q--; // 当前2个值大于N时,前指针的值可能还有匹配,后指针左移
- else
- p++; // 当前2个值小于N时,后指针的值可能还有匹配,前指针右移
- }
- }
- printf("compare=%d;/r/n ", compare); // 打印总比较次数
- return c;
- }
- void test(int index, const int* buf, int count, int expected)
- {
- for(int i=0; i<count; i++) printf("%2d,", buf[i]);
- int actual = c4(buf, count);
- printf("test %2d/t [%s] expected=%d, actual=%d/r/n/r/n",
- index, expected==actual?" ok ":"false", expected, actual);
- }
- int main(void)
- {
- int i=1;
- int t0[10]={1,2,3,4,5,95,96,97,98,99};
- int t0_expected=5;
- test(i++, t0, 10, t0_expected);
- int t1[10]={1,2,13,14,15,95,96,97,98,99};
- int t1_expected=2;
- test(i++, t1, 10, t1_expected);
- int t2[10]={1,2,3,44,55,95,96,97,98,99};
- int t2_expected=3;
- test(i++, t2, 10, t2_expected);
- int t3[10]={1,12,13,87,88,95,96,97,98,99};
- int t3_expected=3;
- test(i++, t3, 10, t3_expected);
- int t4[10]={1,20,30,40,50,51,96,97,98,99};
- int t4_expected=1;
- test(i++, t4, 10, t4_expected);
- int t5[16]={1,12,13,14,20,30,31,32,33,70,80,95,96,97,98,99};
- int t5_expected=3;
- test(i++, t5, 16, t5_expected);
- int t6[16]={1,3,4,12,13,14,20,30,31,70,80,85,86,87,88,99};
- int t6_expected=6;
- test(i++, t6, 16, t6_expected);
- return 0;
- }
- // Node.h
- #include <stdio.h>
- #ifndef NODE
- #define NODE
- class Node
- {
- public :
- int value;
- Node* parent;
- Node* left;
- Node* right;
- private:
- int level;
- // 打印树时的间隔比例因子
- static const int SPACE;
- int m_nMaxRow;
- public :
- Node(void);
- Node(int p_value);
- Node(Node * p_parent);
- Node(int p_value, Node * p_parent);
- // 删除树
- ~Node();
- // 打印树
- void PrintTree();
- // 打印树 x = col, y = row,不是很好看 :P
- void PrintTree(int x, int y, int z);
- // 获取树深度
- int GetLevel();
- // 找最小值节点
- Node* GetMinNode();
- // 找最大值节点
- Node* GetMaxNode();
- // 插入新数据
- Node* Insert(int p_value);
- };
- #endif
- // Node.cpp
- #include <stdio.h>
- #include <conio.h>
- #include "node.h"
- //using namespace std;
- const int Node::SPACE = 3;
- Node::Node(void)
- {
- m_nMaxRow = 0;
- parent = NULL;
- left = NULL;
- right = NULL;
- level = -1;
- }
- Node::Node(int p_value)
- {
- m_nMaxRow = 0;
- value = p_value;
- parent = NULL;
- left = NULL;
- right = NULL;
- level = -1;
- }
- Node::Node(Node * p_parent)
- {
- m_nMaxRow = 0;
- parent = p_parent;
- left = NULL;
- right = NULL;
- if(p_parent) level = p_parent->level+1;
- }
- Node::Node(int p_value, Node * p_parent)
- {
- m_nMaxRow = 0;
- value = p_value;
- parent = p_parent;
- left = NULL;
- right = NULL;
- if(p_parent) level = p_parent->level+1;
- }
- // 删除树
- Node::~Node()
- {
- if (this->left) {delete left; left = NULL;}
- if (this->right) {delete right; right = NULL;}
- }
- // 打印树
- void Node::PrintTree()
- {
- if (this->left) this->left->PrintTree();
- printf("%d ",this->value);
- if (this->right) this->right->PrintTree();
- }
- // 打印树
- // x = col, y = row
- void Node::PrintTree(int x, int y, int z)
- {
- if (x<0) x = 0;
- if (y>25) return;
- // if (y>m_nMaxRow) m_nMaxRow = y;
- if (this->left) this->left->PrintTree(x-SPACE-z-z, y+1, z-1);
- gotoxy(x, y);
- printf("%d ",this->value);
- if (this->right) this->right->PrintTree(x+SPACE+z+z, y+1, z-1);
- }
- // 获取树深度
- int Node::GetLevel()
- {
- // 如果已经初始化,直接返回
- if (level != -1)
- return level;
- // 否则算计深度
- level = 0;
- Node * p = this->parent;
- while(p != NULL)
- {
- level ++;
- p = p->parent;
- }
- return level;
- }
- // 找最小值节点
- Node* Node::GetMinNode()
- {
- if (this->left != NULL) return this->left;
- else return this;
- }
- // 找最大值节点
- Node* Node::GetMaxNode()
- {
- if (this->right != NULL) return this->right;
- else return this;
- }
- // 插入新数据
- Node* Node::Insert(int p_value)
- {
- if (p_value > this->value)
- {
- if(this->right) return this->right->Insert(p_value);
- else return this->right = new Node(p_value, this);
- }
- else
- {
- if(this->left) return this->left->Insert(p_value);
- else return this->left = new Node(p_value, this);
- }
- }