দুটি লিঙ্কযুক্ত তালিকা একত্রিত হয়েছে কিনা তা পরীক্ষা করুন। যদি তাই হয় তবে কোথায়?


104

এই প্রশ্নটি পুরানো হতে পারে, তবে আমি উত্তরটি ভাবতে পারি না।

বলুন, বিভিন্ন দৈর্ঘ্যের দুটি তালিকা রয়েছে, এক পর্যায়ে মার্জ করা ; মার্জিং পয়েন্ট কোথায় রয়েছে তা আমরা কীভাবে জানতে পারি?

শর্তাদি:

  1. আমরা দৈর্ঘ্য জানি না
  2. আমাদের প্রতিটি তালিকাকে একবারে পার্স করা উচিত।

দুটি সংযুক্ত লিঙ্কযুক্ত তালিকার উদাহরণ।


মার্জ মানে সেই বিন্দু থেকে কেবল একটি তালিকা থাকবে।
rplusg

তালিকা পরিবর্তন করার অনুমতি আছে?
আর্টেলিয়াস

4
আমি নিশ্চিত যে তালিকার পরিবর্তন ছাড়া এটি কাজ করে না। (বা কেবল একবার পার্স করার সীমাবদ্ধতা এড়াতে কেবল অন্য কোথাও অনুলিপি করুন))
জর্জি শ্লেলি

4
পয়েন্ট হতে পারে। অভিযুক্ত সাক্ষাত্কার! হেহে
কাইল রোজেন্ডো

4
আমার কাছে একটি আকর্ষণীয় প্রস্তাব আছে ... ধরে নিচ্ছি তালিকার সাধারণ লেজ অসীম দীর্ঘ। ধ্রুবক স্মৃতি ব্যবহার করে আপনি কীভাবে নোড ছেদ পেতে পারেন?
আকুসেটে

উত্তর:


36

যদি

  • "পরিবর্তনের অনুমতি নেই" এর অর্থ "আপনি পরিবর্তন করতে পারেন তবে শেষ পর্যন্ত তাদের পুনরুদ্ধার করা উচিত", এবং
  • আমরা ঠিক দু'বার তালিকাটি পুনরাবৃত্তি করতে পারি could

নিম্নলিখিত আলগোরিদিম সমাধান হবে।

প্রথম, সংখ্যা। ধরুন প্রথম তালিকাটি দৈর্ঘ্যের a+cএবং দ্বিতীয়টি দৈর্ঘ্যের b+c, যেখানে cতাদের সাধারণ "লেজ" এর দৈর্ঘ্য (একীকরণের পরে)। নিম্নলিখিত হিসাবে তাদের বোঝাতে:

x = a+c
y = b+c

যেহেতু আমরা দৈর্ঘ্য জানি না, তাই আমরা গণনা করব xএবং yঅতিরিক্ত পুনরাবৃত্তি ছাড়াই; আপনি কিভাবে দেখতে পাবেন।

তারপরে, আমরা প্রতিটি তালিকা পুনরাবৃত্তি করি এবং পুনরাবৃত্তি করার সময় তাদের বিপরীত করি! যদি উভয় পুনরুক্তিকারী একই সময়ে মার্জ পয়েন্টে পৌঁছায়, তবে আমরা এটি কেবল তুলনা করে খুঁজে পেয়েছি। অন্যথায়, একটি পয়েন্টার অন্যটির আগে মার্জ পয়েন্টে পৌঁছে যাবে।

এর পরে, যখন অন্য পুনরাবৃত্তিটি মার্জ পয়েন্টে পৌঁছায়, তখন এটি সাধারণ লেজে যায় না। পরিবর্তে তালিকার আগের শুরুতে ফিরে যাবে যা আগে মার্জ পয়েন্টে পৌঁছেছিল! সুতরাং, পরিবর্তিত তালিকার শেষের দিকে পৌঁছানোর আগে (অর্থাত্ অন্যান্য তালিকার আগের শুরু), তিনি a+b+1মোট পুনরাবৃত্তি করবেন। এটি কল করুন z+1

পয়েন্টারটি যা প্রথমে মার্জ-পয়েন্টে পৌঁছেছে, তালিকার শেষে পৌঁছানো অবধি পুনরাবৃত্তি করতে থাকবে। এটি করা পুনরাবৃত্তির সংখ্যা গণনা করা উচিত এবং এর সমান x

তারপরে, এই পয়েন্টারটি পুনরাবৃত্তি করে এবং আবার তালিকাগুলি উল্টো করে দেয়। তবে এখন তালিকার শুরুতে এটি আর ফিরে যাবে না যা এটি মূলত শুরু হয়েছিল! পরিবর্তে, এটি অন্য তালিকার শুরুতে যাবে! এটি করা পুনরাবৃত্তির সংখ্যা গণনা করা উচিত এবং এর সমান হতে হবে y

সুতরাং আমরা নিম্নলিখিত সংখ্যা জানি:

x = a+c
y = b+c
z = a+b

যা থেকে আমরা তা নির্ধারণ করি

a = (+x-y+z)/2
b = (-x+y+z)/2
c = (+x+y-z)/2

যা সমস্যার সমাধান করে।


4
প্রশ্নে মন্তব্যে তালিকা পরিবর্তনের অনুমতি নেই!
Skizz

4
আমি এই উত্তরটি (খুব সৃজনশীল) পছন্দ করি। এটির সাথে আমার একমাত্র সমস্যা হ'ল এটি ধরে নেয় যে আপনি উভয় তালিকার দৈর্ঘ্য জানেন।
টিস্টার

আপনি তালিকাটি সংশোধন করতে পারবেন না, এবং আমরা দৈর্ঘ্যটি জানি না - এগুলি সীমাবদ্ধতাগুলি ... যেভাবেই হোক, সৃজনশীল উত্তরের জন্য ধন্যবাদ।
rplusg

