CSDN-CSDN社区-专题开发/技术/项目-数据结构与算法

收藏 [推荐] 前几天去面试的一道题目,没做出来,郁闷,大家帮看看[问题点数:100]

  • gerald_xiao
  • (心在车站)
  • 等 级:
  • 结帖率:
楼主发表于:2009-06-24 19:13:04




题目:

给定一个有n个顶点的图G=(V,E),请设计一个算法计算G中两两连接的4个顶点(即四边形)的数目,

如果没有,输出NOT EXIST,说明你所使用的方法以及时间和空间复杂度。


附录:
    由于去的是一家从事算法开发的公司,待遇很不错,但上面的一道题目,偶没做出来,郁闷,大家帮看看。
   
    如果有机会复试,肯定要分析初试的题目的。大家帮帮忙,不胜感激!


回复次数:190
#1楼 得分:0回复于:2009-06-24 19:14:52
我觉得应该用图的深度搜索的,但一下子也想不出完整的解答。
#2楼 得分:0回复于:2009-06-24 19:26:43
CSDN的牛人们,你们在哪里?
#3楼 得分:0回复于:2009-06-24 20:57:50
用临接矩阵表示图,然后枚举跟某个点相连的所有点中,是否有两点相连。很直观的想法。O(n^3)
#4楼 得分:0回复于:2009-06-24 22:30:00
关注之。

如果两条边交叉算不算四边形啊?
#5楼 得分:0回复于:2009-06-25 09:15:48
感觉3楼的方法不错,有双向搜索的感觉,不过不知道abcd同bcda算1条还是2条。
如果算1条的话,在枚举顺序上可以做一些小小的优化,不过整体复杂度是一样的。

解的数量级摆在那里呢,复杂度基本上很难再降了。
#6楼 得分:0回复于:2009-06-25 11:42:53
期待中......
  • elephont9527用户头像
  • elephont9527
  • (此人未死,无事莫烧纸)
  • 等 级:
#7楼 得分:0回复于:2009-06-25 15:04:24
得到的四边形还要排除2种特例:
1,任意3点不在同一直线上,否则这时候4边形退化为3角形。可以计算每一条边的斜率,比较邻接的2条边斜率
2,2条不相邻的边相交,这种情况应该也不算4边形。排除1的情况下,对于两辆连接的点序ABCDA,判断AB与CD,BC与DA是否相交
  • g_idea用户头像
  • g_idea
  • (埋汰福音)
  • 等 级:
#8楼 得分:0回复于:2009-06-25 15:18:04
用一个4层循环,依次取4个点判断不可以吗?
#9楼 得分:0回复于:2009-06-25 16:31:23
对于顶点A找每一个对角顶点(经过一个结点的过达的),路径条数为N(N>=2),相关四边形数为((N-1)*N)/2,从图中删除这个顶点A,循环找下一个顶点
#10楼 得分:0回复于:2009-06-25 16:44:28
找出所有点与点之间,长度为2的路径,设A到B的路径有N条,则C(n,2)就是对应的四边形个数。

跟9楼的方法好像类似,这两天总是别人说了,我才想起来。
#11楼 得分:0回复于:2009-06-25 17:05:42
哈哈哈
有规律,用递归就可以。但是用时间复杂度计算发现递归不够合理,还有其他的解决办法
#12楼 得分:0回复于:2009-06-25 17:55:43
不懂,帮顶
#13楼 得分:0回复于:2009-06-26 07:21:15
1.从任一点开始,对所有剩余N-1个点两两连线,计算该直线方程y=ax+b,记录(a,b)并按顺序插入一链表,节点有三个数,(a,b,n)其中n记录该直线上点的个数。 (O(N^2))
2.如果只有一直线,显然返回0
3.遍历两两直线,如两直线(a1,b1,n1)和(a2,b2,n2)平行或交点不为上述N顶点之一,则有四边形个数为(n1!*n2!)/(4*(n1-2)!*(n2-2)!) (组合公式,不会忘了吧?),如果交点是顶点,则判断仅在n1>2且n2>2的情况下有四边形个数为((n1-1)!*(n2-1)!)/(4*(n1-3)!*(n2-3)!) (该步复杂度为O(N^2))
4.统计上述所有四边形个数则为结果

