某企業校招的編程題目,問題大致描述如下:
有一棵樹有N個節點,其中有K個節點有蘋果。在每條邊至多走一次的情況下,最多可以摘到的蘋果數。其中,可以從任意一個節點出發。
實現代碼如下:
import java.util.*;
public class Main {
public static void main(String[] args) {
Solution s=new Solution();
// int a[]={2,3,4};
// int b[][]={{1,2},{1,3},{1,4}};
int a[]={2,3,5,6};
int b[][]={{1,2},{1,3},{2,5},{2,4},{3,6},{3,7},{6,8}};
int res = s.collectApples(8, 4,a ,b);
System.out.println(res);
}
}
class Node{
private boolean at;//是否訪問過
private int num;//節點值
private boolean apple;//是否有蘋果
//保存關聯節點
List<Node> childs=new ArrayList<Node>();
public Node(Node p, boolean a,int num){
this.apple=a;
this.num=num;
}
public void add(Node node){
this.childs.add(node);
}
public boolean isAccess(){
return this.at;
}
public boolean existApple(){
return this.apple;
}
public void noAccess(){
this.at=false;
}
public void access(){
this.at=true;
}
//打印時的合理輸出
public String toString(){
return String.valueOf(num);
}
//測試節點內部構造的關聯節點是否正確
public void printChilds(){
for (int i = 0; i < childs.size(); i++) {
System.out.print(childs.get(i)+",");
}
System.out.println();
}
}
class Solution
{
int collectApples(int N, int K, int[] applesAtNodes, int[][] connectedNodes)
{
Map<Integer, Node> map=new HashMap<Integer, Node>();
//首先實例化有蘋果的節點
for(int i=0;i<K;i++){
int cur = applesAtNodes[i];
Node node=new Node(null,true,cur);
map.put(cur,node);
}
int m=connectedNodes.length;
// System.out.print(map);
//根據是否有邊,構造圖結構
for(int i=0;i<m;i++){
int pNum=connectedNodes[i][0];
int cNum=connectedNodes[i][1];
Node pn;
Node cn;
if(map.containsKey(pNum)){
pn=map.get(pNum);
}else{
pn=new Node(null,false,pNum);
map.put(pNum, pn);
}
if(map.containsKey(cNum)){
cn=map.get(cNum);
}else{
cn=new Node(pn,false,cNum);
map.put(cNum, cn);
}
//通過任何一方找到另一方,必須各自擁有對方
pn.add(cn);
cn.add(pn);
}
int max=-1;
//System.out.println(map);//打印構造的map
for(Node node:map.values()){
//測試構造的圖結構是否正確
// System.out.println("node:"+node);
// node.printChilds();
//重新一輪之前,重置所有節點未遍歷過
resetNoAccess(map);
int num1=search(node);//計算以從節點出發的摘取的最大蘋果樹
// System.out.println("num1:"+num1+",max:"+max);
max=Math.max(max,num1);
}
return max;
}
//重置map中節點的是否訪問屬性
void resetNoAccess(Map<Integer, Node> map){
for(Node node:map.values()){
node.noAccess();
}
}
//以某個節點出發遞歸,計算最大可摘取蘋果樹
int search(Node node){
if(node==null || node.isAccess())return 0;
node.access();
//深度遍歷未訪問的關聯節點
int num2=0;
for(int i=0;i<node.childs.size();i++){
int cur=search(node.childs.get(i));
num2=Math.max(cur,num2);
}
if(node.existApple())return 1 + num2;//有蘋果的情況
else return num2;
}
}