4
@ এসটার, @ ক্যালভিন, উত্তরটি ধরে নেওয়া যায় না, আমাদের দৈর্ঘ্য প্রয়োজন। এটি ইনলাইন গণনা করা যায়। আমার উত্তরে ব্যাখ্যা যুক্ত করা হচ্ছে।
পি

4
@ ফোরথিংকার হ্যাশিং নোডগুলি পরিদর্শন করেছে এবং / অথবা সেগুলি হিসাবে চিহ্নিত হিসাবে চিহ্নিত করার জন্য ও (তালিকার দৈর্ঘ্য) মেমরির প্রয়োজন হয়, যখন অনেকগুলি সমাধান (আমার সহ, যদিও এটি অসম্পূর্ণ এবং জটিল) এর জন্য ও (1) মেমরির প্রয়োজন হয়।
পি বিভক্ত

164

নীচে আমি যতগুলি দেখেছি তার মধ্যে এখন পর্যন্ত সবচেয়ে বড় - হে (এন), কোনও কাউন্টার নেই। ভিশনম্যাপে একজন প্রার্থী এসএনকে দেওয়া সাক্ষাত্কারের সময় এটি পেয়েছি ।

এটির মতো একটি ইন্টিরিটিভ পয়েন্টার তৈরি করুন: এটি প্রতিবারের শেষ অবধি এগিয়ে যায় এবং তারপরে বিপরীত তালিকার শুরুতে লাফ দেয় এবং আরও কিছু। এগুলির দুটি তৈরি করুন, দুটি মাথা দেখিয়ে। প্রতিটি পয়েন্টার প্রতি 1 করে প্রতিবার অগ্রসর করুন, যতক্ষণ না তারা সাক্ষাত হয়। এটি একটি বা দুটি পাসের পরে ঘটবে।

আমি এখনও এই প্রশ্নটি সাক্ষাত্কারগুলিতে ব্যবহার করি - তবে এই সমাধান কেন কাজ করে তা বুঝতে কারও পক্ষে কতক্ষণ সময় লাগে তা দেখার জন্য।


6
এটা ঠিক উজ্জ্বল!
কংগ হুই

4
এটি একটি ভাল উত্তর, তবে আপনাকে তালিকা থেকে দুবার যেতে হবে যা শর্ত # 2 লঙ্ঘন করে।
টিস্টার

4
আমি এই সমাধানটি বেশ মার্জিত মনে করি, যদি একটি মার্জ পয়েন্ট উপস্থিত থাকার গ্যারান্টিযুক্ত থাকে। এটি মার্জ পয়েন্টগুলি সনাক্ত করতে কাজ করবে না, যেমন একটি উপস্থিত না থাকলে এটি অসীম লুপ হয়ে যাবে।
বিকল্প দিক

4
এটাই দুর্দান্ত উজ্জ্বল! ব্যাখ্যা: আমাদের 2 টি তালিকা রয়েছে: a-b-c-x-y-zএবং p-q-x-y-z। প্রথম পয়েন্টারের a,b,c,x,y,z,p,q,xপথ, দ্বিতীয় পয়েন্টারের পথp,q,x,y,z,a,b,c,x
নিকোলাই গোলু

14
উজ্জ্বল। যাঁরা বুঝতে পারেন নি, তাদের হেড 1-> লেজ 1 -> হেড 2 -> ছেদ বিন্দু এবং হেড 2 -> টেল 2-> হেড 1 -> ছেদ বিন্দু থেকে ভ্রমণ নোডগুলির সংখ্যা গণনা করুন। উভয়ই সমান হবে (এটি যাচাই করতে লিঙ্কযুক্ত তালিকার বিভিন্ন ধরণের অঙ্কন করুন)। কারণ উভয় পয়েন্টার আবার আইপি পৌঁছানোর আগে একই দূরত্ব হেড 1-> আইপি + হেড 2-> আইপি ভ্রমণ করতে হবে। সুতরাং এটি আইপি পৌঁছানোর সময়, উভয় পয়েন্টার সমান হবে এবং আমাদের মার্জিং পয়েন্ট আছে।
আদেভ

92

পাভেলের উত্তরে তালিকাগুলি সংশোধন করার পাশাপাশি প্রতিটি তালিকাকে দু'বার বারবার করা দরকার।

এখানে একটি সমাধান যে শুধুমাত্র প্রতিটি তালিকাকে দু'বার পুনরাবৃত্তি করতে হবে (তাদের দৈর্ঘ্য গণনা করার জন্য প্রথমবার; দৈর্ঘ্যটি যদি আপনাকে দেওয়া হয় তবে কেবল একবার পুনরাবৃত্তি করতে হবে)।

ধারণাটি হ'ল লম্বা তালিকার প্রারম্ভিক এন্ট্রিগুলিকে অগ্রাহ্য করা (মার্জ পয়েন্টটি সেখানে থাকতে পারে না), যাতে দুটি পয়েন্টার তালিকার শেষের থেকে সমান দূরত্ব হয়। তারপরে তারা মার্জ হওয়া অবধি তাদের এগিয়ে নিয়ে যান।

lenA = count(listA) //iterates list A
lenB = count(listB) //iterates list B

ptrA = listA
ptrB = listB

//now we adjust either ptrA or ptrB so that they are equally far from the end
while(lenA > lenB):
    ptrA = ptrA->next
    lenA--
while(lenB > lenA):
    prtB = ptrB->next
    lenB--

while(ptrA != NULL):
    if (ptrA == ptrB):
        return ptrA //found merge point
    ptrA = ptrA->next
    ptrB = ptrB->next