综合复杂度为O(N^2)

不知有没有更好的算法?
#14楼 得分:0回复于:2009-06-26 07:50:07

哦,LZ说的是图,也就是说生成的四边形的四个顶点两两间必须存在联通路径是吧。那么稍稍简单一些:

1.从任一点开始,遍历该顶点上的路径,计算该路径所在直线方程y=ax+b,记录(a,b)并插入一链表,节点有三个数,(a,b,n)其中n记录该直线上路径的个数。 (O(N^2))
2.如果只有一直线,显然返回0
3.遍历两两直线,如两直线(a1,b1,n1)和(a2,b2,n2)平行(a1==a2)或交点不为上述N顶点之一,则有四边形个数为(n1×n2),如果交点是顶点,则判断仅在n1>1且n2>1的情况下有四边形个数为(n1-1)*(n2-1) (该步复杂度为O(N^2))

4.统计上述所有四边形个数则为结果


原理:不同直线上非交点的任意两点必然可以形成一个四边形
#15楼 得分:0回复于:2009-06-26 16:17:43
mark
#16楼 得分:0回复于:2009-06-26 16:33:52
我的思路是:
对于一个顶点v,
1、若它的相邻顶点数量小于2个,那么它不在任意一个四边形中
2、若它的相邻顶点数大于等于2,找出它的任意两个相邻顶点 v1 和 v2,找出 v1 和 v2 的公共相邻顶点 v3 (不包括v), 这时候 v v1 v2 v3 就构成了一个四边形,
#17楼 得分:0回复于:2009-06-26 16:34:22
我的思路是:
对于一个顶点v,
1、若它的相邻顶点数量小于2个,那么它不在任意一个四边形中
2、若它的相邻顶点数大于等于2,找出它的任意两个相邻顶点 v1 和 v2,找出 v1 和 v2 的公共相邻顶点 v3 (不包括v), 这时候 v v1 v2 v3 就构成了一个四边形,
#18楼 得分:0回复于:2009-06-26 17:01:34
题目要求是4个顶点两两连通,因此就一个点一个点的确定。

对于每一个顶点,做一次循环
for 每个顶点 {
    1、确定第一个顶点,假设是A,也就是说接下来找到的四边形中肯定有点A。
    2、确定第二个顶点,这个很简单,和点A相连的点都是的,但是这些点应该是可用的顶点,假设存在数组link_A[]中。
    3、确定第三个顶点并同时找第四个点,通过和A相连的点找。假设A和B、A和C相连,我们就依次通过B、C找。在通过B找的时候,首先判断点B是否和link_A[]中的其他点相连(这些点本次循环可用),如果不相连,则绝对不会存在含有边AB、且满足题目要求的四边形;如果存在,假设是点C,此时AB、AC、BC都相连,则从和B相连的点中找第四个点,假设存在点D,满足AD、CD相连,则ABCD是一个满足要求的四边形。对点B处理完后,标记点B本次循环不可用,这样就不会重复了。
    4、找到所有含有点A、且满足要求的四边形后,就将A标记以后都不可用。
}

时间复杂度:V*G

