首页 > 试题广场 >

1929年,匈牙利作家Frigyes Karinthy在短篇

[问答题]

1929年,匈牙利作家Frigyes Karinthy在短篇故事‘Chains’中首次提出的“六度人脉理论”,是指地球上所有的人都可以通过六层以内的熟人链和任何其他人联系起来。我们定义A的‘一度好友’为A直接相识的好友,A的‘二度好友’为A一度好友的好友且与A不是一度好友,A的‘三度好友’为A二度好友的好友且与A不是一度好友、二度好友,以此类推。

在美团点评,小美、小团、小卓、小越、小诚、小信的好友关系见下图。

小团、小卓、小诚是小美的一度好友。小越、小信是小美的二度好友。小诚、小越是小信的一度好友,小美、小卓是小信的二度好友,小团是小信的三度好友。

现在已知每个人的所有一度好友,需要为‘小点’推荐10个六度好友,请使用伪代码写出计算方法。

 


用邻接表及广度优先算法
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

public class Graph {
    //边
    public class EdgeNode{
        int index;  //存储该顶点对应的下标
        int weight; //存储权重
    }

    ArrayList<String> pointList;    //顶点数组
    LinkedList<EdgeNode> edjList[]; //邻接表
    int pointNum;       //顶点数
    int edgeNum;        //边数


    public Graph(int n){
        pointList = new ArrayList<>(n);
        edjList = new LinkedList[n];
        for (int i = 0; i < n; i++) {
            edjList[i] = new LinkedList<>();
        }
        pointNum = n;
    }

    //添加一条顶点
    public void addPoint(String name){
        if(pointList.size() >= pointNum){
            System.out.println("point array full");
            return ;
        }
        if(pointList.indexOf(name) != -1){
            System.out.println("已经存在"+name);
            return ;
        }
        pointList.add(name);
    }

    public String getName(int index){
        return pointList.get(index);
    }

    //添加一条边
    public void addEdge(String name1, String name2, int weight){

        int i = pointList.indexOf(name1);
        if(i == -1){
            System.out.println("not find nam1="+name1);
            return ;
        }
        int j = pointList.indexOf(name2);
        if(j == -1){
            System.out.println("not find name2="+name2);
            return ;
        }

        EdgeNode edge = new EdgeNode();
        edge.index = j;
        edge.weight = weight;
        edjList[i].add(edge);
        edgeNum++;

        //加入另一个边 (无向边 两边都加)
        edge = new EdgeNode();
        edge.index = i;
        edge.weight = weight;
        edjList[j].add(edge);
        edgeNum++;
    }

    public void printAll(){
        for (String s : pointList) {

        }
        for (int i=0;i<pointList.size();i++) {
            System.out.print("节点"+pointList.get(i) +"边为:");
            for (EdgeNode edgeNode : edjList[i]) {
                System.out.print(pointList.get(edgeNode.index)+" ");
            }
            System.out.println("");
        }
    }

    /**
     * 广度遍历
     * @param name
     */
    public void BSTTraverse(String name){
        LinkedList<Integer> queue = new LinkedList();

        //找到name
        int i = pointList.indexOf(name);
        if(i == -1){
            System.out.println("not find name="+name);
            return ;
        }
        int[] a = new int[pointNum];
        for (int j = 0; j < pointNum; j++) {
            a[j] = 0;
        }

        a[i] = 1;
        LinkedList<EdgeNode> list = edjList[i];
        for (EdgeNode edgeNode : list) {
            queue.addLast(edgeNode.index);
            a[edgeNode.index] = 1;
        }
        while(queue.size() != 0){
            //从queue中拿出一个节点
            i = queue.removeFirst();
            System.out.println("遍历 " + pointList.get(i));

            list = edjList[i];
            for (EdgeNode edgeNode : list) {
                if(a[edgeNode.index] != 1){
                    queue.addLast(edgeNode.index);
                    a[edgeNode.index] = 1;
                }
            }
        }
    }


    public class Node{
        int index;
        int deep;
    }

    /**
     * 根据深度获取好友队列
     * @param name
     * @param deep 获取1度好友 则深度为2
     * @return
     * 采用广度优先算法
     */
    public LinkedList<Node> getQueueByDeep(String name, int deep){
        LinkedList<Node> queue = new LinkedList();
        //找到name
        int i = pointList.indexOf(name);
        if(i == -1){
            System.out.println("not find name="+name);
            return null;
        }
        int[] a = new int[pointNum];
        for (int j = 0; j < pointNum; j++) {
            a[j] = 0;
        }
        Node node = new Node();
        node.index = i;
        node.deep = 1;
        queue.addLast(node);
        a[i] = 1;

        while(queue.size() != 0){
            //从queue中拿出一个节点
            node = queue.getFirst();
            if(node.deep == deep){
                return queue;
            }
            queue.removeFirst();
            //System.out.println("遍历 " + pointList.get(node.index).data);

            List<EdgeNode> list = edjList[node.index];
            for (EdgeNode edgeNode : list) {
                if(a[edgeNode.index] != 1){
                    Node temp = new Node();
                    temp.index = edgeNode.index;
                    temp.deep = node.deep+1;
                    queue.addLast(temp);
                    a[edgeNode.index] = 1;
                    System.out.println("deep="+temp.deep + pointList.get(edgeNode.index));
                }
            }
        }
        return null;
    }