এটি আমার অন্যান্য উত্তরের মতো asympototically একই (লিনিয়ার সময়) তবে সম্ভবত ছোট ধ্রুবক রয়েছে, তাই সম্ভবত এটি দ্রুত faster তবে আমি মনে করি আমার অন্য উত্তরটি শীতল।


4
আজ, যখন আমরা ভদকা পান করছিলাম, আমি আমার এক বন্ধুর কাছে এই প্রশ্নটির প্রস্তাব দিয়েছিলাম, এবং তিনি আপনার মত উত্তরটি ছেড়ে দিয়ে এসওতে পোস্ট করতে বলেছিলেন। তবে আপনি প্রথম মনে হয়। সুতরাং আমি আমার কাছ থেকে আপনার জন্য একটি +1 করব এবং আমি চাই আমি আরও +1 করতে পারি।
পি শেভ করা

4
+1 এর মতো এবং এছাড়াও তালিকার কোনও পরিবর্তন দরকার নেই, এছাড়াও লিঙ্ক-তালিকার বেশিরভাগ বাস্তবায়ন সাধারণত দৈর্ঘ্যের জন্য সরবরাহ করে
keshav84

4
আমাদের অনেক বেশি পাভেল রয়েছে। আমার সমাধানের তালিকাকে সংশোধন করার প্রয়োজন নেই।
পাভেল রদজিভিলভস্কি

ভাল উত্তর. যদিও এর জন্য সময়ের জটিলতা থাকবে। 0 (এন + এম)? তালিকায় এন = নোড কোথায়, তালিকা 2 তালিকায় মি = নোড?
বিহান ভার্মা

উভয় তালিকার উভয়ই পয়েন্টার সরানোর পরিবর্তে: আমরা কেবল দেখতে পাচ্ছি যে পৃথক> = দুটি পথের মধ্যে ছোট, যদি হ্যাঁ, তবে ছোট তালিকাতে ছোট তালিকাতে সরান অন্য ডিফার +1 মান দ্বারা ছোট তালিকায় সরান; যদি ডিফ 0 হয় তবে সর্বশেষ নোডের উত্তর।
বিশাল আনন্দ

31

ঠিক আছে, আপনি যদি জানেন যে এগুলি মার্জ হবে:

বলুন যে আপনি দিয়ে শুরু:

A-->B-->C
        |
        V
1-->2-->3-->4-->5

1) প্রথম তালিকাটি NUL এ প্রতিটি পরবর্তী পয়েন্টার সেট করে যান।

এখন তোমার আছে:

A   B   C

1-->2-->3   4   5

2) এখন দ্বিতীয় তালিকার মধ্য দিয়ে যান এবং আপনি কোনও এনআরএল না পাওয়া পর্যন্ত অপেক্ষা করুন, এটি আপনার মার্জ পয়েন্ট।

আপনি যদি নিশ্চিত হন না যে এগুলি মার্জ করে তবে আপনি পয়েন্টার মানের জন্য একটি প্রেরণক মান ব্যবহার করতে পারেন, তবে এটি মার্জিত নয়।


4
যাইহোক, আপনি প্রক্রিয়াটি তালিকাটি ধ্বংস করেছেন, আর কখনও ব্যবহার করা হবে না: পি
কাইল রোজেন্ডো

@ কাইল রোজেন্ডো, ভাল, আমার সমাধানগুলি প্রক্রিয়াগুলির পরে পুনরুদ্ধার করতে পারে সেইভাবে তালিকাগুলি পরিবর্তন করে। তবে এটি ধারণার আরও সুস্পষ্ট বিক্ষোভ
পি শেভড

আমি দেখিনি যে তালিকার সংশোধন করার অনুমতি নেই। আমি এটি একটি চিন্তা করব, কিন্তু প্রতিটি নোড দেখা না সঞ্চয় করে কিছুই মনে আসে না।
tster

10
কমন, এটাই সঠিক উত্তর! আমাদের কেবল প্রশ্নটি সামঞ্জস্য করতে হবে :)
পি

24
মেমরি ফাঁস তৈরি করতে দুর্দান্ত অ্যালগরিদম।
করলি হরভাথ

14

যদি আমরা সংস্থাগুলি নির্ধারণের জন্য পদ্ধতি সরবরাহ করতে পারি তার চেয়ে ঠিক দু'বার তালিকাগুলি পুনরায় করা যায়:

  • উভয় তালিকাকে পুনরাবৃত্তি করুন এবং A এবং B দৈর্ঘ্যের গণনা করুন
  • দৈর্ঘ্যের পার্থক্য গণনা করুন সি = | এবি |
  • উভয় তালিকার একসাথে পুনরাবৃত্তি শুরু করুন, তবে তালিকায় অতিরিক্ত সি পদক্ষেপগুলি তৈরি করুন যা আরও বেশি ছিল
  • এই দুটি পয়েন্টার মার্জিং পয়েন্টে একে অপরের সাথে দেখা করবে

8

এখানে একটি সমাধান, গণনামূলকভাবে দ্রুত (প্রতিটি তালিকাকে একবারে পুনরাবৃত্তি করে) তবে প্রচুর স্মৃতি ব্যবহার করে:

for each item in list a
  push pointer to item onto stack_a

for each item in list b
  push pointer to item onto stack_b

while (stack_a top == stack_b top) // where top is the item to be popped next
  pop stack_a
  pop stack_b

// values at the top of each stack are the items prior to the merged item

4
এটি দুবার একটি তালিকা প্রক্রিয়া করার সমতুল্য।
জর্জি স্কলি