#19楼 得分:0回复于:2009-06-26 23:47:57
图是抽象的吧,感觉与顶点坐标无关的,我也没见过有顶点坐标的图,呵呵
#20楼 得分:0回复于:2009-06-27 02:09:44
我写了一个。 图是用邻接矩阵来保存和输入的,顶点我这里是默认生成的,用 0 到 n-1 来表示,
C/C++ code
#include <stdio.h> #include <stdlib.h> /*定义图的最大顶点数,它要大于等于具体图的顶点数n*/ #define MaxVertexNum 15 /*定义图的最大边数,它要大于等于具体图的边数e*/ #define MaxEdgeNum 20 /*定义 MaxValue 为一个全局整型常量,其值要大于邻接矩阵中所有有效值之和*/ #define MaxValue 1000 /*定义图中顶点数据的类型 VertexType 为整型*/ typedef int VertexType; /*定义 GV 为存储顶点信息的数组*/ VertexType GV[MaxVertexNum]; /*定义 GA 为存储邻接矩阵的数组*/ int GA[MaxVertexNum][MaxVertexNum]; /*定义保存图顶点访问标记的数组,每个元素的初值均为0 */ int visited[MaxVertexNum] = {0}; // 全局变量 sum 用来保存四边形数量 int sum = 0; //i 是最开始出发的顶点,n 为图的顶点数 void findQuadrilateral(int i, int n) { int j, k, m; // 标记第 i 个顶点已经访问 visited[i] = 1; for(j=0; j<n; j++) { /* 当i与j相邻时,并且j未被访问,找出另外一个与i相邻的顶点 */ if(GA[i][j] == 1 && visited[j] == 0) for(k=j+1; k<n; k++) { /* 当i与k相邻时,并且k未被访问,找出 j , k 的公共相邻的顶点 */ if(GA[i][k] == 1 && visited[k] == 0) for(m=0; m<n; m++) { // m 与 j,k 相邻且未被访问过,则构成一个新的四边形 i j k m if(GA[j][m] == 1 && GA[k][m] == 1 && visited[m] == 0) { sum += 1; printf("存在四边形: %d %d %d %d \n", i, j, k, m); } } } } } void main() { int n, e; int i, j, k; int min = 1000; /*输入一个图的顶点数和边数*/ printf("输入待处理图的顶点数和边数:"); scanf(" %d %d", &n, &e); /*根据键盘输入建立图的邻接矩阵*/ /* 建立顶点数组 */ printf("输出 %d 个顶点数据\n", n); for(i=0; i<n; i++) { GV[i] = i; printf("%d ", i); } /* 初始化邻接矩阵数组 */ for(i=0; i<n; i++) { for(j=0; j<n; j++) { if(i == j) GA[i][j] = 0; // MaxValue 表示 i 与 j 不是直接相连的 else GA[i][j] = MaxValue; } } /* 建立邻接矩阵数组 */ printf("\n输入 %d 条无向边\n", e); for(k=1; k<=e; k++) { /*输入一条边的两端点序号i和j*/ scanf(" %d %d", &i, &j); /*置数组中相应对称元素的值为 1, 这时候表示 i 与 j 相连*/ GA[i][j] = GA[j][i] = 1; } /* 打印邻接矩阵 */ for(i=0; i<n; i++) { for(j=0; j<n; j++) printf("%4d ", GA[i][j]); printf("\n"); } for(i=0; i<n; i++) { findQuadrilateral(i, n); } printf("\总共有 %d 个四边形\n", sum); }
#21楼 得分:0回复于:2009-06-27 02:18:04
上面的代码求四边形数的复杂度是(O(N^4)),这里我没把邻接矩阵的相关操作写成方法(不知道怎么利用二维数组来作为函数的参数),希望能有高手帮忙改进下。
#22楼 得分:0回复于:2009-06-30 00:56:29
两两连接的4个顶点(即四边形)
后面的括号是误导吧,
两两连接不仅仅是能够构成4边形那么简单.


我的思路是
画圈,逐渐把外部的点一个一个地加为内部点.
在加之前判断一下 内部点和准备纳入内部的点是否有能够满足条件.有则统计.
至所有点都为内部点为止.

空间复杂度为V,
时间复杂度感觉应该是  V*E(没认真算)
用规划做.
  • xdbjzhhh用户头像
  • xdbjzhhh
  • (下雨时,她总是怕打雷.....)
  • 等 级:
#23楼 得分:0回复于:2009-07-02 11:03:17
我太差劲了,听天书似的
#24楼 得分:0回复于:2009-07-02 11:03:47
路过……
#25楼 得分:0回复于:2009-07-02 11:05:30
路过……
#26楼 得分:0回复于:2009-07-02 11:06:00
做个记号!

