转载:http://zhan.renren.com/lichedu?gid=3602888498033254357&from=reblogSynFeed&ref=hotnewsfeed&sfet=3801&fin=0&fid=20211685290&ff_id=320147642

 

笔经面经分享之亚马逊笔试题第二弹。希望通过本帖,能够对正在找工作的同学或者将要找工作的同学提供微薄之力。

                                                                   --小站小编

笔试题

下面是来自于亚马逊的编程笔试题,感兴趣的同学可以先自己想想解题思路:

Please implement a simple logic rule, the input is a set of logic formula, the format is like a1,a2,a3,…,an->b, which means a1,a2,a3,…an can deduce b. It meets the following rules:

1. If A->B B->C then A->C

2. If A,B->C D->A then D,B->C

3. If A,B->C then B,A->C

 

The input contains two lines:

1. The first line contains n (100>n>0) base formulas, separated by spaces

2. The second line contains m (100>m>0) formulas that need to check true or false according to above n formulas, separated by spaces

 

The output should be m lines, if the i-th formula in the second line can be deduced by the n base formulas, the i-th line should be "true", otherwise, "false".

 

Each element is a case sensitive alphabet, to simplify the parsing work, “->” is replaced by ">", there might be more than 1 character on the left side and only one on the right side, the following is an example: A,B,C>D

 

Sample Input and Output

Input

A>B B>C

A>C

Output

true

 

Input

A,B>C D,E>A E>B

E,D>C F,E>C

Output

true

false

 

Input

A>B A,B>C

A>C

Output

true

 

Please complement the matchRule method in Solution class:

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStreamReader;

 

public class Solution {

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

InputStreamReader isr = new InputStreamReader(System.in);

BufferedReader br = new BufferedReader(isr);

 

String baseRules = br.readLine();

String checkingRules = br.readLine();

 

matchRule(baseRules, checkingRules);

 

br.close();

isr.close();

}

 

private static void matchRule(String baseRules, String checkingRules) {

 

}

}

 

--------------我是华丽丽的分隔线----------------

图简介

首先让我们对比一下几种数据结构:线性表,树,图。

 

在线性表中,数据元素之间是被串起来的,仅有线性关系,每个元素只有一个直接前驱和一个直接后继。比如说排队买票。

 

在树形结构中,数据元素之间有着明显的层次关系,并且每一层上的数据元素可能和下一层中多个元素相关,但只能和上一层中一个元素相关。比如说一对父母可以有多个孩子,但是每个孩子只能有一对父母。

 

图是一种较线性表和树更加复杂的数据结构。在图形结构中,结点之间的关系可以是任意的,图中任意两个数据元素之间都可能相关。比如说人与人之间的关系是一种复杂的多对多的关系,所以研究人际关系很自然地就会使用图这种数据结构。

 

图(Graph)是由顶点的有穷非空集合和顶点之间边的集合组成,通常表示为:G(V, E),其中,G表示一个图,V是图G中顶点的集合,E是图G中边的集合。

 

如果图中任意两个顶点之间的边是有方向的,则称该图为有向图,否则称该图为无向图。

拓扑排序简介

我们会把施工过程,生产流程,软件开发,教学安排等都当成一个项目工程来对待,所有的工程都可分为若干个“活动”的子工程。如下图所示:

这是使用大脑作为生物传感器来检测低血糖的流程图。从图的角度来看,它是一个有向图。在一个表示工程的有向图中,用顶点表示活动,用边表示活动之间的优先关系,这样的有向图是一个使用顶点表示活动的网,称为AOV网(Activity On Vertex Network)。AOV网中的边表示活动之间存在的某种制约关系。

 

G(V, E)是一个具有n个顶点的有向图,V中的顶点序列v1, v2, v3....vn, 满足若从顶点vivj有一条路径,则我们称这样的顶点序列为一个拓扑序列。

 

上图中这样的AOV网的拓扑序列不止一条。序列12345678是一个拓扑序列,12546378也是一条拓扑序列。

拓扑排序算法简介