আমি মনে করি, প্রযুক্তিগতভাবে, আপনি দুটি তালিকা দিয়ে স্টাফ করছেন তবে কাইল রোজেন্ডোর সমাধানে এটি একটি উল্লেখযোগ্য উন্নতি। এখন, যদি 'তালিকার প্রক্রিয়াকরণ' সংজ্ঞায়িত করা হয় 'লিঙ্ক মানটি পড়া এবং পয়েন্টারটি অনুসরণ করা' এমন যুক্তি দেওয়া যেতে পারে যে এটি একবারে তালিকাটি প্রক্রিয়া করে - এটি প্রতিটি লিঙ্ক মান একবারে পড়ে, সংরক্ষণ করে এবং তারপরে তাদের তুলনা করে।
স্কিজেড

নিঃসন্দেহে আমার চেয়ে দ্রুত হতে চলেছে, সন্দেহ নেই।
কাইল রোজেন্ডো

8

আপনি নোডের একটি সেট ব্যবহার করতে পারেন। একটি তালিকার মধ্য দিয়ে ইটারেট করুন এবং প্রতিটি নোডকে সেটে যুক্ত করুন। তারপরে দ্বিতীয় তালিকার মধ্য দিয়ে পুনরাবৃত্তি করুন এবং প্রতিটি পুনরাবৃত্তির জন্য, নোডটি সেটে রয়েছে কিনা তা পরীক্ষা করুন। যদি এটি হয় তবে আপনি আপনার মার্জ পয়েন্টটি খুঁজে পেয়েছেন :)


আমি ভয় পাচ্ছি (space (n) অতিরিক্ত স্থানের কারণে) এটিই একমাত্র পন্থা (তালিকার পুনর্নির্মাণের সাজ নয়) এবং তালিকার একাধিকবার পার্সিং না করা। তালিকার একটি লুপ সনাক্ত করা প্রথম তালিকার জন্য তুচ্ছ (সেটটি নোডে রয়েছে কিনা তা পরীক্ষা করুন) - সমাপ্তি নিশ্চিত করতে দ্বিতীয় তালিকার কোনও লুপ সনাক্তকরণ পদ্ধতি ব্যবহার করুন। (সাক্ষাত্কার প্রশ্ন পারে শোনা সম্পর্কে হয়েছে সাবধানে একটি সমস্যা বিবৃতি, এবং না জাম্পিং একটি হাতুড়ি তোমাকে আঘাত কিছু না বেশ একটি পেরেক জানি ঘটতে ব্যবহার করতে।)
বৃদ্ধলোক

6

এটি যুক্তিযুক্তভাবে "প্রতিটি তালিকায় কেবল একবার পার্স করুন" শর্ত লঙ্ঘন করে তবে কচ্ছপ এবং হরে অ্যালগোরিদম (একটি চক্রের তালিকার মার্জ পয়েন্ট এবং চক্রের দৈর্ঘ্য সন্ধান করতে ব্যবহৃত হয়) প্রয়োগ করে সুতরাং আপনি তালিকা এ থেকে শুরু করুন এবং আপনি যখন এনআরএল-তে পৌঁছবেন তখন শেষ করে আপনি এটি বি বি তালিকার শুরুতে একটি পয়েন্টার ভান করেন, এইভাবে একটি চক্রীয় তালিকার উপস্থিতি তৈরি করে। অ্যালগরিদম তখন আপনাকে জানাবে যে লিস্ট এ এর ​​একত্রে কতটা নিচে রয়েছে (উইকিপিডিয়া বর্ণনানুসারে ভেরিয়েবল 'মু')।

এছাড়াও, "ল্যাম্বদা" মান আপনাকে বি বি তালিকার দৈর্ঘ্য জানায় এবং আপনি যদি চান, আপনি আলগোরিদিম চলাকালীন তালিকা তালিকার দৈর্ঘ্যের কাজ করতে পারেন (যখন আপনি ন্যূনাল লিঙ্কটি পুনর্নির্দেশ করবেন)।


আমি যা বলেছি তা খুব সুন্দর, কেবল কল্পিত নাম দিয়ে। : পি
কাইল রোজেন্ডো

একদমই না. এই সমাধানটি অপারেশনগুলিতে ও (এন) এবং মেমরির ব্যবহারে ও (1) (আসলে কেবলমাত্র দুটি পয়েন্টার ভেরিয়েবলের প্রয়োজন)।
আর্টেলিয়াস

হ্যাঁ, আমার সমাধানটি কিছুটা পরিবর্তিত হওয়ায় আমার পূর্ববর্তী মন্তব্যটি মুছে ফেলা উচিত ছিল। হেহে।
কাইল রোসেন্ডো

তবে আমি দেখতে পাচ্ছি না যে এটি প্রথম স্থানে কীভাবে প্রযোজ্য ছিল?
আর্টেলিয়াস

আপনার ব্যাখ্যাটি অ্যালগরিদম নিজেই করেনি। সম্ভবত আমি এটিকে অন্যভাবে দেখি তবে ওহে
কাইল রোজেন্ডো

3

হতে পারে আমি এটিকে আরও সরল করে দিচ্ছি, তবে কেবল ছোট্ট তালিকাটি পুনরাবৃত্তি করব এবং Linkমার্জিং পয়েন্ট হিসাবে শেষ নোডগুলি ব্যবহার করব ?

সুতরাং, একত্রীকরণ বিন্দুটি কোথায় Data->Link->Link == NULL, Data->Linkমার্জিং পয়েন্ট হিসাবে দেওয়া হচ্ছে (তালিকার শেষে)।

সম্পাদনা:

ঠিক আছে, আপনি যে ছবি পোস্ট করেছেন সেখান থেকে আপনি দুটি তালিকাকে ছোট, প্রথমটি বিশ্লেষণ করুন। ক্ষুদ্রতম তালিকার সাহায্যে আপনি নীচের নোডের রেফারেন্সগুলি বজায় রাখতে পারেন। এখন, আপনি দ্বিতীয় তালিকাকে পার্স করার সময় আপনি রেফারেন্সের সাথে তুলনা করুন যেখানে লিঙ্কলিস্টে [i] রেফারেন্সটি [i] -> লিংক। এটি মার্জ পয়েন্ট দেবে। ছবি দিয়ে ব্যাখ্যা করার সময় (ছবিটির ওপিতে মানগুলি সুপারপোজ করুন)।