---------------------
磁力泵
排污泵
化工泵
螺杆泵
  • yaneng用户头像
  • yaneng
  • (呀能)
  • 等 级:
#27楼 得分:0回复于:2009-07-02 11:19:56
学习!!
#28楼 得分:0回复于:2009-07-02 11:23:09
学习下
#29楼 得分:0回复于:2009-07-02 11:27:31
mark,以后再看
#30楼 得分:0回复于:2009-07-02 11:30:26
路过。。。。。。。。。。。。。。。。。
#31楼 得分:0回复于:2009-07-02 11:32:47
牛人还是很多滴
#32楼 得分:0回复于:2009-07-02 11:33:59
标记一下,学习学习
#33楼 得分:0回复于:2009-07-02 11:44:57
這不是一個組合問題麼
CN4
#34楼 得分:0回复于:2009-07-02 11:51:58
学习!!!
#35楼 得分:0回复于:2009-07-02 11:54:34
学习下~
#36楼 得分:0回复于:2009-07-02 12:07:21
学习了
#37楼 得分:0回复于:2009-07-02 12:18:02
19楼 明显顶点坐标不必要 图是离散的拓扑结构
#38楼 得分:0回复于:2009-07-02 12:34:22
那段程序貌似运行不了哦
#39楼 得分:0回复于:2009-07-02 12:37:26
学习了啊。帮顶!!
#40楼 得分:0回复于:2009-07-02 12:39:48
看看
#41楼 得分:0回复于:2009-07-02 12:46:34
坐等高人
#42楼 得分:0回复于:2009-07-02 12:47:16
图是抽象的。
#43楼 得分:0回复于:2009-07-02 12:47:39
用组合公式算出总数,减去任意3点在同一直线上的情况
#44楼 得分:0回复于:2009-07-02 12:51:20
学习
#45楼 得分:0回复于:2009-07-02 13:24:00
就是有高人
#46楼 得分:0回复于:2009-07-02 13:27:06
mark 学习中,搞得我都想吧数据结构的书翻出来再看看咯……
  • whsxzh用户头像
  • whsxzh
  • (山寨程序员)
  • 等 级:
#47楼 得分:0回复于:2009-07-02 13:35:42
这个不是计算机题,是数学题
  • phommy用户头像
  • phommy
  • (顽石宫主)
  • 等 级:
#48楼 得分:0回复于:2009-07-02 13:37:35
两两连接的4个顶点(即四边形)的数目
---

这个要求是有问题的,两两连接和四边形(依次连接)不大一样

不过无论如何,判断是否满足“两两连接”或“四边形”的时间都是常数,最直接的想法是有C(n,4)种组合,依次验证。当然可以动态规划一下,不过时间复杂度还是O(n^4)。
#49楼 得分:0回复于:2009-07-02 13:49:32
答案出來了  卻沒看到給分~~~~~
#50楼 得分:0回复于:2009-07-02 13:53:54
搞算法的牛人阿~~~~~
#51楼 得分:0回复于:2009-07-02 13:56:20
拿分走人.
#52楼 得分:0回复于:2009-07-02 13:57:16
学习了,谢谢了!
#53楼 得分:0回复于:2009-07-02 14:28:28
难啊!
  • jaylongli用户头像
  • jaylongli
  • (思则变,变则通,通则灵。)
  • 等 级:
#54楼 得分:0回复于:2009-07-02 14:34:38
引用 2 楼 gerald_xiao 的回复:
CSDN的牛人们,你们在哪里?



C S D N==》床上等你?
#55楼 得分:0回复于:2009-07-02 14:58:26
都是强人呀,出这样的难题
亏他想的出来,
我可是想不出答案来!
太费脑筋了吧11
记得找工作的时候去一家管也公司也出过难题
至今我都没有想出来,关键是现在没有时间去想呀,每天都忙的不可开交呀!1
哈哈哈!
生产气体检测仪 气体报警器的这家公司就是一家在招人方面比较严格的公司,他们的网址是:http://www.hnccdq.com/
有这样兴趣的人可以看看!
#56楼 得分:0回复于:2009-07-02 14:58:36
顶下先
  • thinkc用户头像
  • thinkc
  • (【淡定】)
  • 等 级:
#58楼 得分:0回复于:2009-07-02 15:15:48
这个不是计算机题,是数学题,高中的排列组合,C(n,6)
#59楼 得分:0回复于:2009-07-02 15:23:34
找无向图中长度为L=4的环。其实L可以为大于等于3任何值。

C/C++ code
#include <vector> #include <stack> #include <map> template <typename G> int countCycle(G& g, int edges) { int count = 0; if (edges < 3) { // 3 edges is minimal condition return count; } typedef typename G::vertix_t * pVertix_t; typedef typename G::vertix_t::id_t vertix_id_t; typedef std::vector<pVertix_t> vertices_t; typedef std::stack<pVertix_t> stack_t; enum Status {NOT_VISITED, VISITED, DONE}; typedef std::map<vertix_id_t, Status> status_map; typedef std::map<vertix_id_t, size_t> depth_map; typedef depth_map::mapped_type depth_t; stack_t st; status_map verStatus; depth_map verDepth; vertices_t vertices = g.getAllVertices(); for (vertices_t::iterator it = vertices.begin(); it != vertices.end(); ++it) { pVertix_t pVer= *it; vertix_id_t id = pVer->getID(); if (verStatus[id] == NOT_VISITED) { depth_t depth(); verDepth[id] = depth; st.push(pVer); while (!st.empty()) { pVertix_t p = st.top(); st.pop(); id = p->getID(); if (verStatus[id] == VISITED) { verStatus[id] == DONE; } else if (verStatus[id] == NOT_VISITED) { // not visited verStatus[id] = VISITED; st.push(p); depth = verDepth[id] + 1; vertices_t cntVers = getConnectedVectix(p); for (vertices_t::iterator it2 = cntVers.begin(); it2 != cntVers.end(); ++it2) { pVertix_t cntVer = *it2; vertix_id_t id2 = cntVer->getID(); if (verStatus[id2] == VISITED) { // cycle if (edge == verDepth[id] - verDepth[id2] + 1)) { // find one ++count; } } else { verDepth[id2] = depth; st.push(cntVer); } } // for each connected vertices } // if visited or not } // while in stack not empty } } return count; }
#60楼 得分:0回复于:2009-07-02 15:26:14
同意其实是一个数学组合问题,C(n,4).
#61楼 得分:0回复于:2009-07-02 15:30:32
同意 两两连接和四边形(依次连接)不大一样 的提法
#62楼 得分:0回复于:2009-07-02 15:34:37
顶+mark
#63楼 得分:0回复于:2009-07-02 15:50:50
哇塞,感觉这个题目这么有深度啊
#64楼 得分:0回复于:2009-07-02 15:52:19
等待高人解答
#65楼 得分:0回复于:2009-07-02 15:58:52
汗啊 我先回家研究研究图形学 在搞这个算法
#66楼 得分:0回复于:2009-07-02 16:06:42
太高深啦  学习一下
#67楼 得分:0回复于:2009-07-02 16:20:42
mark
#68楼 得分:0回复于:2009-07-02 16:21:33
回去一问俺女朋友就会
#69楼 得分:0回复于:2009-07-02 17:00:31
也不是太懂  学习中
#70楼 得分:0回复于:2009-07-02 17:02:46
学习
#71楼 得分:0回复于:2009-07-02 17:12:33
学习
#72楼 得分:0回复于:2009-07-02 17:39:47
离散不行..
#73楼 得分:0回复于:2009-07-02 17:49:03
make for learning !
#74楼 得分:0回复于:2009-07-02 17:58:43
引用 7 楼 elephont9527 的回复:
得到的四边形还要排除2种特例:
1,任意3点不在同一直线上,否则这时候4边形退化为3角形。可以计算每一条边的斜率,比较邻接的2条边斜率
2,2条不相邻的边相交,这种情况应该也不算4边形。排除1的情况下,对于两辆连接的点序ABCDA,判断AB与CD,BC与DA是否相交


