আমি এই পদ্ধতির মধ্যে অন্য পার্থক্য খুঁজে পেয়েছি। এটি দেখতে সহজ এবং গুরুত্বহীন মনে হচ্ছে, তবে আপনি সাক্ষাত্কারের জন্য প্রস্তুত হওয়ার সময় এটির একটি খুব গুরুত্বপূর্ণ ভূমিকা রয়েছে এবং এই বিষয়টি উত্থাপিত হয়, তাই নিবিড়ভাবে দেখুন।
সংক্ষেপে: 1) পুনরুক্তি পোস্ট-অর্ডার ট্র্যাভারসাল সহজ নয় - যা ডিএফটি আরও জটিল করে তোলে 2) চক্রগুলি পুনরাবৃত্তি সহ চেক করা সহজ করে তোলে
বিবরণ:
পুনরাবৃত্তির ক্ষেত্রে, প্রাক এবং পোস্ট ট্র্যাভারসালগুলি তৈরি করা সহজ:
একটি দুর্দান্ত স্ট্যান্ডার্ড প্রশ্নটি কল্পনা করুন: "টাস্ক 5টি কার্যকর করার জন্য কার্যকর করা উচিত এমন সমস্ত কার্যগুলি মুদ্রণ করুন, যখন কার্যগুলি অন্যান্য কাজের উপর নির্ভর করে"
উদাহরণ:
//key-task, value-list of tasks the key task depends on
//"adjacency map":
Map<Integer, List<Integer>> tasksMap = new HashMap<>();
tasksMap.put(0, new ArrayList<>());
tasksMap.put(1, new ArrayList<>());
List<Integer> t2 = new ArrayList<>();
t2.add(0);
t2.add(1);
tasksMap.put(2, t2);
List<Integer> t3 = new ArrayList<>();
t3.add(2);
t3.add(10);
tasksMap.put(3, t3);
List<Integer> t4 = new ArrayList<>();
t4.add(3);
tasksMap.put(4, t4);
List<Integer> t5 = new ArrayList<>();
t5.add(3);
tasksMap.put(5, t5);
tasksMap.put(6, new ArrayList<>());
tasksMap.put(7, new ArrayList<>());
List<Integer> t8 = new ArrayList<>();
t8.add(5);
tasksMap.put(8, t8);
List<Integer> t9 = new ArrayList<>();
t9.add(4);
tasksMap.put(9, t9);
tasksMap.put(10, new ArrayList<>());
//task to analyze:
int task = 5;
List<Integer> res11 = getTasksInOrderDftReqPostOrder(tasksMap, task);
System.out.println(res11);**//note, no reverse required**
List<Integer> res12 = getTasksInOrderDftReqPreOrder(tasksMap, task);
Collections.reverse(res12);//note reverse!
System.out.println(res12);
private static List<Integer> getTasksInOrderDftReqPreOrder(Map<Integer, List<Integer>> tasksMap, int task) {
List<Integer> result = new ArrayList<>();
Set<Integer> visited = new HashSet<>();
reqPreOrder(tasksMap,task,result, visited);
return result;
}
private static void reqPreOrder(Map<Integer, List<Integer>> tasksMap, int task, List<Integer> result, Set<Integer> visited) {
if(!visited.contains(task)) {
visited.add(task);
result.add(task);//pre order!
List<Integer> children = tasksMap.get(task);
if (children != null && children.size() > 0) {
for (Integer child : children) {
reqPreOrder(tasksMap,child,result, visited);
}
}
}
}
private static List<Integer> getTasksInOrderDftReqPostOrder(Map<Integer, List<Integer>> tasksMap, int task) {
List<Integer> result = new ArrayList<>();
Set<Integer> visited = new HashSet<>();
reqPostOrder(tasksMap,task,result, visited);
return result;
}
private static void reqPostOrder(Map<Integer, List<Integer>> tasksMap, int task, List<Integer> result, Set<Integer> visited) {
if(!visited.contains(task)) {
visited.add(task);
List<Integer> children = tasksMap.get(task);
if (children != null && children.size() > 0) {
for (Integer child : children) {
reqPostOrder(tasksMap,child,result, visited);
}
}
result.add(task);//post order!
}
}
দ্রষ্টব্য যে পুনরাবৃত্তির পোস্ট-অর্ডার-ট্র্যাভারসালটির পরবর্তী ফলাফলের বিপরীতের প্রয়োজন হয় না। শিশুরা প্রথম মুদ্রিত হয় এবং প্রশ্নটি আপনার টাস্কটি সর্বশেষে মুদ্রিত হয়। সবকিছু ঠিক আছে. আপনি একটি পুনরাবৃত্তিমূলক প্রাক-অর্ডার-ট্র্যাভারসাল করতে পারেন (উপরেও দেখানো হয়েছে) এবং এর জন্য ফলাফল তালিকার বিপরীতের প্রয়োজন হবে।
পুনরাবৃত্ত পদ্ধতির সাথে এত সহজ নয়! পুনরাবৃত্তির (একটি স্ট্যাক) পদ্ধতির ক্ষেত্রে আপনি কেবল প্রাক-অর্ডারিং-ট্র্যাভারসাল করতে পারেন, ফলে আপনি ফলাফলের অ্যারেটি বিপরীত করতে বাধ্য হয়েছেন:
List<Integer> res1 = getTasksInOrderDftStack(tasksMap, task);
Collections.reverse(res1);//note reverse!
System.out.println(res1);
private static List<Integer> getTasksInOrderDftStack(Map<Integer, List<Integer>> tasksMap, int task) {
List<Integer> result = new ArrayList<>();
Set<Integer> visited = new HashSet<>();
Stack<Integer> st = new Stack<>();
st.add(task);
visited.add(task);
while(!st.isEmpty()){
Integer node = st.pop();
List<Integer> children = tasksMap.get(node);
result.add(node);
if(children!=null && children.size() > 0){
for(Integer child:children){
if(!visited.contains(child)){
st.add(child);
visited.add(child);
}
}
}
//If you put it here - it does not matter - it is anyway a pre-order
//result.add(node);
}
return result;
}
দেখতে সহজ, না?
তবে কিছু সাক্ষাত্কারে এটি একটি ফাঁদ।
এটির অর্থ নিম্নলিখিত: পুনরাবৃত্তির পদ্ধতির সাথে, আপনি গভীরতা ফার্স্ট ট্র্যাভারসাল বাস্তবায়ন করতে পারেন এবং তারপরে আপনার প্রাক বা পোস্টের কোন আদেশ দরকার তা নির্বাচন করতে পারেন (কেবল "মুদ্রণ" এর অবস্থান পরিবর্তন করে, "ফলাফলের তালিকায় যোগ করার ক্ষেত্রে" আমাদের ক্ষেত্রে )। পুনরাবৃত্তির (একটি স্ট্যাক) পদ্ধতির সাহায্যে আপনি সহজেই কেবল প্রাক-অর্ডার ট্রভারসাল করতে পারেন এবং তাই যখন বাচ্চাদের প্রথমে মুদ্রণ করা প্রয়োজন (বেশিরভাগ পরিস্থিতি যখন আপনার নীচের নোডগুলি থেকে প্রিন্ট শুরু করতে হবে, উপরের দিকে যেতে হবে) - আপনি আছেন বিপদের. আপনার যদি সমস্যা হয় তবে আপনি পরে বিপরীত হতে পারেন, তবে এটি আপনার অ্যালগরিদমের সাথে যুক্ত হবে। এবং যদি কোনও সাক্ষাত্কারকারী তার ঘড়ির দিকে তাকিয়ে থাকে তবে এটি আপনার পক্ষে সমস্যা হতে পারে। পুনরাবৃত্ত পোস্ট-অর্ডার ট্র্যাভারসাল করার জটিল উপায় রয়েছে, সেগুলি বিদ্যমান, তবে এগুলি সহজ নয় । উদাহরণ:https://www.geeksforgeeks.org/iterative-postorder-traversal-using-stack/
সুতরাং, নীচের লাইন: আমি সাক্ষাত্কারের সময় পুনরাবৃত্তি ব্যবহার করব, এটি পরিচালনা করা এবং ব্যাখ্যা করা সহজ। আপনার যে কোনও জরুরি ক্ষেত্রে অর্ডার পোস্ট-অর্ডার ট্র্যাভার্সাল যাওয়ার সহজ উপায় আছে। পুনরাবৃত্তির সাথে আপনি যে নমনীয় নন।
আমি পুনরাবৃত্তি ব্যবহার করব এবং তারপরে বলব: "ঠিক আছে, তবে পুনরাবৃত্তি আমাকে ব্যবহৃত স্মৃতিতে আরও সরাসরি নিয়ন্ত্রণ সরবরাহ করতে পারে, আমি স্ট্যাকের আকারটি সহজেই পরিমাপ করতে পারি এবং কিছু বিপজ্জনক ওভারফ্লো বর্জন করতে পারি .."
পুনরাবৃত্তির আরও একটি প্লাস - কোনও গ্রাফের চক্র এড়ানো / লক্ষ্য করা সহজ।
উদাহরণ (প্রিউডোকোড):
dft(n){
mark(n)
for(child: n.children){
if(marked(child))
explode - cycle found!!!
dft(child)
}
unmark(n)
}