আপনার একটি লিঙ্কযুক্ত তালিকা রয়েছে (নীচে দেখানো রেফারেন্স):

A->B->C->D->E

আপনার একটি দ্বিতীয় লিঙ্কযুক্ত তালিকা রয়েছে:

1->2->

একত্রিত তালিকার সাথে, উল্লেখগুলি পরে নিম্নলিখিত হিসাবে যাবে:

1->2->D->E->

অতএব, আপনি প্রথম "ছোট" তালিকাটি মানচিত্র করুন (একত্রীকরণের তালিকা হিসাবে, যা আমরা গণনা করছি তার দৈর্ঘ্য 4 এবং মূল তালিকা 5)

প্রথম তালিকার মধ্য দিয়ে লুপ করুন, রেফারেন্সের একটি রেফারেন্স বজায় রাখুন।

তালিকায় নিম্নলিখিত রেফারেন্স থাকবে Pointers { 1, 2, D, E }

আমরা এখন দ্বিতীয় তালিকার মধ্য দিয়ে যাচ্ছি:

-> A - Contains reference in Pointers? No, move on
-> B - Contains reference in Pointers? No, move on
-> C - Contains reference in Pointers? No, move on
-> D - Contains reference in Pointers? Yes, merge point found, break.

অবশ্যই, আপনি পয়েন্টারগুলির একটি নতুন তালিকা বজায় রাখছেন, তবে নির্দিষ্টকরণের বাইরে নয়। তবে প্রথম তালিকাটি ঠিক একবার পার্স করা হবে এবং দ্বিতীয় তালিকাটি কেবলমাত্র বিশ্লেষণ করবে যদি কোনও মার্জ পয়েন্ট না থাকে। অন্যথায়, এটি শীঘ্রই শেষ হয়ে যাবে (মার্জ পয়েন্টে)।


প্রথমে আমি যা বলতে চাইছিলাম তার থেকে কিছুটা পরিবর্তন হয় তবে ওপি যা মনে করে তা থেকে এটি কৌশলটি করবে।
কাইল রোজেন্ডো

এটা এখন আরও পরিষ্কার। তবে মেমরি ব্যবহারে রৈখিক। আমি এটা পছন্দ করি না।
আর্টেলিয়াস

প্রশ্নটি আরও জিজ্ঞাসা করে নি, অন্যথায় পুরো প্রক্রিয়াটি মাল্টিথ্রেড করা যেতে পারে। এটি এখনও একটি সরল "শীর্ষ স্তরের" সমাধানের ভিউ, কোডটি যে কোনও উপায়ে প্রয়োগ করা যেতে পারে। :)
কাইল রোজেন্ডো

4
আহ, কি? মাল্টিথ্রেডিং প্রক্রিয়াকরণ শক্তিকে আরও ভালভাবে ব্যবহার করার একটি উপায়, একটি অ্যালগোরিদমের জন্য প্রয়োজনীয় প্রসেসিং শক্তি হ্রাস না করে। এবং কোডটি যে কোনও উপায়ে প্রয়োগ করা যেতে পারে তা কেবল একটি অজুহাত।
আর্টেলিয়াস

4
এটি সত্যিই 'প্রতিটি তালিকায় কেবল একবার পার্স' নিকটবর্তী ব্রেকিং পয়েন্টে বাঁকায়। আপনি যা করছেন তা হ'ল একটি তালিকা অনুলিপি করা এবং তারপরে অনুলিপিটির বিরুদ্ধে অন্য তালিকাটি পরীক্ষা করা।
Skizz

3

আমি আমার FC9 x86_64 এ মার্জ কেস পরীক্ষা করেছি এবং নীচের মত প্রতিটি নোড ঠিকানা মুদ্রণ করেছি:

Head A 0x7fffb2f3c4b0
0x214f010
0x214f030
0x214f050
0x214f070
0x214f090
0x214f0f0
0x214f110
0x214f130
0x214f150
0x214f170


Head B 0x7fffb2f3c4a0
0x214f0b0
0x214f0d0
0x214f0f0
0x214f110
0x214f130
0x214f150
0x214f170

দ্রষ্টব্য, কারণ আমি নোড কাঠামোটি প্রান্তিককরণ করেছি, সুতরাং যখন malloc () একটি নোড হয়, ঠিকানাটি ডাব্লু / 16 বাইট প্রান্তিক করা হয়, কমপক্ষে 4 বিট দেখুন। সর্বনিম্ন বিটগুলি 0 সেগুলি, অর্থাৎ 0x0 বা 000 বি হয়। সুতরাং আপনার যদি একই বিশেষ ক্ষেত্রে হয় (প্রান্তিক নোড ঠিকানা), আপনি এই কমপক্ষে 4 টি বিট ব্যবহার করতে পারেন। উদাহরণস্বরূপ যখন উভয় তালিকাগুলি মাথা থেকে লেজ পর্যন্ত ভ্রমণ করে, ভিজিট নোড ঠিকানার 4 বিটের 1 বা 2 সেট করুন, অর্থাত্ একটি পতাকা সেট করুন;

next_node = node->next;
node = (struct node*)((unsigned long)node | 0x1UL);

নোটের উপরের পতাকাগুলি আসল নোডের ঠিকানাগুলিকে প্রভাবিত করবে না কেবলমাত্র আপনার সংরক্ষিত নোড পয়েন্টার মান।