顶点不是在圆上吗?怎么会有三点在一条直线上,那不是三点确定一笨直线了吗?那还是圆 了吗??
#75楼 得分:0回复于:2009-07-02 18:00:01
哦,是我搞错了,我说的吗?圆怎么会计算出可以有多少个四边形呢?呵呵。

现在有点眉目了,等等达人的解。看看。呵。
#76楼 得分:0回复于:2009-07-02 18:21:20
.
#77楼 得分:0回复于:2009-07-02 18:47:47
学习下.....................
#78楼 得分:0回复于:2009-07-02 20:09:57
哪家算法公司呢? 可否告知啊
#79楼 得分:0回复于:2009-07-02 20:37:20
此图感觉不象是数据结构中的图。
#80楼 得分:0回复于:2009-07-02 22:13:55
实在是太高深了,看来这数据结构是何等的重要呀,可惜我读的这所学校并没有教这个。自学,看那些代码都看得头晕哪!后面还有一大堆框架之类的。。。。看来编程这条路不是那么好走呀。
#81楼 得分:0回复于:2009-07-02 22:19:13
个顶点的图G=(V,E),临接矩阵已经出来,剩下的就是矩阵相关搜索了!
  • wyp1986用户头像
  • wyp1986
  • (~易拉う罐で)
  • 等 级:
#82楼 得分:0回复于:2009-07-02 23:34:43
进来学习一下
#83楼 得分:0回复于:2009-07-03 08:35:34
学习一下
#84楼 得分:0回复于:2009-07-03 08:49:17
观摩了5分钟……题目还么看懂.......
  • xiabao用户头像
  • xiabao
  • (小军)
  • 等 级:
#85楼 得分:0回复于:2009-07-03 08:58:48
mark
#86楼 得分:0回复于:2009-07-03 09:14:03
是有点难度,搞得我郁闷了半小时。
#87楼 得分:0回复于:2009-07-03 10:38:22
这是“面试”题。对“面试”题而言,结果可能并不重要,重要的是你在面试过程中表现出来的内在的东西。
祝你成功。
#88楼 得分:0回复于:2009-07-03 10:51:00
太复杂了,不懂
#89楼 得分:0回复于:2009-07-03 11:43:35
学习了.不错啊
  • lllsui用户头像
  • lllsui
  • (lllsui)
  • 等 级:
#90楼 得分:0回复于:2009-07-03 11:55:09
up
#91楼 得分:0回复于:2009-07-03 12:19:15
学习下
#92楼 得分:0回复于:2009-07-03 12:29:06
厉害
#93楼 得分:0回复于:2009-07-03 12:30:54
最近也在看算法~ 很多不明`
#94楼 得分:0回复于:2009-07-03 15:24:09
做个标记
#95楼 得分:0回复于:2009-07-03 16:07:12
思考下,用最短路径怎么样? 取一个点,然后寻找经过三点的最短路径。然后判断三点不在一直线。 然后删除,取下一个点。这样怎么样? 
#96楼 得分:0回复于:2009-07-03 17:02:53
路过!顶下~~~
#97楼 得分:0回复于:2009-07-03 18:07:15
学习 下
#98楼 得分:0回复于:2009-07-03 18:19:24
乍一看 头都是大的
#99楼 得分:0回复于:2009-07-03 18:31:11
funny!!!!!!!!!!!
#100楼 得分:0回复于:2009-07-03 18:54:11
我发觉,我还有很多东西都不会啊!
相关问题
今天面试,郁闷,有个问题没回答出来,进来看看.NET技术/ ASP.NET ...
面试好多家都没录用,郁闷扩充话题/ 程序人生- CSDN社区community.csdn.net
我想了几个要开发的项目,结果一查,已经有人做出来了,很郁闷,该怎么 ...
昨天去微软面试了,有道题没做出来,大家帮忙想想一想软件工程/管理 ...
期末了!从老师那边套来的题目,帮帮忙! C/C++ / 新手乐园- CSDN社区 ...
请大家特别是长沙的XDJM们进来看看,要去面试了,紧张ing 扩充话题 ...