AOV网进行拓扑排序的基本思路是:从AOV网中选择一个入度为0的顶点输出,然后删去此顶点,并删除该顶点指向其他顶点的边,继续重复此步骤,直到输出全部顶点或者AOV网中不存在入度为0的顶点为止。(注:入度是指一个活动的直接先决活动的数量,以上图中的活动7为例,它的入度为2,分别是活动3和活动6

回到笔试题

基础知识介绍完毕,如果大家还有不明白的地方,可以先找找相关的资料参考一下。

5.1 对题目的理解

要解决一个问题,首先需要明确问题:

输入n条(100>n>0)条正确的逻辑推导语句,m条(100>m>0)待检验的的逻辑推导语句。所以问题是如根据正确的推导语句判断待检验的逻辑推导语句的正确性。

 

逻辑推导语句的一个例子:A,B,C>D结合题目的内容,逻辑推导语句有如下特点:

1. 语句中的每个元素都是大小写敏感的字母

2. 左边是1个或多个字母,以逗号分隔

3. 右边有且仅有一个字母

4. 中间的推导符号为“>”

5.2 为什么可以使用拓扑排序可以解决问题

从题目中的几个例子可以看出,所谓的逻辑推导关系,其实也可以理解成AOV网中各个活动之间优先关系。正是因为有这个相似性,所以我们可以利用拓扑排序来解决这个问题。

5.3 使用拓扑排序解决问题

利用拓扑排序解决这个问题,我们的步骤应该是:

1. 逐条解析n条正确的逻辑推导语句,并生成一个AOV网拓扑结构

2. 逐条解析m条待检验的逻辑推导语句,使用拓扑排序算法逐条检验。

3. 输出检验结果

 

使用拓扑排序算法逐条检验一条逻辑推导语句的方法:

遍历逻辑推导语句左边的结点,对于每个结点,查看该结点在步骤1生成的AOV网中的入度是否为0,如果为0,则把该结点关联的所有结点的入度减1(相当于在AOV网中,把该结点指向其他结点的边删除掉,也就相当于将它从AOV网中删除掉),最后当遍历完毕时,查看逻辑推导语句右边的结点的入度是否为0,如果为0,则说明推导成功,该语句是正确的;否则该语句是错误的。

 

最后的实现代码(java)如下:

 

 
  
  1. private static void matchRule(String baseRules, String checkingRules) { 
  2.  
  3.         if (!validateInput(baseRules) || !validateInput(checkingRules)){ 
  4.  
  5.             return
  6.  
  7.         } 
  8.  
  9.          
  10.  
  11.         RuleTopology topology = new RuleTopology(baseRules); 
  12.  
  13.         List<String> result = topology.checkRules(checkingRules); 
  14.  
  15.         printResult(result); 
  16.  
  17.     } 
  18.  
  19.      
  20.  
  21.     static class RuleTopology { 
  22.  
  23.         static String RULE_SEPERATOR = " "
  24.  
  25.         static String RULE_CONDITION_SEPERATOR = ","
  26.  
  27.         static String RULE_DEDUCTION_SIGNAL  = ">"
  28.  
  29.         static String RULE_RESULT_TRUE = "true"
  30.  
  31.         static String RULE_RESULT_FALSE = "false"
  32.  
  33.          
  34.  
  35.         Map<VertexNode, Set<VertexNode>> topology = null
  36.  
  37.          
  38.  
  39.         public RuleTopology(String baseRules) { 
  40.  
  41.             buildTopology(baseRules.split(RULE_SEPERATOR)); 
  42.  
  43.         } 
  44.  
  45.          
  46.  
  47.         public List<String> checkRules(String checkingRules) { 
  48.  
  49.             List<String> result = new ArrayList<String>(); 
  50.  
  51.              
  52.  
  53.             for (String rule : checkingRules.split(RULE_SEPERATOR)) { 
  54.  
  55.                 result.add(checkRule(deepCopyTopology(), rule)); 
  56.  
  57.             } 
  58.  
  59.              
  60.  
  61.             return result; 
  62.  
  63.         } 
  64.  
  65.          
  66.  
  67.         public VertexNode getNode(Map<VertexNode, Set<VertexNode>> topology, String name) { 
  68.  
  69.             VertexNode colusionNode = null
  70.  
  71.             Set<VertexNode> topologyNodes = topology.keySet(); 
  72.  
  73.             for (VertexNode node : topologyNodes) { 
  74.  
  75.                 if (node.getName().equals(name)) { 
  76.  
  77.                     colusionNode = node; 
  78.  
  79.                     break
  80.  
  81.                 } 
  82.  
  83.             } 
  84.  
  85.             return colusionNode; 
  86.  
  87.         } 
  88.  
  89.          
  90.  
  91.         String checkRule(Map<VertexNode, Set<VertexNode>> topology, String rule) { 
  92.  
  93.             //There's two parts of a rule, e.g. A,B>C: 
  94.  
  95.             //condition part: A,B 
  96.  
  97.             //conclusion part: C 
  98.  
  99.             String[] parts = rule.split(RULE_DEDUCTION_SIGNAL); 
  100.  
  101.             String[] conditionPart = parts[0].split(RULE_CONDITION_SEPERATOR); 
  102.  
  103.             String conclusionPart = parts[1]; 
  104.  
  105.              
  106.  
  107.             //If the input number of VertexNode with the same name as 
  108.  
  109.             //conclusionPart is zero from the beginning, then return false, 
  110.  
  111.             //because in this situation the rule can not be checked based 
  112.  
  113.             //on the base rules. 
  114.  
  115.             VertexNode colusionNode = getNode(topology, conclusionPart); 
  116.  
  117.             if (colusionNode.getInNum() == 0) { 
  118.  
  119.                 return RULE_RESULT_FALSE; 
  120.  
  121.             } 
  122.  
  123.              
  124.  
  125.             //For each VertexNode with the same name in the conditionPart, 
  126.  
  127.             //decrease the input number of each VertexNode it connected. 
  128.  
  129.             for (String nodeName : conditionPart) { 
  130.  
  131.                 VertexNode findedNode = getNode(topology, nodeName); 
  132.  
  133.                  
  134.  
  135.                 if (findedNode != null) { 
  136.  
  137.                     decreaseConVexInNum(topology, findedNode); 
  138.  
  139.                 } 
  140.  
  141.             } 
  142.  
  143.              
  144.  
  145.             //Finally, all the input number of each VertexNode in topology 
  146.  
  147.             //have been decreased, then to see whether the input number 
  148.  
  149.             //of the VertexNode with the same name as conclusionPart is 
  150.  
  151.             //zero. 
  152.  
  153.             return colusionNode.getInNum()==0?RULE_RESULT_TRUE:RULE_RESULT_FALSE; 
  154.  
  155.         } 
  156.  
  157.          
  158.  
  159.         /** 
  160.  
  161.          * A VertexNode may have some connected VertexNodes, decrease the 
  162.  
  163.          * input number of a VertexNode may trigger the input number of 
  164.  
  165.          * its connected VertexNodes to be zero 
  166.  
  167.          * @param topology 
  168.  
  169.          * @param node 
  170.  
  171.          */ 
  172.  
  173.         void decreaseConVexInNum(Map<VertexNode, Set<VertexNode>> topology, VertexNode node) { 
  174.  
  175.             if (node.getInNum() == 0) { 
  176.  
  177.                 Set<VertexNode> edgeNodes = topology.get(node); 
  178.  
  179.                 for (VertexNode edgeNode : edgeNodes) { 
  180.  
  181.                     edgeNode.decreaseInNum(); 
  182.  
  183.                     decreaseConVexInNum(topology, edgeNode); 
  184.  
  185.                 } 
  186.  
  187.             } 
  188.  
  189.         } 
  190.  
  191.          
  192.  
  193.         /** 
  194.  
  195.          * Used to deep copy topology. To check the rules in checkingRules,  
  196.  
  197.          * it needs to change the topology. So before checking each rule, 
  198.  
  199.          * we should deep copy the topology to keep the original topology 
  200.  
  201.          * unchanged. 
  202.  
  203.          * @return 
  204.  
  205.          */ 
  206.  
  207.         @SuppressWarnings("unchecked"
  208.  
  209.         Map<VertexNode, Set<VertexNode>> deepCopyTopology() { 
  210.  
  211.             Map<VertexNode, Set<VertexNode>> result = null
  212.  
  213.             ByteArrayOutputStream bos = new ByteArrayOutputStream(); 
  214.  
  215.             ObjectOutputStream oos = null
  216.  
  217.             ObjectInputStream ois = null
  218.  
  219.             try { 
  220.  
  221.                 oos = new ObjectOutputStream(bos); 
  222.  
  223.                 oos.writeObject(topology); 
  224.  
  225.                  
  226.  
  227.                 ois = new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray())); 
  228.  
  229.                 result = (Map<VertexNode, Set<VertexNode>>) ois.readObject(); 
  230.  
  231.             } catch (IOException e) { 
  232.  
  233.                 e.printStackTrace(); 
  234.  
  235.             } catch (ClassNotFoundException e) { 
  236.  
  237.                 e.printStackTrace(); 
  238.  
  239.             } 
  240.  
  241.             return result; 
  242.  
  243.         } 
  244.  
  245.          
  246.  
  247.         void buildTopology(String[] rules) { 
  248.  
  249.             topology = new HashMap<VertexNode, Set<VertexNode>>(); 
  250.  
  251.             for (String rule : rules) { 
  252.  
  253.                 parseRule(rule); 
  254.  
  255.             } 
  256.  
  257.         } 
  258.  
  259.          
  260.  
  261.         void parseRule(String rule) { 
  262.  
  263.             //There's two parts of a rule, e.g. A,B>C: 
  264.  
  265.             //condition part: A,B 
  266.  
  267.             //conclusion part: C 
  268.  
  269.             String[] parts = rule.split(RULE_DEDUCTION_SIGNAL); 
  270.  
  271.             String[] conditionPart = parts[0].split(RULE_CONDITION_SEPERATOR); 
  272.  
  273.             String conclusionPart = parts[1]; 
  274.  
  275.             //List ruleNodes contains all the names of nodes in the rule 
  276.  
  277.             //(includes condition part and conclusion part) 
  278.  
  279.             List<String> ruleNodeNames = new ArrayList<String>(Arrays.asList(conditionPart)); 
  280.  
  281.             ruleNodeNames.add(conclusionPart); 
  282.  
  283.              
  284.  
  285.             //If nodes in rule have not been exit in topology, add to 
  286.  
  287.             //topology 
  288.  
  289.             for (String nodeName : ruleNodeNames) { 
  290.  
  291.                 if ( !topology.containsKey(new VertexNode(nodeName)) ) { 
  292.  
  293.                     topology.put(new VertexNode(nodeName), new HashSet<VertexNode>()); 
  294.  
  295.                 } 
  296.  
  297.             } 
  298.  
  299.              
  300.  
  301.             //Find the VertexNode in topology with the same name with 
  302.  
  303.             //conclusionPart 
  304.  
  305.             VertexNode colusionNode = getNode(topology, conclusionPart); 
  306.  
  307.              
  308.  
  309.             //For each node in condition part, add the related VertexNode 
  310.  
  311.             //For node in conclusion part, increase the input number by 
  312.  
  313.             //one 
  314.  
  315.             for (String nodeName : conditionPart) { 
  316.  
  317.                 topology.get(new VertexNode(nodeName)).add(colusionNode); 
  318.  
  319.                 colusionNode.increaseInNum(); 
  320.  
  321.             } 
  322.  
  323.         } 
  324.  
  325.          
  326.  
  327.         static class VertexNode implements Serializable { 
  328.  
  329.             private static final long serialVersionUID = 2218090065058270731L; 
  330.  
  331.              
  332.  
  333.             private int inNum = 0
  334.  
  335.             private String name = ""
  336.  
  337.              
  338.  
  339.             public VertexNode(String name) { 
  340.  
  341.                 this.name = name; 
  342.  
  343.             } 
  344.  
  345.              
  346.  
  347.             public void increaseInNum() { 
  348.  
  349.                 ++inNum; 
  350.  
  351.             } 
  352.  
  353.             public void decreaseInNum() { 
  354.  
  355.                 --inNum; 
  356.  
  357.             } 
  358.  
  359.              
  360.  
  361.             public int getInNum() { 
  362.  
  363.                 return inNum; 
  364.  
  365.             } 
  366.  
  367.   
  368.  
  369.             public String getName() { 
  370.  
  371.                 return name; 
  372.  
  373.             } 
  374.  
  375.   
  376.  
  377.             @Override 
  378.  
  379.             public int hashCode() { 
  380.  
  381.                 final int prime = 31
  382.  
  383.                 int result = 1
  384.  
  385.                 result = prime * result + ((name == null) ? 0 : name.hashCode()); 
  386.  
  387.                 return result; 
  388.  
  389.             } 
  390.  
  391.   
  392.  
  393.             @Override 
  394.  
  395.             public boolean equals(Object obj) { 
  396.  
  397.                 if (this == obj) 
  398.  
  399.                     return true
  400.  
  401.                 if (obj == null
  402.  
  403.                     return false
  404.  
  405.                 if (getClass() != obj.getClass()) 
  406.  
  407.                     return false
  408.  
  409.                 VertexNode other = (VertexNode) obj; 
  410.  
  411.                 if (name == null) { 
  412.  
  413.                     if (other.name != null
  414.  
  415.                         return false
  416.  
  417.                 } else if (!name.equals(other.name)) 
  418.  
  419.                     return false
  420.  
  421.                 return true
  422.  
  423.             } 
  424.  
  425.         } 
  426.  
  427.     } 
  428.  
  429.      
  430.  
  431.     static void printResult(List<String> result) { 
  432.  
  433.         for (String item : result) { 
  434.  
  435.             System.out.println(item); 
  436.  
  437.         } 
  438.  
  439.     } 
  440.  
  441.      
  442.  
  443.     static boolean validateInput(String input) { 
  444.  
  445.         return true
  446.  
  447.     }

 

由于水平有限,错误在所难免,欢迎批评指正。谢谢!

 

 

——来自##17##朱元友