একবার পাওয়া গেল যে কেউ পতাকা বিট (গুলি) সেট করেছে, তারপরে প্রথম পাওয়া নোডটি মার্জ পয়েন্ট হওয়া উচিত। হয়ে যাওয়ার পরে, আপনি সেট করা পতাকা বিটগুলি সাফ করে নোড ঠিকানাটি পুনরুদ্ধার করবেন। যদিও একটি গুরুত্বপূর্ণ বিষয়টি হ'ল পুনরায় করা (যেমন নোড = নোড-> পরবর্তী) পরিষ্কার করার সময় আপনার যত্নবান হওয়া উচিত। মনে রাখবেন আপনি পতাকা বিট সেট করেছিলেন, তাই এইভাবে করুন

real_node = (struct node*)((unsigned long)node) & ~0x1UL);
real_node = real_node->next;
node = real_node;

এই প্রস্তাবটি পরিবর্তিত নোড ঠিকানাগুলি পুনরুদ্ধার করবে বলে, এটি "কোনও পরিবর্তন নয়" হিসাবে বিবেচিত হতে পারে।


+1, এটি স্বাভাবিকভাবেই একবারে "একবারে পুনরাবৃত্তি" নিয়ে মনে আসে কেন এটি কখনই ভোট দেয়নি! সুন্দর সমাধান।
jman

3

একটি সহজ সমাধান হতে পারে তবে একটি সহায়ক স্থান প্রয়োজন ry ধারণাটি হ'ল একটি তালিকা অতিক্রম করে হ্যাশ ম্যাপে প্রতিটি ঠিকানা সংরক্ষণ করা হবে, এখন অন্য তালিকাটি অতিক্রম করুন এবং ঠিকানাটি হ্যাশ মানচিত্রে রয়েছে কিনা তা মেলান। প্রতিটি তালিকা শুধুমাত্র একবারে ট্রান্সভার করা হয়। কোনও তালিকায় কোনও পরিবর্তন নেই। দৈর্ঘ্য এখনও অজানা। সহায়ক স্থান ব্যবহৃত: O (n) যেখানে 'n' হ'ল প্রথম তালিকার দৈর্ঘ্য।


2

এই সমাধানটি কেবল একবারই তালিকাকে
পুনরুক্ত করে দেয় ... তালিকার কোনও সংশোধন করার প্রয়োজন নেই..তবে আপনি স্থান সম্পর্কে অভিযোগ করতে পারেন .. 1) মূলত আপনি তালিকা 1 এ পুনরাবৃত্তি করেন এবং প্রতিটি নোডের ঠিকানা একটি অ্যারেতে সংরক্ষণ করেন (যা স্বাক্ষরযুক্ত স্বীকৃত মান সংরক্ষণ করে)
2) তারপরে আপনি তালিকাটি পুনরাবৃত্তি করুন, এবং প্রতিটি নোডের ঠিকানার জন্য ---> আপনি অ্যারের মাধ্যমে অনুসন্ধান করেন যে আপনি কোনও মিল খুঁজে পেয়েছেন বা না পেয়েছেন ... যদি আপনি এটি করেন তবে এটি মার্জ নোড

//pseudocode
//for the first list
p1=list1;
unsigned int addr[];//to store addresses
i=0;
while(p1!=null){
  addr[i]=&p1;
  p1=p1->next;
}
int len=sizeof(addr)/sizeof(int);//calculates length of array addr
//for the second list
p2=list2;
while(p2!=null){
  if(search(addr[],len,&p2)==1)//match found
  {
    //this is the merging node
    return (p2);
  }
  p2=p2->next;
}

int search(addr,len,p2){
  i=0;  
  while(i<len){
    if(addr[i]==p2)
      return 1;
    i++;
  }
 return 0;
} 

আশা করি এটি একটি বৈধ সমাধান ...


এই তালিকাটি পরিবর্তে অ্যারের আকারে থাকা সত্ত্বেও এটি বেশিরভাগ তালিকাগুলির একাধিকবার পুনরাবৃত্তি করে।
syockit

1

কোনও তালিকা পরিবর্তন করার দরকার নেই। একটি সমাধান রয়েছে যাতে আমাদের কেবলমাত্র প্রতিটি তালিকাকে একবারে অতিক্রম করতে হবে।

  1. দুটি স্ট্যাক তৈরি করুন, স্ট্যাক 1 এবং স্ট্যাক 2 বলুন।
  2. 1 ম তালিকাটি ট্র্যাভার করুন এবং stck1 এ আপনি যে প্রতিটি নোডটি অতিক্রম করছেন তার একটি অনুলিপি চাপুন।
  3. দ্বিতীয় ধাপ হিসাবে একই তবে এবার দ্বিতীয় তালিকাটি অতিক্রম করুন এবং নোডের অনুলিপিটি স্ট্যাক 2 তে চাপ দিন।
  4. এখন, উভয় স্ট্যাক থেকে পপ করুন এবং দুটি নোড সমান কিনা তা যাচাই করুন, যদি হ্যাঁ তবে তাদের একটি রেফারেন্স রাখুন। যদি না হয়, তবে পূর্ববর্তী নোডগুলি যা সমান ছিল সেগুলি হ'ল আসলে আমরা যে মার্জ পয়েন্টটি খুঁজছিলাম।

1
int FindMergeNode(Node headA, Node headB) {
  Node currentA = headA;
  Node currentB = headB;

  // Do till the two nodes are the same
  while (currentA != currentB) {
    // If you reached the end of one list start at the beginning of the other
    // one currentA
    if (currentA.next == null) {
      currentA = headA;
    } else {
      currentA = currentA.next;
    }
    // currentB
    if (currentB.next == null) {
      currentB = headB;
    } else {
      currentB = currentB.next;
    }
  }
  return currentB.data;
}


0

এখানে নিষ্পাপ সমাধান, পুরো তালিকাগুলি ছাড়িয়ে যাওয়ার দরকার নেই।

