ব্যাকট্র্যাকিং এবং গভীরতার প্রথম অনুসন্ধানের মধ্যে পার্থক্য কী?
ব্যাকট্র্যাকিং এবং গভীরতার প্রথম অনুসন্ধানের মধ্যে পার্থক্য কী?
উত্তর:
ব্যাকট্র্যাকিং একটি আরও সাধারণ উদ্দেশ্যে অ্যালগরিদম।
গভীরতা-প্রথম অনুসন্ধানটি গাছের কাঠামোগুলি অনুসন্ধানের সাথে সম্পর্কিত ব্যাকট্র্যাকিংয়ের একটি নির্দিষ্ট ফর্ম। উইকিপিডিয়া থেকে:
একটি মূল থেকে শুরু হয় (গ্রাফের ক্ষেত্রে মূল হিসাবে কিছু নোড নির্বাচন করে) এবং ব্যাকট্র্যাকিংয়ের আগে প্রতিটি শাখা ধরে যতদূর সম্ভব অন্বেষণ করে।
এটি গাছের সাথে কাজ করার তার উপায়গুলির অংশ হিসাবে ব্যাকট্র্যাকিং ব্যবহার করে তবে গাছের কাঠামোর মধ্যে সীমাবদ্ধ।
ব্যাকট্র্যাকিংটি যে কোনও ধরণের কাঠামোতে ব্যবহার করা যেতে পারে যেখানে ডোমেনের অংশগুলি নির্মূল করা যেতে পারে - এটি লজিকাল গাছ হোক না। উইকির উদাহরণে দাবা বোর্ড এবং একটি নির্দিষ্ট সমস্যা ব্যবহার করা হয়েছে - আপনি একটি নির্দিষ্ট পদক্ষেপটি দেখতে পারেন এবং এটিকে মুছে ফেলতে পারেন, তারপরে পরবর্তী সম্ভাব্য পদক্ষেপে ব্যাকট্র্যাক করুন, এটিকে নির্মূল করুন ইত্যাদি can
আমি মনে করি অন্য সম্পর্কিত প্রশ্নের এই উত্তরটি আরও অন্তর্দৃষ্টি দেয়।
আমার জন্য, ব্যাকট্র্যাকিং এবং ডিএফএসের মধ্যে পার্থক্য হ'ল ব্যাকট্র্যাকিং একটি অন্তর্ভুক্ত গাছকে পরিচালনা করে এবং ডিএফএস একটি সুস্পষ্ট গাছের সাথে ডিল করে। এটি তুচ্ছ মনে হলেও এর অর্থ অনেক বেশি। যখন কোনও সমস্যার সন্ধানের স্থানটি ব্যাকট্র্যাকিংয়ের মাধ্যমে পরিদর্শন করা হয়, তখন অন্তর্নিহিত গাছটি এটির মাঝখানে পড়ে যায় এবং ছাঁটাই হয়। তবুও ডিএফএসের জন্য, যে গাছ / গ্রাফের সাথে এটি সম্পর্কিত তা স্পষ্টভাবে নির্মিত এবং অগ্রহণযোগ্য কেসগুলি ইতিমধ্যে ফেলে দেওয়া হয়েছে, অর্থাত্ ছাঁটাই করা হয়েছে, কোনও অনুসন্ধান করার আগেই।
সুতরাং, অন্তর্ভুক্ত গাছের জন্য ব্যাকট্র্যাকিং হ'ল ডিএফএস, যখন ডিএফএস ছাঁটাই ছাড়াই ব্যাকট্র্যাকিং করে।
ব্যাকট্র্যাকিং সাধারণত ডিএফএস প্লাস অনুসন্ধানের ছাঁটাই হিসাবে প্রয়োগ করা হয়। আপনি অনুসন্ধানের স্থান গাছের গভীরতা-প্রথম পথে আংশিক সমাধানগুলি তৈরি করে tra ব্রুট-ফোর্স ডিএফএস সমস্ত অনুসন্ধান ফলাফল তৈরি করতে পারে, এমনকি এমনগুলিও, যা ব্যবহারিকভাবে বোঝায় না। সমস্ত সমাধান (এন! বা 2 ^ n) তৈরি করতে এটি খুব অযোগ্যও হতে পারে। সুতরাং বাস্তবে আপনি ডিএফএস করার সময় আপনাকে আংশিক সমাধানও ছাঁটাই করতে হবে, যা প্রকৃত কার্যের প্রসঙ্গে অর্থবোধ করে না এবং আংশিক সমাধানগুলিতে মনোনিবেশ করে, যা বৈধ অনুকূল সমাধানের দিকে নিয়ে যেতে পারে। এটি আসল ব্যাকট্র্যাকিংয়ের কৌশল - আপনি যত তাড়াতাড়ি সম্ভব আংশিক সমাধানগুলি ত্যাগ করুন, একটি পদক্ষেপ ফিরে করুন এবং আবার স্থানীয় সর্বোত্তম খুঁজে পাওয়ার চেষ্টা করবেন।
বিএফএস ব্যবহার করে অনুসন্ধান স্পেস ট্রিকে অতিক্রম করতে এবং পথে ব্যাকট্র্যাকিং কৌশল বাস্তবায়িত করতে কিছুই থামে না, তবে এটি অনুশীলনের মধ্যে অর্থবোধ করে না কারণ আপনাকে সারিবদ্ধভাবে স্তরের স্তরে স্তরের স্তরের দ্বারা অনুসন্ধানের স্টেট স্তর সংরক্ষণ করতে হবে এবং গাছের প্রস্থ দ্রুততার সাথে উচ্চতা পর্যন্ত বৃদ্ধি পাবে, তাই আমরা খুব তাড়াতাড়ি অনেক জায়গা নষ্ট করব। এজন্য সাধারণত ডিএফএস ব্যবহার করে গাছগুলি ট্র্যাভার করা হয়। এই ক্ষেত্রে সন্ধানের স্ট্যাকটি স্ট্যাকের মধ্যে সংরক্ষণ করা হয় (কল স্ট্যাক বা স্পষ্ট কাঠামো) এবং এটি গাছের উচ্চতা অতিক্রম করতে পারে না।
আইএমএইচও, বেশিরভাগ উত্তর হ'ল মূলত অসম্পূর্ণ এবং / অথবা যাচাইয়ের কোনও রেফারেন্স ছাড়াই। সুতরাং আমাকে একটি রেফারেন্সের সাথে একটি খুব স্পষ্ট ব্যাখ্যা শেয়ার করি ।
প্রথমত, ডিএফএস হ'ল একটি সাধারণ গ্রাফ ট্রভারসাল (এবং অনুসন্ধান) অ্যালগরিদম। সুতরাং এটি যে কোনও গ্রাফে (বা এমনকি বন) প্রয়োগ করা যেতে পারে। গাছ একটি বিশেষ ধরণের গ্রাফ, তাই ডিএফএস গাছের জন্যও কাজ করে। সংক্ষেপে, আসুন আমরা এটি কেবল একটি গাছ বা পছন্দগুলির জন্য কাজ করে বলা বন্ধ করি।
[১] এর উপর ভিত্তি করে, ব্যাকট্র্যাকিং হল একটি বিশেষ ধরণের ডিএফএস যা মূলত স্থান (মেমরি) সংরক্ষণের জন্য ব্যবহৃত হয়। আমি যে পার্থক্যটি উল্লেখ করতে চাইছি তা বিভ্রান্ত বলে মনে হতে পারে যেহেতু গ্রাফ আলগোরিদিমগুলিতে আমরা নোডের সমস্ত নিকটবর্তী প্রতিবেশী ( গাছের জন্য এটি তাত্ক্ষণিক শিশুদের ) দেখার জন্য পুনরাবৃত্ত প্যাটার্ন ব্যবহার করতে অভ্যস্ত , আমরা প্রায়শই উপেক্ষা করি যে get_all_imedia_neighbors এর খারাপ প্রয়োগের ফলে অন্তর্নিহিত অ্যালগরিদমের মেমরির ব্যবহারে পার্থক্য হতে পারে।
আরও, যদি গ্রাফ নোডের শাখা ফ্যাক্টর বি, এবং ব্যাস এইচ ( একটি গাছের জন্য এটি গাছের উচ্চতা ) থাকে, তবে আমরা যদি নোডের পরিদর্শন করার প্রতিটি ধাপে সমস্ত নিকটবর্তী প্রতিবেশীদের সংরক্ষণ করি, মেমরির প্রয়োজনীয়তাগুলি বিগ-ও (বিএইচ) হবে । তবে, আমরা যদি একবারে কেবল একটি একক (তাত্ক্ষণিক) প্রতিবেশী গ্রহণ করি এবং এটি প্রসারিত করি, তবে মেমরির জটিলতা হ্রাস করে বিগ-ও (এইচ) হয়ে যায় । পূর্ববর্তী ধরণের বাস্তবায়নকে ডিএফএস হিসাবে আখ্যায়িত করা হয় , তবে পরবর্তী প্রকারটিকে ব্যাকট্রাকিং বলা হয় ।
এখন আপনি দেখুন, আপনি যদি উচ্চ স্তরের ভাষা নিয়ে কাজ করছেন তবে সম্ভবত সম্ভবত আপনি ডিএফএসের ছদ্মবেশে ব্যাকট্র্যাকিং ব্যবহার করছেন। তদতিরিক্ত, একটি খুব বড় সমস্যা সেট জন্য পরিদর্শন নোড ট্র্যাক রাখা সত্যিই মেমরি নিবিড় হতে পারে; get_all_imedia_neighbors (বা অসীম লুপ না পেয়ে কোনও নোডের পুনর্বিবেচনা পরিচালনা করতে পারে এমন অ্যালগোরিদম) এর সাবধানে নকশার জন্য আহ্বান জানানো ।
[1] স্টুয়ার্ট রাসেল এবং পিটার নরভিগ, কৃত্রিম বুদ্ধিমত্তা: একটি আধুনিক পদ্ধতি, তৃতীয় এড
সাধারণত, গভীরতার প্রথম-অনুসন্ধান একটি প্রকৃত গ্রাফ / বৃক্ষ কাঠামোর মাধ্যমে কোনও মান সন্ধানের মাধ্যমে পুনরাবৃত্তি করার একটি উপায়, যেখানে ব্যাকট্র্যাকিং কোনও সমস্যার জায়গার মধ্য দিয়ে পুনরাবৃত্তি করে সমাধানের সন্ধান করে। ব্যাকট্র্যাকিং একটি আরও সাধারণ অ্যালগরিদম যা অগত্যা গাছের সাথেও সম্পর্কিত নয়।
ডোনাল্ড নুথের মতে, এটি একই রকম। ডান্সিং লিঙ্কস অ্যালগরিদম সম্পর্কে তার কাগজের লিঙ্কটি এখানে দেওয়া হয়েছে, যা এন-কুইনস এবং সুডোকু সলভারের মতো "গাছহীন" সমস্যা সমাধানে ব্যবহৃত হয় solve
আমি বলব, ডিএফএস হল ব্যাকট্র্যাকিংয়ের বিশেষ রূপ; ব্যাকট্র্যাকিং হল ডিএফএসের সাধারণ রূপ is
আমরা যদি ডিএফএসকে সাধারণ সমস্যাগুলিতে প্রসারিত করি তবে আমরা এটিকে ব্যাকট্র্যাকিং বলতে পারি। যদি আমরা গাছ / গ্রাফ সম্পর্কিত সমস্যাগুলিতে ব্যাকট্র্যাকিং ব্যবহার করি তবে আমরা এটিকে ডিএফএস বলতে পারি।
তারা একই ধারণাটি অ্যালগরিদমিক দিকগুলিতে বহন করে।
গভীরতা হ'ল প্রথমে কোনও গাছের সন্ধান বা অনুসন্ধানের জন্য একটি অ্যালগরিদম। এখানে দেখুন । ব্যাকট্র্যাকিং একটি আরও বিস্তৃত শব্দ যা কোনও সমাধান প্রার্থী গঠিত হওয়ার পরে ব্যবহৃত হয় এবং পরে প্রাক্তন অবস্থায় ব্যাকট্র্যাকিংয়ের মাধ্যমে বাতিল করা হয়। এখানে দেখুন । গভীরতা প্রথম অনুসন্ধানটি প্রথমে একটি শাখা অনুসন্ধানের জন্য ব্যাকট্র্যাকিং ব্যবহার করে (সমাধান প্রার্থী) এবং সফল না হলে অন্য শাখায় অনুসন্ধান করা (এস)।
আইএমও, ব্যাকট্রাকিংয়ের যে কোনও নির্দিষ্ট নোডে আপনি প্রথমে তার প্রতিটি সন্তানের গভীরতার শাখা প্রশস্ত করার চেষ্টা করেন তবে শিশু নোডের কোনওটিতে শাখা করার আগে আপনাকে পূর্ববর্তী সন্তানের অবস্থা "মুছা" করতে হবে (এই পদক্ষেপটি পিছনের সমতুল্য) প্যারেন্ট নোডে চলুন)। অন্য কথায়, প্রতিটি ভাইবোন রাষ্ট্রের একে অপরকে প্রভাবিত করা উচিত নয়।
বিপরীতে, সাধারণ ডিএফএস অ্যালগরিদমের সময় আপনার সাধারণত এই সীমাবদ্ধতা থাকে না, পরবর্তী ভাইবোন নোডটি তৈরি করার জন্য আপনার পূর্ববর্তী ভাইবোনদের রাজ্যটি মুছে ফেলার দরকার নেই।
ডিএফএস আপনি যেভাবে কোনও গ্রাফ অন্বেষণ করতে বা অতিক্রম করতে চান তার বর্ণনা দেয়। এটি পছন্দ অনুযায়ী যতটা সম্ভব গভীরতর ধারণার উপর দৃষ্টি নিবদ্ধ করে।
ব্যাকট্র্যাকিং, সাধারণত ডিএফএসের মাধ্যমে প্রয়োগ করা হয়, যত তাড়াতাড়ি সম্ভব ছদ্মবেশহীন অনুসন্ধানের উপ-স্থানগুলিকে ছাঁটাই করার ধারণাটিতে আরও বেশি আলোকপাত করে।
একটি গভীরতা-প্রথম সার্চ , আপনি ট্রি রুট এ শুরু এবং তারপর যতটা আপনি অন্বেষণ প্রতিটি শাখা বরাবর, তারপর ছেড়ে দেত্তয়া প্রতিটি পরবর্তী পিতা বা মাতা নোডের এবং এটি সন্তান তর্ক
ব্যাকট্র্যাকিং হ'ল একটি লক্ষ্য শেষে শুরু করার জন্য এবং ক্রমান্বয়ে পিছনের দিকে অগ্রসর হয়ে ধীরে ধীরে একটি সমাধান তৈরির জন্য একটি সাধারণ শব্দ।
আইডিয়া - যে কোনও বিন্দু থেকে শুরু করুন, এটির পছন্দসই শেষ পয়েন্টটি পরীক্ষা করুন, যদি হ্যাঁ তবেই আমরা একটি সমাধান পেয়েছি পরবর্তী সমস্ত সম্ভাব্য পজিশনে চলে যায় এবং যদি আমরা আরও এগিয়ে যেতে না পারি তবে পূর্ববর্তী অবস্থানে ফিরে আসুন এবং সেই বিকল্পটিকে চিহ্নিত করে অন্যান্য বিকল্পগুলি সন্ধান করুন পথ আমাদের সমাধানের দিকে নিয়ে যাবে না।
এখন ব্যাকট্র্যাকিং এবং ডিএফএস হল 2 টি ভিন্ন ভিন্ন বিমূর্ত তথ্য প্রকারের ক্ষেত্রে একই ধারণাকে প্রয়োগ করা 2 টি আলাদা নাম।
যদি ধারণাটি ম্যাট্রিক্স ডেটা স্ট্রাকচারে প্রয়োগ করা হয় তবে আমরা এটিকে ব্যাকট্র্যাকিং বলি।
যদি একই ধারণাটি গাছ বা গ্রাফে প্রয়োগ করা হয় তবে আমরা এটিকে ডিএফএস বলি।
এখানে ক্লিচটি হ'ল একটি ম্যাট্রিক্স একটি গ্রাফে রূপান্তরিত হতে পারে এবং গ্রাফকে ম্যাট্রিক্সে রূপান্তর করা যেতে পারে। সুতরাং, আমরা আসলে ধারণাটি প্রয়োগ করি। যদি কোনও গ্রাফে থাকে তবে আমরা এটিকে ডিএফএস বলি এবং যদি ম্যাট্রিক্সে থাকে তবে আমরা এটিকে ব্যাকট্র্যাকিং বলি।
উভয় অ্যালগরিদমের ধারণা একই is
ব্যাকট্র্যাকিং হ'ল নির্দিষ্ট সমাপ্তির শর্তগুলির সাথে গভীরতার প্রথম অনুসন্ধান।
এমন একটি গোলকধাঁধা দিয়ে হাঁটার কথা বিবেচনা করুন যেখানে আপনি প্রতিটি পদক্ষেপের জন্য সিদ্ধান্ত নেন, সেই সিদ্ধান্তটি কল স্ট্যাকের কল (যা আপনার গভীরতার প্রথম অনুসন্ধান পরিচালনা করে) ... আপনি যদি শেষ পর্যন্ত পৌঁছে যান, তবে আপনি আপনার পথ ফিরে আসতে পারবেন। তবে, আপনি যদি কোনও ডেডেন্ডে পৌঁছে যান তবে আপনি একটি নির্দিষ্ট সিদ্ধান্ত থেকে ফিরে আসতে চান, মূলত আপনার কল স্ট্যাকের কোনও ফাংশন থেকে ফিরে returning
সুতরাং যখন আমি ব্যাকট্র্যাকিংয়ের কথা চিন্তা করি তখন আমি যত্নশীল
আমি backtracking আমার ভিডিওতে তা ব্যাখ্যা এখানে ।
ব্যাকট্র্যাকিং কোডের বিশ্লেষণ নীচে রয়েছে। এই ব্যাকট্র্যাকিং কোডটিতে আমি এমন সমস্ত সংমিশ্রণ চাই যা নির্দিষ্ট পরিমাণে বা লক্ষ্য হিসাবে ফলাফল করে। অতএব, আমার কাছে have টি সিদ্ধান্ত রয়েছে যা আমার কল স্টকে কল করে, প্রতিটি সিদ্ধান্তে আমি হয় লক্ষ্যের সংখ্যায় পৌঁছানোর জন্য আমার পথের অংশ হিসাবে একটি নম্বর বেছে নিতে পারি, সেই নম্বরটি এড়িয়ে যেতে পারি, বা এটি বাছাই করে আবার বেছে নিতে পারি। এবং তারপরে আমি যদি কোনও সমাপ্তির শর্তে পৌঁছে যাই তবে আমার ব্যাকট্র্যাকিং পদক্ষেপটি কেবল ফিরে আসা । রিটার্নিং ব্যাকট্র্যাকিং পদক্ষেপ কারণ এটি কল স্ট্যাকের সেই কলটি থেকে বেরিয়ে আসে।
class Solution:
"""
Approach: Backtracking
State
-candidates
-index
-target
Decisions
-pick one --> call func changing state: index + 1, target - candidates[index], path + [candidates[index]]
-pick one again --> call func changing state: index, target - candidates[index], path + [candidates[index]]
-skip one --> call func changing state: index + 1, target, path
Base Cases (Termination Conditions)
-if target == 0 and path not in ret
append path to ret
-if target < 0:
return # backtrack
"""
def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
"""
@desc find all unique combos summing to target
@args
@arg1 candidates, list of ints
@arg2 target, an int
@ret ret, list of lists
"""
if not candidates or min(candidates) > target: return []
ret = []
self.dfs(candidates, 0, target, [], ret)
return ret
def dfs(self, nums, index, target, path, ret):
if target == 0 and path not in ret:
ret.append(path)
return #backtracking
elif target < 0 or index >= len(nums):
return #backtracking
# for i in range(index, len(nums)):
# self.dfs(nums, i, target-nums[i], path+[nums[i]], ret)
pick_one = self.dfs(nums, index + 1, target - nums[index], path + [nums[index]], ret)
pick_one_again = self.dfs(nums, index, target - nums[index], path + [nums[index]], ret)
skip_one = self.dfs(nums, index + 1, target, path, ret)