    public static void main(String[] args) throws Exception{

        Graph g = new Graph(7);
        g.addPoint("小团");
        g.addPoint("小美");
        g.addPoint("小诚");
        g.addPoint("小信");
        g.addPoint("小卓");
        g.addPoint("小越");

        g.addPoint("小孩");

        g.addEdge("小团", "小美", 1);
        g.addEdge("小卓", "小美", 1);
        g.addEdge("小诚", "小美", 1);
        g.addEdge("小团", "小卓", 1);
        g.addEdge("小诚", "小信", 1);
        g.addEdge("小信", "小越", 1);
        g.addEdge("小卓", "小越", 1);

        g.addEdge("小信", "小孩", 1);

        g.printAll();

        g.BSTTraverse("小美");

        int deep = 4;
        LinkedList<Node> queue = g.getQueueByDeep("小美", 4);
        if(queue == null){
            System.out.println("没有"+(deep-1)+"度好友");
        }else{
            for (Node node : queue) {
                System.out.println(node.deep+"度好友为 "+ g.getName(node.index));
            }
        }
    }
}


发表于 2020-12-30 23:35:09 回复(0)
对人体
发表于 2020-03-26 23:35:59 回复(0)
跑一遍最短路(bfs即可),离小点距离为6的人
发表于 2023-03-10 19:03:42 回复(0)
1. 首先要把所有人物名字都放到一个List<String>列表p中。
2. 之后要想办法把每个人之间的关系建立出来。使用一个List<Integer>[]  list,其中数组下标表示该人物姓名在p中的位置,存储的元素则是该人物一度好友的下标。如:小美的下标为1,一度好友有小团(下标2),小城(下标3)。则list[1].add(2);list[1].add(3)。
3. 定义一个队列,Queue<Node> 其中node有两个属性,index下标,deep深度。把要查找的人物,放入队列中(下标根据p查找,deep初始为1)。将该人物list中的元素入队,深度+1。如果已经遍历过该元素则跳过。如果达到要求深度则直接返回queue

发表于 2022-03-13 10:31:23 回复(0)
dict1 := make(map[string]map[string]struct{}{})
dict2 := make(map[string]map[string]struct{}{})
dict3 := make(map[string]map[string]struct{}{})
dict4 := make(map[string]map[string]struct{}{})
dict5 := make(map[string]map[string]struct{}{})
for people{
for people's friends{
 dict1[people's name] [people's friend] = struct{}
}
}
for people{
if dict1["小点"]["people's name] == struct{}{  //如果是小点朋友,跳过
delete people // 把这个人从待选集合中删掉
continue
}else{
for name,v  range dict1["小点"]{
if dict1[name][people's name] == struct{}{
dict2["小点"]["people's name] = struct{}    //生成二度朋友
delete people
}
//以此类推,找到六度朋友
  
发表于 2022-02-27 15:16:11 回复(0)
所以答案呢?

发表于 2021-09-14 11:03:14 回复(0)
说一下我的想法,交流一下。
‘小点’为起始点,广度优先遍历,生成遍历树(无权图可以生成最小生成树),输出层数为6的结点。
数据结构使用邻接表,边表节点由 一度好友 组成。
java 中,邻接表可以用 linkedlist(边表) 加 hashmap (顶点表)实现。
发表于 2020-11-18 20:27:10 回复(0)
加入小点的一度好友,然后再对一度好友的一度好友进行搜索,如果不存在小点的一度好友之中,那就是小点的二度好友。这样循环下去,就可以找到六度好友。可以利用HashMap实现。
编辑于 2020-08-29 22:27:38 回复(0)

发表于 2020-07-20 08:25:32 回复(0)
class People{
	int layer;
	People next;
	*** ***;
}
// 目标层数
int desLayer=6;
People people, firstPeople;
people.layer = 0;
// 把第一个人加入队列,执行一个广搜
queue.offer(people);
while(!queue.isEmpty()){
	// firstPeople代表当前所在第i层
	firstPeople = queue.poll();
	int layer_ = firstPeople.layer;
	if(layer_ == desLayer){
		// 如果第i-1层已经全部搜索完毕,开始搜索第i层第一个
		break;
	}
	// 如果该节点在之前已经被扫描到则不用再加入,因为firstPeople.layer一定大于等于set中的那个节点的layer
	if(set.contains(firstPeople)){
		;
	}else{
		People tPeople = firstPeople;
		// 将这个节点下一层节点加入队列
		while(tPeople.hasNext()){
			People nextPeople = tPeople.next();
			nextPeople.layer = layer_+1;
			queue.offer(nextPeople);
			tPeople = tPeople.next();
		}
		// 记录从第一层-到i-1层的节点
		set.add(firstPeople);
	}
}
// 满足目标层
if(!queue.isEmpty()){
	//将队列中第i层节点全部加入,包括firstPeople
	iSet.addAll(queue);
	iSet.add(firstPeople);
}
// 与之前的记录的做一个差集
iSet = iSet.sub(set);

发表于 2020-03-14 12:29:12 回复(1)