যদি আপনার কাঠামোগত নোডের মতো তিনটি ক্ষেত্র থাকে

struct node {
    int data;   
    int flag;  //initially set the flag to zero  for all nodes
    struct node *next;
};

বলুন আপনার দুটি মাথা রয়েছে (হেড 1 এবং হেড 2) দুটি তালিকার শীর্ষের দিকে ইঙ্গিত করছে।

উভয় তালিকে একই গতিতে অতিক্রম করুন এবং সেই নোডের জন্য পতাকাটি = 1 (পরিদর্শন করা পতাকা) রাখুন,

  if (node->next->field==1)//possibly longer list will have this opportunity
      //this will be your required node. 

0

এটি সম্পর্কে:

  1. আপনি যদি কেবলমাত্র প্রতিটি তালিকায় কেবল একবার প্রবেশের অনুমতি পেয়ে থাকেন তবে আপনি একটি নতুন নোড তৈরি করতে পারেন, এই নোডের প্রতিটি নোডের জন্য প্রথম তালিকাটি অতিক্রম করতে পারেন এবং কোনও নোড আপনার নতুন নোডের দিকে ইশারা করছে কিনা তা দেখতে দ্বিতীয় তালিকাটি অতিক্রম করতে পারেন ( এটি আপনার মার্জ পয়েন্ট)। যদি দ্বিতীয় ট্র্যাভারসালটি আপনার নতুন নোডের দিকে না যায় তবে মূল তালিকার একটি মার্জ পয়েন্ট থাকে না।

  2. যদি আপনাকে তালিকাগুলি একাধিকবার অতিক্রম করতে দেওয়া হয়, তবে আমাদের দৈর্ঘ্যের সন্ধানের জন্য আপনি প্রতিটি তালিকাটি অতিক্রম করতে পারেন এবং যদি সেগুলি আলাদা হয় তবে দীর্ঘ তালিকার শুরুতে "অতিরিক্ত" নোডগুলি বাদ দিন। তারপরে উভয় তালিকাগুলি একবারে এক ধাপ অতিক্রম করুন এবং প্রথম মার্জিং নডটি সন্ধান করুন।


1. শুধুমাত্র সংশোধন করে না তবে প্রথম তালিকায় ব্যর্থ করে। 2. বারবার পরামর্শ দেওয়া হয়।
গ্রেইবার্ড

0

জাভা পদক্ষেপ:

  1. একটি মানচিত্র তৈরি করুন।
  2. তালিকার উভয় শাখায় যাত্রা শুরু করুন এবং নোডের সাথে সম্পর্কিত কোনও অনন্য জিনিস (নোড আইডি বলুন) কী হিসাবে ব্যবহার করে মানচিত্রে তালিকার সমস্ত ট্র্যাভার্সড নোড রাখুন এবং সবার জন্য শুরুতে মান 1 রেখে দিন।
  3. যখন প্রথম ডুপ্লিকেট কীটি আসে তখন সেই কীটির জন্য মান বাড়িয়ে দিন (এখন যাক এর মানটি 2 হয়ে গেল যা> 1)।
  4. মানটি 1 এর চেয়ে বেশি যেখানে কীটি পান এবং এটি নোড হওয়া উচিত যেখানে দুটি তালিকার একত্রীকরণ হচ্ছে।

4
আমাদের একীভূত অংশে চক্র থাকলে কী হবে?
রোহিত 18

কিন্তু চক্র পরিচালনার ক্ষেত্রে ত্রুটির জন্য, এটি ইসআইয়ের উত্তরের মতো দেখায় ।
গ্রেইবার্ড

0

আমরা "দক্ষতার সাথে দেখা" ক্ষেত্রটি প্রবর্তন করে দক্ষতার সাথে সমাধান করতে পারি। প্রথম তালিকাটি অনুসরণ করুন এবং শেষ পর্যন্ত সমস্ত নোডের জন্য "isVisited" মানটি "সত্য" -এ সেট করুন। এখন দ্বিতীয় থেকে শুরু করুন এবং প্রথম নোড সন্ধান করুন যেখানে পতাকাটি সত্য এবং বুম, এটি আপনার মার্জিং পয়েন্ট।


0

পদক্ষেপ 1: উভয় তালিকার দৈর্ঘ্য সন্ধান করুন পদক্ষেপ 2: পার্থক্যটি সন্ধান করুন এবং পার্থক্য সহ বৃহত্তম তালিকাটি সরান পদক্ষেপ 3: এখন উভয় তালিকা একই অবস্থানে থাকবে। পদক্ষেপ 4: মার্জ পয়েন্টটি অনুসন্ধানের জন্য তালিকার মাধ্যমে আইট্রেট করুন

//Psuedocode
def findmergepoint(list1, list2):
lendiff = list1.length() > list2.length() : list1.length() - list2.length() ? list2.lenght()-list1.lenght()
biggerlist = list1.length() > list2.length() : list1 ? list2  # list with biggest length
smallerlist = list1.length() < list2.length() : list2 ? list1 # list with smallest length


# move the biggest length to the diff position to level both the list at the same position
for i in range(0,lendiff-1):
    biggerlist = biggerlist.next
#Looped only once.  
while ( biggerlist is not None and smallerlist is not None ):
    if biggerlist == smallerlist :
        return biggerlist #point of intersection


return None // No intersection found

(আমি প্রতিটি আইটেমটি আরও ভালভাবে একটি লাইন শুরু করার সাথে তালিকাকে পছন্দ করেছি a বানান পরীক্ষকটি ব্যবহারের বিষয়টি বিবেচনা করুন))
গ্রেইবার্ড

0
int FindMergeNode(Node *headA, Node *headB)
{
    Node *tempB=new Node;
    tempB=headB;
   while(headA->next!=NULL)
       {
       while(tempB->next!=NULL)
           {
           if(tempB==headA)
               return tempB->data;
           tempB=tempB->next;
       }
       headA=headA->next;
       tempB=headB;
   }
    return headA->data;
}

আপনার উত্তরের জন্য আপনাকে কিছু ব্যাখ্যা যুক্ত করতে হবে। কোড কেবল উত্তরগুলি মুছতে পারে।
rghome

0

নোডের অ্যাড্রেসেস বনাম মান সঞ্চয় করতে মানচিত্র বা অভিধান ব্যবহার করুন। যদি ঠিকানাটি ম্যাপ / অভিধানে অ্যাল্রেড থাকে তবে কীটির মান উত্তর the আমি এটা করেছি:

int FindMergeNode(Node headA, Node headB) {

Map<Object, Integer> map = new HashMap<Object, Integer>();

while(headA != null || headB != null)
{
    if(headA != null && map.containsKey(headA.next))
    {
        return map.get(headA.next);
    }

    if(headA != null && headA.next != null)
    {
         map.put(headA.next, headA.next.data);
         headA = headA.next;
    }

    if(headB != null && map.containsKey(headB.next))
    {
        return map.get(headB.next);
    }

    if(headB != null && headB.next != null)
    {
        map.put(headB.next, headB.next.data);
        headB = headB.next;
    }
}

return 0;
}

0

এও (এন) জটিলতার সমাধান। তবে একটি অনুমানের উপর ভিত্তি করে।

অনুমানটি হ'ল: উভয় নোডের কেবল ইতিবাচক পূর্ণসংখ্যা রয়েছে।

যুক্তি: তালিকা 1 এর সমস্ত পূর্ণসংখ্যাটিকে negativeণাত্মক করুন। তারপরে তালিকার 2 টি দিয়ে চলুন, যতক্ষণ না আপনি একটি negativeণাত্মক পূর্ণসংখ্যা পাওয়া যায়। একবার পাওয়া যায় => এটি নেওয়ার পরে, সাইনটি ইতিবাচক করে ফিরে আসুন।

static int findMergeNode(SinglyLinkedListNode head1, SinglyLinkedListNode head2) {

    SinglyLinkedListNode current = head1; //head1 is give to be not null.

    //mark all head1 nodes as negative
    while(true){
        current.data = -current.data;
        current = current.next;
        if(current==null) break;
    }

    current=head2; //given as not null
    while(true){
        if(current.data<0) return -current.data;
        current = current.next;
    }

}

0

আমরা দুটি পয়েন্টার ব্যবহার করতে পারি এবং ফ্যাশনে এমন পরিবর্তন করতে পারি যে পয়েন্টারগুলির মধ্যে একটি যদি নাল হয় তবে আমরা এটিকে অন্য তালিকার শীর্ষের দিকে এবং অন্যটির জন্য একইভাবে নির্দেশ করি, এইভাবে যদি তালিকার দৈর্ঘ্য আলাদা হয় তবে তারা দ্বিতীয় পাসে মিলবে । যদি তালিকা 1 এর দৈর্ঘ্য n হয় এবং তালিকা 2 মি হয় তবে তাদের পার্থক্যটি ডি = অ্যাবস (এনএম)। তারা এই দূরত্বটি কভার করবে এবং একত্রীকরণ স্থানে মিলিত হবে।
কোড:

int findMergeNode(SinglyLinkedListNode* head1, SinglyLinkedListNode* head2) {
    SinglyLinkedListNode* start1=head1;
    SinglyLinkedListNode* start2=head2;
    while (start1!=start2){
        start1=start1->next;
        start2=start2->next;
        if (!start1)
        start1=head2;
        if (!start2)
        start2=head1;
    }
    return start1->data;
}

0

আপনি list1একটি হ্যাশসেটের নোড এবং দ্বিতীয়টির মধ্য দিয়ে লুপ যুক্ত করতে পারেন এবং যদি কোনও নোড list2ইতিমধ্যে সেটে উপস্থিত থাকে yes

static int findMergeNode(SinglyLinkedListNode head1, SinglyLinkedListNode head2) {
    HashSet<SinglyLinkedListNode> set=new HashSet<SinglyLinkedListNode>();
    while(head1!=null)
    {
        set.add(head1);
        head1=head1.next;
    }
    while(head2!=null){
        if(set.contains(head2){
            return head2.data;
        }
    }
    return -1;
}

0

জাভাস্ক্রিপ্ট ব্যবহার করে সমাধান

var getIntersectionNode = function(headA, headB) {
    
    if(headA == null || headB == null) return null;
    
    let countA = listCount(headA);
    let countB = listCount(headB);
    
    let diff = 0;
    if(countA > countB) {

        diff = countA - countB;
        for(let i = 0; i < diff; i++) {
            headA = headA.next;
        }
    } else if(countA < countB) {
        diff = countB - countA;
        for(let i = 0; i < diff; i++) {
            headB = headB.next;
        }
    }

    return getIntersectValue(headA, headB);
};

function listCount(head) {
    let count = 0;
    while(head) {
        count++;
        head = head.next;
    }
    return count;
}

function getIntersectValue(headA, headB) {
    while(headA && headB) {
        if(headA === headB) {
            return headA;
        }
        headA = headA.next;
        headB = headB.next;
    }
    return null;
}

0

যদি লিঙ্কযুক্ত তালিকার সম্পাদনা অনুমোদিত হয়,

  1. তারপরে তালিকার 2 টি সমস্ত নোডের পরবর্তী নোড পয়েন্টারগুলি শূন্য হিসাবে তৈরি করুন।
  2. তালিকার শেষ নোডের ডেটা মান সন্ধান করুন। এটি "কোনও হাই ফাই লজিক" না দিয়ে উভয় তালিকার একক ট্র্যাভার্সালকে ছেদকারী নোড দেবে।
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.