সহজ সাক্ষাত্কারের প্রশ্নটি আরও শক্ত হয়ে উঠেছে: প্রদত্ত নম্বরগুলি ১.১০০, খুঁজে পাওয়া নিখোঁজ নম্বর (গুলি) সঠিকভাবে অনুপস্থিত


1146

কিছুক্ষণ আগে আমার একটি আকর্ষণীয় কাজের সাক্ষাত্কারের অভিজ্ঞতা ছিল। প্রশ্নটি সত্যিই সহজ শুরু হয়েছিল:

চতুর্থাংশ 1 : আমরা একটি ব্যাগ সংখ্যার ধারণকারী আছে 1, 2, 3, ..., 100। প্রতিটি সংখ্যা ঠিক একবার প্রদর্শিত হয়, তাই 100 সংখ্যা আছে। এখন একটি নম্বর এলোমেলোভাবে ব্যাগ থেকে বাছাই করা হয়েছে। অনুপস্থিত নম্বরটি সন্ধান করুন।

আমি অবশ্যই এই সাক্ষাত্কারের প্রশ্নটি অবশ্যই শুনেছি, তাই আমি খুব দ্রুত উত্তরটি দিয়েছি:

ক 1 : ওয়েল, সংখ্যার যোগফল 1 + 2 + 3 + … + Nহয় (N+1)(N/2)(দেখুন : গাণিতিক সিরিজের সমষ্টি উইকিপিডিয়া )। জন্য N = 100, যোগফল হয় 5050

সুতরাং, সমস্ত সংখ্যা যদি ব্যাগে উপস্থিত থাকে তবে যোগফলটি ঠিক হবে 5050। যেহেতু একটি নম্বর অনুপস্থিত, যোগফলটি এর চেয়ে কম হবে এবং পার্থক্যটি সেই সংখ্যা। সুতরাং আমরা O(N)সময় এবং O(1)স্থানের যে অনুপস্থিত নম্বর খুঁজে পেতে পারেন ।

এই মুহুর্তে আমি ভেবেছিলাম আমি ভাল করেছি, তবে হঠাৎ প্রশ্নটি একটি অপ্রত্যাশিত মোড় নিয়েছিল:

প্রশ্ন 2 : এটি সঠিক, তবে এখন আপনি কীভাবে এটি করবেন যদি দুটি নম্বর অনুপস্থিত থাকে?

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

সাক্ষাত্কারকারক আমাকে এই বলে উত্সাহ দেওয়ার চেষ্টা করেছিলেন যে সমস্যা সমাধানের জন্য দ্বিতীয় সমীকরণ থাকা আসলেই একটি উপায়। এই মুহুর্তে আমি একরকম বিচলিত হয়ে পড়েছিলাম (হাতের আগে উত্তর না জানার জন্য), এবং জিজ্ঞাসা করলাম এটি একটি সাধারণ (পড়ুন: "দরকারী") প্রোগ্রামিং কৌশল, বা এটি যদি কেবল কৌশল / গোটচের উত্তর।

সাক্ষাত্কারের উত্তরটি আমাকে অবাক করে: আপনি 3 টি হারিয়ে যাওয়া সংখ্যাগুলি আবিষ্কার করার কৌশলটি সাধারণ করতে পারেন। আসলে, আপনি কে অনুপস্থিত সংখ্যাগুলি খুঁজে পেতে এটি সাধারণকরণ করতে পারেন ।

কিউকি : ব্যাগ থেকে যদি ঠিক কে নম্বরগুলি অনুপস্থিত থাকে তবে আপনি কীভাবে এটি দক্ষতার সাথে আবিষ্কার করবেন?

এটি কয়েক মাস আগে ছিল এবং আমি এখনও এই কৌশলটি কী তা বুঝতে পারি না। স্পষ্টতই একটি Ω(N)সময় নীচের দিকে আবদ্ধ হয় যেহেতু আমাদের অবশ্যই কমপক্ষে একবারে সমস্ত নম্বর স্ক্যান করতে হবে, তবে সাক্ষাত্কারকারী জোর দিয়েছিলেন যে সমাধানের কৌশলটির টাইম এবং স্পেস জটিলতা (মাইনাস O(N)টাইম ইনপুট স্ক্যান) কে নয় এন-এ সংজ্ঞায়িত করা হয়েছে ।

সুতরাং এখানে প্রশ্নটি সহজ:

  • আপনি কিউ 2 সমাধান করবেন ?
  • আপনি কিউ 3 সমাধান করবেন ?
  • আপনি কিউকে কীভাবে সমাধান করবেন ?

ব্যাখ্যা

  • সাধারণত আছে এন 1 .. থেকে নম্বর এন , শুধু না 1..100।
  • আমি সুস্পষ্ট সেট-ভিত্তিক সমাধানের সন্ধান করছি না, যেমন একটি বিট সেট ব্যবহার করে , প্রতিটি সংখ্যা একটি নির্ধারিত বিটের মান অনুসারে এনকোডিং / অনুপস্থিতি, O(N)অতিরিক্ত স্থানের বিট ব্যবহার করে using আমরা N এর সাথে আনুপাতিক কোনও অতিরিক্ত স্থান বহন করতে পারি না ।
  • আমি সুস্পষ্ট বাছাই-প্রথম পদ্ধতির জন্যও খুঁজছি না। এটি এবং সেট-ভিত্তিক পদ্ধতির একটি সাক্ষাত্কারে উল্লেখ করা মূল্যবান (এগুলি কার্যকর করা সহজ, এবং এন এর উপর নির্ভর করে , খুব ব্যবহারিক হতে পারে)। আমি হোলি গ্রেইল সলিউশনটি খুঁজছি (যা বাস্তবায়নের ক্ষেত্রে ব্যবহারিক হতে পারে বা নাও হতে পারে তবে তবুও কাঙ্ক্ষিত অ্যাসিম্পোটিক বৈশিষ্ট্য রয়েছে)।

আবার, অবশ্যই আপনাকে অবশ্যই ইনপুটটি স্ক্যান করতে হবে O(N), তবে আপনি কেবলমাত্র অল্প পরিমাণে তথ্য ক্যাপচার করতে পারেন ( কে নয় এন এর সাথে সংজ্ঞায়িত ), এবং তারপরে কোনওভাবে কে অনুপস্থিত সংখ্যাগুলি খুঁজে পেতে হবে ।


7
@ পলিজেলেনব্রিক্যান্টস স্পষ্টতার জন্য আপনাকে ধন্যবাদ। "আমি এমন একটি অ্যালগরিদম খুঁজছি যা ও (এন) সময় এবং ও (কে) স্পেস ব্যবহার করে যেখানে কে অনুপস্থিত সংখ্যার গণনা" ;-) থেকে শুরু থেকেই স্পষ্ট হয়ে উঠবে
ডেভ ও।

7
আপনার সুনির্দিষ্টভাবে বলা উচিত, প্রশ্নোত্তর 1 এর বিবৃতিতে যে আপনি সংখ্যায় ক্রমে অ্যাক্সেস করতে পারবেন না। এটি সম্ভবত আপনার কাছে সুস্পষ্ট বলে মনে হয় তবে আমি কখনও প্রশ্নটির কথা শুনিনি এবং "ব্যাগ" শব্দটি (যার অর্থ "মাল্টিসেট" এর অর্থও) বিভ্রান্তিকর ছিল।
জের্মি

7
এখানে প্রদত্ত উত্তরগুলি হাস্যকর হিসাবে দয়া করে নীচেরটি পড়ুন

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

3
যাইহোক চতুর্থাংশ 1 জন্য সুন্দর সুন্দর বিকল্প সমাধান কম্পিউটিং যেতে পারে XORথেকে সমস্ত সংখ্যার 1জন্য n, তারপর দেওয়া অ্যারের মধ্যে সব সংখ্যার ফলাফলের XORing। শেষ অবধি আপনার গায়েবি নম্বর আছে। এই সমাধানটিতে আপনাকে সমষ্টি হিসাবে ওভারফ্লো সম্পর্কে যত্ন করার দরকার নেই।
sbeliakov

উত্তর:


590

দিমিত্রিস অ্যান্ড্রুয়ের লিঙ্কের একটি সংক্ষিপ্তসার এখানে ।

আই-তম শক্তির যোগফল মনে রাখুন, যেখানে i = 1,2, .., কে। এটি সমীকরণের সিস্টেমটি সমাধান করতে সমস্যা হ্রাস করে

a 1 + a 2 + ... + a কে = খ 1

a 1 2 + a 2 2 + ... + a কে 2 = বি 2

...

a 1 কে + এ 2 কে + ... + এ কে কে = বি কে

নিউটনের পরিচয় ব্যবহার করে , জেনে আমি বি গণনা করতে পারি

সি 1 = এ 1 + এ 2 + ... এ কে

c 2 = a 1 a 2 + a 1 a 3 + ... + a k-1 a k

...

সি কে = এ 12 ... এ কে

আপনি যদি বহুপদী (xa 1 ) ... (xa কে ) প্রসারিত করেন তবে সহগগুলি হ'ল সি 1 , ..., সি কে - ভিয়েটের সূত্রগুলি দেখুন । যেহেতু প্রতিটি বহুত্বীয় উপাদানগুলি স্বতন্ত্রভাবে (বহুভুজের রিং একটি ইউক্লিডিয়ান ডোমেন ), এর অর্থ একটি আমি অনন্যভাবে নির্ধারিত, অনুমানের অবধি।

এর ফলে একটি প্রমাণ শেষ হয় যে সংখ্যাগুলি পুনরুদ্ধার করার জন্য ক্ষমতাগুলি স্মরণ করা যথেষ্ট। ধ্রুব কে জন্য, এটি একটি ভাল পদ্ধতির।

তবে, যখন কে আলাদা হয়, সি 1 , ..., সি কে গণনা করার প্রত্যক্ষ পন্থা নিষিদ্ধ ব্যয়বহুল, যেহেতু সি কে সমস্ত অনুপস্থিত সংখ্যার, মাত্রা এন! / (এনকে) এর পণ্য! এটি কাটিয়ে উঠতে, জেড কিউ ফিল্ডে গণনা সম্পাদন করুন , যেখানে কিউ এমন একটি প্রধান যা এন <= কি <2 এন - এটি বার্ট্র্যান্ডের পোস্টুলেট দ্বারা বিদ্যমান । প্রমাণগুলি পরিবর্তন করার দরকার নেই, যেহেতু সূত্রগুলি এখনও রয়েছে এবং বহুবচনগুলির অনুষঙ্গীকরণ এখনও অনন্য। সীমাবদ্ধ ক্ষেত্রগুলির উপর নির্ভরশীলতার জন্য আপনার একটি অ্যালগরিদমও প্রয়োজন, উদাহরণস্বরূপ বার্লেক্যাম্প বা ক্যান্টোর-জ্যাসেনহাউসের একটি

ধ্রুবক কে এর জন্য উচ্চ স্তরের সিউডোকোড:

  • প্রদত্ত সংখ্যার i-th শক্তি গণনা করুন
  • অজানা সংখ্যার আই-তম শক্তির যোগফলগুলি বিয়োগ করুন। অঙ্কগুলি কল করুন i
  • i থেকে সহগের হিসাব করতে নিউটনের পরিচয় ব্যবহার করুন ; তাদের কল কর i । মূলত, গ 1 = খ 1 ; সি 2 = (সি 1 বি 1 - বি 2 ) / 2; সঠিক সূত্রের জন্য উইকিপিডিয়া দেখুন
  • বহুবর্ষীয় x কে- সি 1 এক্স কে -1 + ... + সি কে এর ফ্যাক্টর ।
  • বহুবর্ষের শিকড় হ'ল প্রয়োজনীয় সংখ্যা হ'ল 1 , ..., কে

কে পরিবর্তিত করার জন্য, যেমন মিলার-রবিন ব্যবহার করে একটি প্রাথমিক এন <= q <2n সন্ধান করুন এবং সমস্ত সংখ্যা হ্রাসকারী মডুলো q সহ পদক্ষেপগুলি সম্পাদন করুন।

সম্পাদনা: এই উত্তরের পূর্ববর্তী সংস্করণে বলা হয়েছে যে জেড কিউ এর পরিবর্তে , যেখানে q প্রধান, সেখানে বৈশিষ্ট্যযুক্ত 2 (q = 2 ^ (লগ এন)) এর একটি সীমাবদ্ধ ক্ষেত্র ব্যবহার করা সম্ভব। এটি কেস নয়, যেহেতু নিউটনের সূত্রগুলিতে কে পর্যন্ত সংখ্যা দ্বারা বিভাজন প্রয়োজন।


6
আপনাকে কোনও প্রধান ক্ষেত্র ব্যবহার করতে হবে না, আপনি এটিও ব্যবহার করতে পারেন q = 2^(log n)। (আপনি কীভাবে সুপার- এবং সাবস্ক্রিপ্টগুলি তৈরি করেছেন ?!)
হেইনিরিচ অ্যাপফেল্মাস

49
+1 এটি সত্যই, চতুর। একই সাথে, এটি প্রশ্নবিদ্ধ, সত্যই এটি প্রচেষ্টাটির পক্ষে মূল্যবান কিনা, বা বেশ কয়েকটি কৃত্রিম সমস্যার সমাধানের (অংশগুলি) অন্যভাবে ব্যবহার করা যেতে পারে কিনা। এমনকি এটি যদি সত্যিকারের বিশ্ব সমস্যাও ছিল তবে অনেক প্ল্যাটফর্মে সর্বাধিক তুচ্ছ O(N^2)সমাধান সম্ভবত যুক্তিসঙ্গত উচ্চতার জন্য সম্ভবত এই সৌন্দর্যকে ছাড়িয়ে যাবে N। আমাকে এটিকে ভাবায় : tinyurl.com/c8fwgw তবুও, দুর্দান্ত কাজ! সমস্ত গণিতে ক্রল করার মতো ধৈর্য আমার হত না :)
back2dos

167
আমি মনে করি এটি একটি দুর্দান্ত উত্তর। আমি মনে করি এটি একটি সাক্ষাত্কারের প্রশ্নের নিখোঁজ সংখ্যাগুলি ছাড়িয়ে যাওয়ার পক্ষে কতটা দরিদ্র তা চিত্রিত করে। এমনকি প্রথমটি গোচ্চ্যা ধরণের, তবে এটি যথেষ্ট সাধারণ যে এটি মূলত দেখায় "আপনি কিছু সাক্ষাত্কার প্রস্তুত করেছেন did" তবে কোনও সিএস মেজরকে কে = 1 ছাড়িয়ে যেতে হবে এমন আশা করা (বিশেষত একটি সাক্ষাত্কারে "স্পটটিতে") কিছুটা বোকা।
corsiKa

5
এটি কার্যকরভাবে ইনপুটটিতে কোডিং কোড রিড করছে।
ডেভিড এহর্মান

78
আমি বাজায় একটিতে সমস্ত নম্বর প্রবেশ করানো hash setএবং সন্ধানের মাধ্যমে 1...Nসংখ্যাগুলি অনুপস্থিত কিনা তা নির্ধারণের জন্য স্যুটটির মাধ্যমে পুনরাবৃত্তি করা, সবচেয়ে সাধারণ হবে, kপরিবর্তনের ক্ষেত্রে গড়ে দ্রুততম , সবচেয়ে ডিবাগযোগ্য, সবচেয়ে রক্ষণযোগ্য এবং বোধগম্য সমাধান। অবশ্যই গণিতের পথটি চিত্তাকর্ষক তবে কোথাও কোথাও আপনাকে ইঞ্জিনিয়ার হওয়া প্রয়োজন এবং গণিতবিদ নয়। বিশেষত যখন ব্যবসায় জড়িত থাকে।
v.oddou

243

আপনি মুথুকৃষ্ণন - ডেটা স্ট্রিম অ্যালগরিদমস: ধাঁধা 1: হারিয়ে যাওয়া সংখ্যাগুলি সন্ধানের দু'টি পৃষ্ঠা পড়ে এটি পেয়ে যাবেন । এটি ঠিক যে সাধারণীকরণটি আপনি খুঁজছেন তা দেখায় । সম্ভবত আপনার সাক্ষাত্কারকারক এটিই পড়েন এবং কেন তিনি এই প্রশ্নগুলি উত্থাপন করেছিলেন।

এখন, যদি কেবল লোকেরা মুথুকৃষ্ণনের চিকিত্সা দ্বারা সাবমড বা সুপারসাইড করা উত্তরগুলি মুছতে শুরু করে এবং এই পাঠ্যটি সন্ধান করা আরও সহজ করে তোলে। :)


এছাড়াও এসডিসিভিভিসি-এর সরাসরি সম্পর্কিত উত্তরটি দেখুন , যার মধ্যে সিডোকোডও রয়েছে ( হুররে! সেই কৌশলগুলি গণিতের সূত্রগুলি পড়ার দরকার নেই :)) (ধন্যবাদ, দুর্দান্ত কাজ!)।


ওহ ... এটি আকর্ষণীয় আমাকে স্বীকার করতে হবে আমি গণিতগুলি দ্বারা কিছুটা বিভ্রান্ত হয়ে পড়েছিলাম তবে আমি এটি স্কিমিং করছিলাম। আরও পরে দেখার জন্য এটি খোলা ছেড়ে দিতে পারে। :) এবং এই লিঙ্কটি আরও সন্ধানযোগ্য পেতে +1 করুন। ;-)
ক্রিস

2
গুগল বই লিঙ্ক আমার জন্য কাজ করে না। এখানে আরও ভাল সংস্করণ [পোস্টস্ক্রিপ্ট ফাইল]।
হেইনিরিচ এফেল্মাস

9
কি দারুন. আমি এই upvated হবে আশা করি না! শেষবার যখন আমি সমাধানটি (নুথের ক্ষেত্রে, তখন সে ক্ষেত্রে) নিজেই সমাধান করার চেষ্টা করার পরিবর্তে একটি রেফারেন্স পোস্ট করলাম, এটি আসলে ডাউনভোটেড ছিল: stackoverflow.com/questions/3060104/… আমার ভিতরে গ্রন্থাগারিক আনন্দিত, ধন্যবাদ :)
দিমিত্রিস অ্যান্ড্রু

@ অ্যাফেল্মাস, নোট করুন এটি একটি খসড়া। (আমি অবশ্যই আপনাকে দোষ দিচ্ছি না, বইটি সন্ধানের আগে আমি প্রায় এক বছর ধরে আসল জিনিসগুলির জন্য খসড়াটি বিভ্রান্ত করেছি)। বিটিডব্লু যদি লিঙ্কটি কাজ না করে, আপনি Books.google.com এ গিয়ে "মুথুকৃষ্ণন ডেটা স্ট্রিম অ্যালগরিদম" (উদ্ধৃতি ব্যতীত) অনুসন্ধান করতে পারেন , এটি প্রথম পপ আপ।
দিমিত্রিস আন্দ্রেউ

2
এখানে প্রদত্ত উত্তরগুলি হাস্যকর হিসাবে দয়া করে নীচেরটি পড়ুন

174

আমরা উভয় সংখ্যাকে নিজের করে এবং সংখ্যার স্কোয়ার যোগ করে কিউ 2 সমাধান করতে পারি।

তারপরে আমরা সমস্যাটি কমাতে পারি

k1 + k2 = x
k1^2 + k2^2 = y

অঙ্কগুলি প্রত্যাশিত মানের তুলনায় কোথায় xএবং yকতদূর রয়েছে।

প্রতিস্থাপন আমাদের দেয়:

(x-k2)^2 + k2^2 = y

যা আমরা তখন আমাদের অনুপস্থিত সংখ্যা নির্ধারণ করতে সমাধান করতে পারি।


7
+1 টি; আমি নির্বাচিত সংখ্যার জন্য ম্যাপেলে সূত্রটি চেষ্টা করেছি এবং এটি কাজ করে। যদিও এখনও এটি কাজ করে আমি নিজেকে বোঝাতে পারি নি।
বহুবৃক্ষের পদার্থগুলি

4
@ পলিজেনেলব্রিক্যান্টস: আপনি যদি যথার্থতা প্রমাণ করতে চান, আপনি প্রথমে দেখান যে এটি সর্বদা একটি সঠিক সমাধান সরবরাহ করে (এটি সর্বদা সংখ্যার একটি সংখ্যার উত্পাদন করে যা সেট থেকে অপসারণ করার পরে, সেটটির অবশিষ্টাংশের ফলাফল করে পর্যবেক্ষণের যোগফল এবং সমষ্টিগুলির সমষ্টি) সেখান থেকে, স্বতন্ত্রতা প্রমাণ করা যতটা সহজ এটি দেখানোর মতো সহজ যে এটি কেবল এই জাতীয় সংখ্যার জোড়া তৈরি করে।
আনন

5
সমীকরণের প্রকৃতির অর্থ আপনি সেই সমীকরণ থেকে কে 2 এর দুটি মান পাবেন। যাইহোক, আপনি কে 1 উত্পন্ন করার জন্য যে প্রথম সমীকরণটি ব্যবহার করেন তা থেকে আপনি দেখতে পারবেন যে কে 2 এর এই দুটি মানটির অর্থ কে 1 হ'ল অন্য মান তাই আপনার দুটি সমাধান রয়েছে যা একই সংখ্যার বিপরীতে way আপনি যদি স্বতঃস্ফূর্তভাবে সেই কে 1> কে 2 ঘোষণা করেন তবে আপনার কাছে কেবল চতুর্ভুজ সমীকরণের একটি সমাধান এবং এভাবে সামগ্রিকভাবে একটি সমাধান হবে। এবং পরিষ্কারভাবে প্রশ্নের প্রকৃতির দ্বারা একটি উত্তর সর্বদা উপস্থিত থাকে তাই এটি সর্বদা কার্যকর হয়।
ক্রিস

3
প্রদত্ত অঙ্কের কে 1 + কে 2 এর জন্য অনেকগুলি জোড়া রয়েছে। আমরা এই জোড়গুলিকে কে 1 = a + বি এবং কে 2 = আব হিসাবে লিখতে পারি যেখানে a = (কে 1 + কে 2/2)। একটি প্রদত্ত অঙ্কের জন্য অনন্য। বর্গের যোগফল (a + b) ** 2 + (আব) ** 2 = 2 * (একটি 2 + বি 2)। প্রদত্ত অঙ্কের কে 1 + কে 2 এর জন্য , 2 টি শর্ত স্থির করা হয়েছে এবং আমরা দেখতে পাই যে 2 টার্মের কারণে স্কোয়ারগুলির যোগফল অনন্য হবে । সুতরাং, x এবং y এর মানগুলি এক জোড়া পূর্ণসংখ্যার জন্য স্বতন্ত্র।
phkahler

8
এটা সত্যিই দারুন. @ ব্যবহারকারী 3281743 এখানে একটি উদাহরণ। অনুপস্থিত সংখ্যাগুলি (কে 1 এবং কে 2) 4 এবং 6 হতে হবে যোগফল (1 -> 10) = 55 এবং যোগফল (1 ^ 2 -> 10 ^ 2) = 385 Now এখন x = 55 - (যোগফলটি সমস্ত অবশিষ্ট সংখ্যা) ) এবং y = 385 - (যোগফল (সমস্ত অবশিষ্ট সংখ্যার স্কোয়ার)) এভাবে x = 10 এবং y = 52. যা আমাদের দেখায় তার বিকল্প: (10 - কে 2) + 2 + কে 2 ^ 2 = 52 আপনি যা করতে পারেন সরল করুন: 2 কে ^ 2 - 20 কে + 48 = 0. চতুর্ভুজ সমীকরণটি সমাধান করা উত্তর হিসাবে আপনাকে 4 এবং 6 দেয়।
অ্যালেক্সকোরেন

137

@ J_random_hacker যেমন উল্লেখ করেছে, এটি ও (এন) সময় এবং ও (1) স্পেসে নকলগুলি সন্ধান করার মতো এবং এখানে আমার উত্তরের অভিযোজনটি এখানেও কাজ করে।

ধরে নিই যে "ব্যাগ" A[]আকারের 1-ভিত্তিক অ্যারে দ্বারা প্রতিনিধিত্ব করা হয়েছে N - k, আমরা O(N)সময় এবং O(k)অতিরিক্ত স্থান Qk সমাধান করতে পারি ।

প্রথমত, আমরা উপাদানগুলি A[]দ্বারা আমাদের অ্যারের প্রসারিত করি k, এটি এখন আকারের হয় N। এটি O(k)অতিরিক্ত স্থান। এরপরে আমরা নিম্নলিখিত সিডো-কোড অ্যালগোরিদমটি চালাই:

for i := n - k + 1 to n
    A[i] := A[1]
end for

for i := 1 to n - k
    while A[A[i]] != A[i] 
        swap(A[i], A[A[i]])
    end while
end for

for i := 1 to n
    if A[i] != i then 
        print i
    end if
end for

প্রথম লুপ initialises kএই পদক্ষেপ পর কোনো এন্ট্রি আকার প্রাথমিক অ্যারের মধ্যে অনুপস্থিত ছিল - অ্যারের মধ্যে প্রথম এন্ট্রি হিসাবে একই অতিরিক্ত এন্ট্রি (শুধু এই একটি সুবিধাজনক মান আমরা জানি যে অ্যারের মধ্যে ইতিমধ্যে উপস্থিত হয় N-kহয় এখনও বর্ধিত অ্যারে অনুপস্থিত)।

দ্বিতীয় লুপটি বর্ধিত অ্যারেটিকে অনুমতি দেয় যাতে যদি উপাদানটি xঅন্তত একবার উপস্থিত হয় তবে ent প্রবেশদ্বারগুলির মধ্যে একটিতে অবস্থান থাকবে A[x]

নোট যদিও এটি একটি নেস্টেড লুপ আছে, এটা এখনও রান যে O(N)আছে যদি একটি একটি swap শুধুমাত্র ঘটে - সময় iযেমন যে A[i] != iপ্রতিটি swap 'র সেট অন্তত একটি উপাদান যেমন যে, এবং A[i] == i, যেখানে তার আগে সত্য ছিল না। এর অর্থ হ'ল মোট অদলবদলের সংখ্যা (এবং এইভাবে whileলুপের দেহের মোট মৃত্যুদন্ড কার্যকর হওয়া সংখ্যা ) সর্বাধিক N-1

তৃতীয় লুপটি অ্যারের সেই সূচকগুলি মুদ্রণ iকরে যা মান দ্বারা দখল করা হয় না i- এর অর্থ এটি iঅবশ্যই অনুপস্থিত ছিল।


4
আমি ভাবছি কেন খুব কম লোকই এই উত্তরটিকে ভোট দেয় এবং এমনকি এটি সঠিক উত্তর হিসাবে চিহ্নিত করে না। পাইথনে কোড এখানে। এটি ও (এন) সময়ে চলে এবং অতিরিক্ত স্থান ও (কে) প্রয়োজন। পেস্টবিন.com
ওয়াল-ই

3
@ কেএফ এটি বিটগুলি সেট করার এবং বিট 0 স্থানগুলি গণনা করার সাথে বেশ সমান is
ফক্স

5
"বিট সেট করা এবং বিট 0 থাকা জায়গাগুলি গণনা করার জন্য ও (এন) অতিরিক্ত স্থান প্রয়োজন, এই সমাধানটি ও (কে) অতিরিক্ত স্থান কীভাবে ব্যবহার করবেন তা দেখায়।
ক্যাফে

7
স্ট্রিমগুলির সাথে ইনপুট হিসাবে কাজ করে না এবং ইনপুট অ্যারেটি সংশোধন করে (যদিও আমি এটি খুব পছন্দ করি এবং ধারণাটি ফলপ্রসূ)।
কমকো

3
@ ভি.ডডু: না, ঠিক আছে। অদলবদলটি পরিবর্তিত হবে A[i]যার অর্থ পরবর্তী পুনরুক্তি আগেরটির মতো একই দুটি মানের তুলনা করবে না। নতুন A[i]গত লুপ একই হবে যেমন A[A[i]], কিন্তু নতুন A[A[i]]একটি হতে হবে নতুন মান। চেষ্টা করে দেখুন।
ক্যাফে

128

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


20
;) আপনার 4 বছরের বয়সী অবশ্যই 5 বা / এর নিকটবর্তী হতে হবে এবং একটি প্রতিভা। আমার 4 বছরের কন্যা এখনও 4 এর সাথে সঠিকভাবে গণনা করতে পারে না। ভাল হতে হবে বলুন যে তিনি শেষ পর্যন্ত সবেমাত্র "4" এর অস্তিত্বকে একীভূত করেছিলেন। অন্যথায় এখন অবধি সে সবসময় এড়িয়ে চলে যেত। "1,2,3,5,6,7" ছিল তার সাধারণ গণনার ক্রম। আমি তাকে একসাথে পেন্সিল যুক্ত করতে বলেছিলাম এবং সে আবার স্ক্র্যাচ থেকে সমস্ত নাম্বার করে 1 + 2 = 3 পরিচালনা করবে। আমি আসলে চিন্তিত ...: '(মেহ ..
v.oddou

সহজ কিন্তু কার্যকর পদ্ধতির।
পাবটোরে

6
ও (রান্নাঘরের মেঝে) হা হা - তবে ও (ও ^ 2) হবে না?

13
O (m²) আমার অনুমান :)
ভিক্টর মেলগ্রেন

1
@ ফুকলভ: উত্তরে বলা হয়েছে যে "এটির জন্য ও (রান্নাঘরের মেঝে) এর প্রয়োজনীয় স্থান রয়েছে "। কিন্তু যাই হোক, এই একটি উদাহরণ হিসেবে বলা যায় যেখানে বাছাই হয় পারেন মধ্যে অর্জন করা হে (ঢ) সময় --- দেখুন এই আলোচনা
অ্যান্টনি ল্যাবারে

36

নিশ্চিত নন, যদি এটি সর্বাধিক দক্ষ সমাধান হয় তবে আমি সমস্ত এন্ট্রি লুপ করব এবং কোন বিট সেট করব তা মনে রাখতে বিটসেট ব্যবহার করব এবং তারপরে 0 বিটের জন্য পরীক্ষা করব।

আমি সহজ সমাধানগুলি পছন্দ করি - এবং আমি এমনকি বিশ্বাস করি যে এটি যোগফল, বা স্কোয়ারের যোগ ইত্যাদির চেয়ে আরও দ্রুত হতে পারে etc.


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

@ পলিজেনেলব্রিক্যান্টস: আপনি আপনার প্রশ্নে কোথায় বলেছিলেন তা আমি খুঁজে পাচ্ছি না। আপনি যদি বিটসেটটিকে ফলাফল হিসাবে বিবেচনা করেন তবে কোনও দ্বিতীয় পাস নেই। জটিলতাটি হ'ল (আমরা যদি এন কে ধ্রুবক হিসাবে বিবেচনা করি, যেমন সাক্ষাত্কারকারীর পরামর্শ অনুসারে, জটিলতাটি " কে এন-তে নয় " সংজ্ঞায়িত করা হয়েছে ) ও (1), এবং যদি আপনাকে আরও "পরিষ্কার" ফলাফল তৈরি করতে হয় তবে আপনি ও (কে) পান যা আপনি সবচেয়ে ভাল পেতে পারেন কারণ পরিষ্কার ফলাফল তৈরি করার জন্য আপনার সর্বদা ও (কে) প্রয়োজন need
ক্রিস Lerher

"নোট যে আমি সুস্পষ্ট সেট-ভিত্তিক সমাধান জন্য খুঁজছেন করছি না (যেমন একটি বিট সেট ব্যবহার করে," আসল প্রশ্নটি থেকে দ্বিতীয় শেষ
hrnt

9
@ এইচএমটি: হ্যাঁ, প্রশ্নটি কয়েক মিনিট আগে সম্পাদিত হয়েছিল। আমি কেবল উত্তর দিচ্ছি, যে আমি একজন মধ্যস্থতাকারীর কাছ থেকে প্রত্যাশা করব ... কৃত্রিমভাবে সাব-অনুকূল সমাধান তৈরি করা (আপনি ও (এন) + ও (কে) সময়কে পরাজিত করতে পারবেন না, আপনি যা কিছু করেন না) ' আমার কাছে কিছু বোঝার উপায় নেই - আপনি ও (এন) অতিরিক্ত স্থানের সামর্থ না রাখে তবে প্রশ্নটি এতে স্পষ্ট নয়।
ক্রিস Lerher

3
আরও স্পষ্ট করার জন্য আমি আবার প্রশ্নটি সম্পাদনা করেছি। আমি প্রতিক্রিয়া / উত্তর প্রশংসা করি।
বহুগেনুবিক্যান্টস

33

আমি গণিতগুলি পরীক্ষা করে দেখিনি, তবে আমি সন্দেহ করি যে Σ(n^2)আমরা গণনা করছিলাম একই পাসে কম্পিউটিং Σ(n)দুটি অনুপস্থিত নম্বর পেতে পর্যাপ্ত তথ্য সরবরাহ করবে, Σ(n^3)সেখানে তিনটি রয়েছে কিনা তেমনি করুন and


15

সংখ্যার সংখ্যার উপর ভিত্তি করে সমাধানগুলির সমস্যাটি হ'ল তারা বড় পরিমাণে এক্সপোজারগুলির সাথে সংখ্যার সাথে সংরক্ষণ এবং কাজ করার ব্যয়কে বিবেচনা করে না ... বাস্তবে, এটি খুব বড় এন এর জন্য কাজ করার জন্য, একটি বড় সংখ্যক গ্রন্থাগার ব্যবহৃত হত । আমরা এই অ্যালগরিদমের জন্য স্থান ব্যবহার বিশ্লেষণ করতে পারি।

আমরা এসডিসিভিভিসি এবং দিমিত্রিস অ্যান্ড্রেউয়ের অ্যালগরিদমের সময় এবং স্থান জটিলতা বিশ্লেষণ করতে পারি।

সঞ্চয় স্থান:

l_j = ceil (log_2 (sum_{i=1}^n i^j))
l_j > log_2 n^j  (assuming n >= 0, k >= 0)
l_j > j log_2 n \in \Omega(j log n)

l_j < log_2 ((sum_{i=1}^n i)^j) + 1
l_j < j log_2 (n) + j log_2 (n + 1) - j log_2 (2) + 1
l_j < j log_2 n + j + c \in O(j log n)`

সুতরাং l_j \in \Theta(j log n)

মোট ব্যবহৃত সঞ্চয়স্থান: \sum_{j=1}^k l_j \in \Theta(k^2 log n)

ব্যবহৃত স্থান: ধরে নিই যে কম্পিউটিংয়ে সময় a^jলাগে ceil(log_2 j), মোট সময়:

t = k ceil(\sum_i=1^n log_2 (i)) = k ceil(log_2 (\prod_i=1^n (i)))
t > k log_2 (n^n + O(n^(n-1)))
t > k log_2 (n^n) = kn log_2 (n)  \in \Omega(kn log n)
t < k log_2 (\prod_i=1^n i^i) + 1
t < kn log_2 (n) + 1 \in O(kn log n)

ব্যবহৃত মোট সময়: \Theta(kn log n)

যদি এই সময় এবং স্থানটি সন্তোষজনক হয় তবে আপনি একটি সাধারণ পুনরাবৃত্ত আলগোরিদিম ব্যবহার করতে পারেন। খ! আমি ব্যাগে আইথ এন্ট্রি হব, n অপসারণের পূর্বে সংখ্যাগুলির সংখ্যা, এবং কে অপসারণের সংখ্যা। হাস্কেল সিনট্যাক্সে ...

let
  -- O(1)
  isInRange low high v = (v >= low) && (v <= high)
  -- O(n - k)
  countInRange low high = sum $ map (fromEnum . isInRange low high . (!)b) [1..(n-k)]
  findMissing l low high krange
    -- O(1) if there is nothing to find.
    | krange=0 = l
    -- O(1) if there is only one possibility.
    | low=high = low:l
    -- Otherwise total of O(knlog(n)) time
    | otherwise =
       let
         mid = (low + high) `div` 2
         klow = countInRange low mid
         khigh = krange - klow
       in
         findMissing (findMissing low mid klow) (mid + 1) high khigh
in
  findMising 1 (n - k) k

ব্যবহৃত স্টোরেজ: O(k)তালিকার O(log(n))জন্য, স্ট্যাকের জন্য: O(k + log(n)) এই অ্যালগরিদমটি আরও স্বজ্ঞাত, একই সময়ে জটিলতা রয়েছে এবং কম স্থান ব্যবহার করে।


1
+1, দেখতে দুর্দান্ত লাগছে তবে আপনি আমাকে স্নিপেট # 1 এর 4 লাইন থেকে 5 নং লাইনে যেতে যেতে হারিয়েছেন - আপনি কি আরও ব্যাখ্যা করতে পারেন? ধন্যবাদ!
j_random_hacker

isInRangeহয় হে (লগ ঢ) , না হে (1) : এটা, পরিসর 1..n সংখ্যা তুলনা তাই এটি তুলনা করা হয়েছে হে (লগ ঢ) বিট। আমি জানি না এই ত্রুটিটি কী পরিমাণে বিশ্লেষণের বাকি অংশগুলিকে প্রভাবিত করে।
জ্যাকসাহ্নওয়াল্ড্ট বলেছেন GoFundMonica

14

একটি মিনিট অপেক্ষা করুন. প্রশ্নটি হিসাবে বলা হয়েছে, ব্যাগে 100 টি নম্বর রয়েছে। কে কত বড় হোক না কেন, সমস্যাটি ধ্রুবক সময়ে সমাধান করা যায় কারণ আপনি একটি সেট ব্যবহার করতে পারেন এবং একটি লুপের সর্বাধিক 100 - কে পুনরাবৃত্তিতে সেট থেকে সংখ্যাগুলি সরাতে পারেন। 100 ধ্রুবক। অবশিষ্ট সংখ্যা সেট আপনার উত্তর।

যদি আমরা 1 থেকে N পর্যন্ত সংখ্যার সমাধানটি সাধারণীকরণ করি তবে N ব্যতীত কোনও কিছুই পরিবর্তন হয় না ধ্রুবক নয়, তাই আমরা ও (এন - কে) = ও (এন) সময়ে আছি। উদাহরণস্বরূপ, আমরা যদি কিছু সেট ব্যবহার করি, আমরা বিটগুলি ও (এন) সময়ে 1 তে সেট করে, সংখ্যার মধ্য দিয়ে পুনরাবৃত্তি করি, বিটগুলি 0 হিসাবে নির্ধারণ করি (ও (এনকি) = ও (এন)) এবং তারপরে আমরা উত্তর আছে।

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


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

সমস্যাটি সহজ নয় তবে মানচিত্রের জন্য আপনাকে ও (এন) অতিরিক্ত মেমরি ব্যবহার করতে হবে। সমস্যাটি আমাকে ধ্রুবক সময় এবং ধ্রুবক স্মৃতিতে সমাধান করে
মোজো রিসিন

3
আমি বাজি ধরছি আপনি প্রমাণ করতে পারবেন ন্যূনতম সমাধানটি কমপক্ষে ও (এন)। কারণ কম, এর অর্থ হ'ল আপনি কিছু সংখ্যক দেখতেও পেলেন না এবং যেহেতু কোনও অর্ডার নির্দিষ্ট করা হয়নি, সমস্ত সংখ্যার দিকে তাকাতে বাধ্যতামূলক।
v.oddou

আমরা যদি ইনপুটটিকে স্ট্রিম হিসাবে দেখি এবং মেমরি রাখতে এন খুব বড় হয় তবে ও (কে) মেমরির প্রয়োজনীয়তাটি বোঝায়। যদিও আমরা এখনও হ্যাশিং ব্যবহার করতে পারি: কেবল কে ^ 2 বালতি তৈরি করুন এবং তাদের প্রতিটিটির জন্য সহজ যোগফলের অ্যালগরিদম ব্যবহার করুন। এটি কেবলমাত্র কে ^ 2 মেমরি এবং আরও কয়েকটি বালতি সাফল্যের উচ্চ সম্ভাবনা পেতে ব্যবহার করা যেতে পারে।
টমাস আহলে

8

2 (এবং 3) অনুপস্থিত সংখ্যার প্রশ্নটি সমাধান করার জন্য, আপনি সংশোধন করতে পারেন quickselect, যা গড়ে O(n)পার্টিশনটি জায়গায় রেখে সম্পন্ন করা হয় এবং এটি ধ্রুবক মেমরি ব্যবহার করে।

  1. একটি এলোমেলো পিভটকে pপার্টিশনে বিভক্ত করুন l, যার মধ্যে পিভটের চেয়ে ছোট সংখ্যা রয়েছে এবং এর rমধ্যে পিভটের চেয়েও বেশি সংখ্যা রয়েছে।

  2. প্রতিটি পার্টিশনের ( p - 1 - count(l) = count of missing numbers in lএবং n - count(r) - p = count of missing numbers in r) আকারের সাথে পিভট মানটির তুলনা করে 2 টি অনুপস্থিত সংখ্যা কোন পার্টিশনে রয়েছে তা নির্ধারণ করুন

  3. ক) প্রতিটি পার্টিশনে যদি একটি নম্বর অনুপস্থিত থাকে, তবে প্রতিটি অনুপস্থিত নম্বর সন্ধানের জন্য অঙ্কের পদ্ধতির পার্থক্যটি ব্যবহার করুন।

    (1 + 2 + ... + (p-1)) - sum(l) = missing #1 এবং ((p+1) + (p+2) ... + n) - sum(r) = missing #2

    খ) যদি একটি পার্টিশনে উভয় সংখ্যা অনুপস্থিত থাকে এবং পার্টিশনটি খালি থাকে, তবে অনুপস্থিত সংখ্যাগুলি হয় (p-1,p-2)বা কোনও (p+1,p+2) পার্টিশনের সংখ্যাগুলি অনুপস্থিত রয়েছে তার উপর নির্ভর করে।

    যদি একটি পার্টিশনে 2 নম্বর অনুপস্থিত তবে শূন্য না থাকে, তবে সেই অংশটিতে পুনরাবৃত্তি করুন।

মাত্র 2 টি অনুপস্থিত সংখ্যার সাথে, এই অ্যালগরিদম সর্বদা কমপক্ষে একটি বিভাজন ত্যাগ করে, তাই এটি O(n)দ্রুতগতির নির্বাচনের গড় সময়ের জটিলতা ধরে রাখে । একইভাবে, 3 টি অনুপস্থিত সংখ্যার সাথে এই অ্যালগরিদম প্রতিটি পাসের সাথে কমপক্ষে একটি বিভাজনও বাতিল করে দেয় (কারণ 2 টি অনুপস্থিত সংখ্যার মতো, কেবলমাত্র 1 টি পার্টিশনে একাধিক নিখোঁজ সংখ্যা থাকবে)। যাইহোক, আমি নিশ্চিত নই যে আরও অনুপস্থিত সংখ্যা যুক্ত করা হলে পারফরম্যান্স কতটা কমে যায়।

এখানে এমন একটি বাস্তবায়ন রয়েছে যা স্থানের পার্টিশন ব্যবহার করে না , সুতরাং এই উদাহরণটি স্থানের প্রয়োজনীয়তা পূরণ করে না তবে এটি আলগোরিদমের পদক্ষেপগুলি চিত্রিত করে:

<?php

  $list = range(1,100);
  unset($list[3]);
  unset($list[31]);

  findMissing($list,1,100);

  function findMissing($list, $min, $max) {
    if(empty($list)) {
      print_r(range($min, $max));
      return;
    }

    $l = $r = [];
    $pivot = array_pop($list);

    foreach($list as $number) {
      if($number < $pivot) {
        $l[] = $number;
      }
      else {
        $r[] = $number;
      }
    }

    if(count($l) == $pivot - $min - 1) {
      // only 1 missing number use difference of sums
      print array_sum(range($min, $pivot-1)) - array_sum($l) . "\n";
    }
    else if(count($l) < $pivot - $min) {
      // more than 1 missing number, recurse
      findMissing($l, $min, $pivot-1);
    }

    if(count($r) == $max - $pivot - 1) {
      // only 1 missing number use difference of sums
      print array_sum(range($pivot + 1, $max)) - array_sum($r) . "\n";
    } else if(count($r) < $max - $pivot) {
      // mroe than 1 missing number recurse
      findMissing($r, $pivot+1, $max);
    }
  }

ডেমো


সেটটি বিভক্ত করা লিনিয়ার স্পেস ব্যবহার করার মতো। কমপক্ষে এটি স্ট্রিমিং সেটিংয়ে কাজ করবে না।
থমাস আহলে

@ThomasAhle দেখতে en.wikipedia.org/wiki/Selection_algorithm#Space_complexity । স্থানে সেটটি বিভক্ত করতে কেবল ও (1) অতিরিক্ত স্থান প্রয়োজন - লিনিয়ার স্পেস নয়। স্ট্রিমিং সেটিংয়ে এটি ও (কে) অতিরিক্ত স্থান হবে তবে মূল প্রশ্নটি স্ট্রিমিংয়ের উল্লেখ করে না।
FuzzyTree

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

1
তবে আপনি যেমন বলেছিলেন যে আরও সংখ্যক সংযোজন হওয়ায় পারফরম্যান্স কমে যেতে পারে? সর্বদা নিখুঁত কাট পেতে আমরা লিনিয়ার টাইম মিডিয়ান অ্যালগরিদমও ব্যবহার করতে পারি, তবে কে সংখ্যাগুলি 1 তে ভালভাবে ছড়িয়ে গেলে, ..., এন, আপনি ছাঁটাই করার আগে আপনাকে লগের মাত্রা "গভীর" করতে হবে না কোন শাখা?
টমাস আহলে

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

7

এখানে এমন একটি সমাধান রয়েছে যা কোনও চালাক কৌশল ছাড়াই এবং কেবল সোজাসুজি ছাড়া অতিরিক্ত স্টোরেজের কে বিট ব্যবহার করে। কার্যকর করার সময় ও (এন), অতিরিক্ত স্থান ও (কে)। প্রথমে সমাধানটি না পড়ে বা প্রতিভা না পেয়ে সমাধান করা যায় তা প্রমাণ করার জন্য:

void puzzle (int* data, int n, bool* extra, int k)
{
    // data contains n distinct numbers from 1 to n + k, extra provides
    // space for k extra bits. 

    // Rearrange the array so there are (even) even numbers at the start
    // and (odd) odd numbers at the end.
    int even = 0, odd = 0;
    while (even + odd < n)
    {
        if (data [even] % 2 == 0) ++even;
        else if (data [n - 1 - odd] % 2 == 1) ++odd;
        else { int tmp = data [even]; data [even] = data [n - 1 - odd]; 
               data [n - 1 - odd] = tmp; ++even; ++odd; }
    }

    // Erase the lowest bits of all numbers and set the extra bits to 0.
    for (int i = even; i < n; ++i) data [i] -= 1;
    for (int i = 0; i < k; ++i) extra [i] = false;

    // Set a bit for every number that is present
    for (int i = 0; i < n; ++i)
    {
        int tmp = data [i];
        tmp -= (tmp % 2);
        if (i >= even) ++tmp;
        if (tmp <= n) data [tmp - 1] += 1; else extra [tmp - n - 1] = true;
    }

    // Print out the missing ones
    for (int i = 1; i <= n; ++i)
        if (data [i - 1] % 2 == 0) printf ("Number %d is missing\n", i);
    for (int i = n + 1; i <= n + k; ++i)
        if (! extra [i - n - 1]) printf ("Number %d is missing\n", i);

    // Restore the lowest bits again.
    for (int i = 0; i < n; ++i) {
        if (i < even) { if (data [i] % 2 != 0) data [i] -= 1; }
        else { if (data [i] % 2 == 0) data [i] += 1; }
    }
}

আপনি কি চান (data [n - 1 - odd] % 2 == 1) ++odd;?
চার্লস

2
এটি কীভাবে কাজ করে তা আপনি ব্যাখ্যা করতে পারেন? আমি বুঝতে পারছি না।
তেপীম্মে

সমাধানটি খুব, খুব সহজ হবে যদি আমি অস্থায়ী সঞ্চয়ের জন্য (এন + কে) বুলিয়ানগুলির একটি অ্যারে ব্যবহার করতে পারি তবে এটি অনুমোদিত নয়। সুতরাং আমি শুরুতে সমান সংখ্যাগুলি এবং অ্যারের শেষে বিজোড় সংখ্যাগুলি রেখে ডেটাটি পুনরায় সাজাই। এখন n এন সংখ্যার সর্বনিম্ন বিটগুলি অস্থায়ী স্টোরেজ জন্য ব্যবহার করা যেতে পারে, কারণ আমি জানি যে সেখানে কতগুলি এমনকি বিজোড় সংখ্যা রয়েছে এবং সর্বনিম্ন বিটগুলি পুনর্গঠন করতে পারে! এই এন বিটস এবং কে অতিরিক্ত বিটগুলি হ'ল (এন + কে) বুলিয়ান যা আমার প্রয়োজন।
gnasher729

2
মেমরি রাখতে যদি ডেটা খুব বেশি পরিমাণে থাকে তবে এটি কাজ করবে না এবং আপনি কেবল এটিকে একটি স্ট্রিম হিসাবে দেখেছেন। সুস্বাদুভাবে হ্যাকি যদিও :)
থমাস আহলে

স্থান জটিলতা ও (1) হতে পারে। প্রথম পাসে, আপনি 'অতিরিক্ত' ব্যবহার না করে সমস্ত সংখ্যা <(এন - কে) ঠিক এই অ্যালগরিদম দ্বারা প্রক্রিয়া করেন। দ্বিতীয় পাসে, আপনি আবার সমতা বিটগুলি সাফ করুন এবং সংখ্যার (এন কে) .. (এন) এর জন্য প্রথম কে অবস্থান ব্যবহার করুন।
ইমু

5

আপনি প্রতিটি নম্বর আছে কিনা তা পরীক্ষা করতে পারেন? যদি হ্যাঁ আপনি এটি ব্যবহার করতে পারেন:

এস = ব্যাগের সমস্ত সংখ্যার যোগফল (এস <5050)
জেড = অনুপস্থিত সংখ্যার 5050 - এস এর যোগফল

যদি অনুপস্থিত সংখ্যা হয় xএবং yতারপর:

x = Z - y এবং
সর্বোচ্চ (x) = জেড - 1

আপনার কাছ থেকে পরিসীমা পরীক্ষা 1করতে max(x)এবং সংখ্যা খুঁজে বের


1
সংখ্যাটি max(x)কখন, মানে কী x?
থমাস আহলে

2
তিনি সম্ভবত সংখ্যার সেট থেকে সর্বোচ্চটি
বোঝাতে পারেন

আমাদের যদি 2 টির বেশি সংখ্যক থাকে তবে এই সমাধানটি
ফাঁস

4

এই অ্যালগরিদম প্রশ্ন 1 এর জন্য কাজ করতে পারে:

  1. প্রথম 100 পূর্ণসংখ্যার পূর্ববর্তী জোড় (ভাল = 1 ^ 2 ^ 3 ^ 4 .... 100)
  2. ইনপুট স্ট্রিম থেকে আগত উপাদানগুলিকে Xor করুন (val1 = val1 ^ next_input)
  3. চূড়ান্ত উত্তর = ভাল ^ ভাল 1

বা আরও ভাল:

def GetValue(A)
  val=0
  for i=1 to 100
    do
      val=val^i
    done
  for value in A:
    do
      val=val^value 
    done
  return val

এই অ্যালগরিদমটি আসলে দুটি অনুপস্থিত সংখ্যার জন্য বাড়ানো যেতে পারে। প্রথম পদক্ষেপটি একই থাকে। যখন আমরা দুটি অনুপস্থিত সংখ্যার সাথে গেটভ্যালুকে কল করি তখন ফলাফলটি হ'ল a1^a2দুটি অনুপস্থিত নম্বর। চল বলি

val = a1^a2

এখন ভাল থেকে a1 এবং a2 চালানোর জন্য আমরা ভাল মধ্যে কোনও সেট বিট নিই। বলুন ithবিটটি ভালতে সেট করা আছে। তার মানে ithবিট পজিশনে এ 1 এবং এ 2 এর আলাদা সমতা রয়েছে । এখন আমরা মূল অ্যারেতে আরেকটি পুনরাবৃত্তি করি এবং দুটি এক্সওর মান রাখি। Ith বিট সেট রয়েছে এমন সংখ্যার জন্য একটি এবং অন্যটিতে ith বিট সেট নেই। আমাদের কাছে এখন দুটি বালতি সংখ্যা রয়েছে এবং এর গ্যারান্টি রয়েছে যে a1 and a2বিভিন্ন বালতিতে পড়ে থাকবে lie এখন প্রতিটি বালতিতে একটি করে অনুপস্থিত উপাদান খুঁজে বের করার জন্য আমরা যা করেছি তার পুনরাবৃত্তি করুন।


এটি কেবল সমস্যার সমাধান করে k=1, তাই না? তবে আমি xorওভারের অঙ্কগুলি ব্যবহার করতে চাই , এটি কিছুটা দ্রুত বলে মনে হচ্ছে।
টমাস আহলে

@ থমাসআহলে হ্যাঁ আমি আমার উত্তরে এটি ডেকেছি।
বাশার্ক

ঠিক। K = 2 এর জন্য "দ্বিতীয় আদেশ" জোর কী হতে পারে আপনার কোনও ধারণা আছে? সমষ্টিগুলির জন্য স্কোয়ার ব্যবহার করার মতো, আমরা কি জোরের জন্য "বর্গ" করতে পারি?
টমাস আহলে

1
@ থমাস অহলে এটি 2 টি হারিয়ে যাওয়া সংখ্যার জন্য কাজ করতে সংশোধন করেছে।
বাশার্ক

এটি আমার প্রিয় উপায় :)
রবার্ট কিং

3

আপনার যদি উভয় তালিকার যোগফল এবং উভয় তালিকার পণ্য থাকে তবে আপনি Q2 সমাধান করতে পারেন।

(l1 মূল, l2 পরিবর্তিত তালিকা)

d = sum(l1) - sum(l2)
m = mul(l1) / mul(l2)

একটি গাণিতিক সিরিজের যোগফল প্রথম এবং শেষ পদগুলির গড়ের চেয়ে দ্বিগুণ হওয়ায় আমরা এটিকে অনুকূল করতে পারি:

n = len(l1)
d = (n/2)*(n+1) - sum(l2)

এখন আমরা জানি যে (যদি a এবং b অপসারণের সংখ্যা হয়):

a + b = d
a * b = m

সুতরাং আমরা এটিকে পুনরায় সাজিয়ে তুলতে পারি:

a = s - b
b * (s - b) = m

এবং গুণিত:

-b^2 + s*b = m

এবং পুনর্বিন্যাস করুন যাতে ডান দিকটি শূন্য হয়:

-b^2 + s*b - m = 0

তারপরে আমরা চতুর্ভুজ সূত্রে সমাধান করতে পারি:

b = (-s + sqrt(s^2 - (4*-1*-m)))/-2
a = s - b

পাইথন 3 কোডের নমুনা:

from functools import reduce
import operator
import math
x = list(range(1,21))
sx = (len(x)/2)*(len(x)+1)
x.remove(15)
x.remove(5)
mul = lambda l: reduce(operator.mul,l)
s = sx - sum(x)
m = mul(range(1,21)) / mul(x)
b = (-s + math.sqrt(s**2 - (-4*(-m))))/-2
a = s - b
print(a,b) #15,5

আমি স্কয়ার্টের জটিলতা, হ্রাস এবং যোগফলগুলি জানি না তাই আমি এই সমাধানটির জটিলতাটি কাজ করতে পারি না (যদি কেউ জানেন তবে নীচে মন্তব্য করুন))


এটি গণনা করতে কত সময় এবং স্মৃতি ব্যবহার করে x1*x2*x3*...?
থমাস আহলে

@ থমাসএহলে এটি ও (এন) -সময়ের এবং ও (1) -র তালিকাটির দৈর্ঘ্যের ক্ষেত্রে রয়েছে, তবে বাস্তবে এটি গুন হিসাবে বেশি (কমপক্ষে পাইথনে) হ'ল ও (এন ^ 1.6) - সময় দৈর্ঘ্যের সময় সংখ্যা এবং সংখ্যাগুলি তাদের দৈর্ঘ্যের ও (লগ এন) - স্পেস।
টুওমাস লাককোনেন

@ থমাস অহলে নং, লগ (এ ^ n) = এন * লগ (ক) যাতে আপনার কাছে ও (এল লগ কে)-নম্বরটি সঞ্চয় করার স্থান থাকে। সুতরাং দৈর্ঘ্যের l এবং দৈর্ঘ্যের কে এর মূল সংখ্যার একটি তালিকা দেওয়া আপনার ও (এল) স্পেসে থাকবে তবে ধ্রুবক ফ্যাক্টর (লগ কে) এগুলি সমস্ত লেখার চেয়ে কম হবে। (আমি মনে করি না যে আমার পদ্ধতিটি প্রশ্নের উত্তর দেওয়ার একটি বিশেষ উপায়))
টুওমাস লাককোনেন

3

কিউ 2 এর জন্য এটি এমন একটি সমাধান যা অন্যদের তুলনায় কিছুটা অদক্ষ, তবে এখনও ও (এন) রানটাইম রয়েছে এবং ও (কে) স্থান নেয়।

আসল অ্যালগরিদমটি দু'বার চালানোর ধারণাটি। প্রথমটিতে আপনি একটি মোট নম্বর পেয়ে যা নিখোঁজ রয়েছে যা আপনাকে অনুপস্থিত সংখ্যার উপরের সীমা দেয়। এই নাম্বারে কল করুন N। আপনি জানেন যে নিখোঁজ দুটি সংখ্যা যোগ করতে চলেছে N, সুতরাং প্রথম সংখ্যাটি কেবলমাত্র বিরতিতে [1, floor((N-1)/2)]থাকতে পারে যখন দ্বিতীয়টি হতে চলেছে [floor(N/2)+1,N-1]

সুতরাং আপনি সমস্ত সংখ্যায় আবার লুপ করুন, প্রথম বিরতিতে অন্তর্ভুক্ত নয় এমন সমস্ত সংখ্যা বাদ দিয়ে। যেগুলি হ'ল, আপনি তাদের যোগফলের উপর নজর রাখেন। অবশেষে, আপনি নিখোঁজ দুটি সংখ্যার একটি এবং দ্বিতীয়টি বর্ধিত করে জানতে পারবেন।

আমার অনুভূতি আছে যে এই পদ্ধতিটি সাধারণীকরণ করা যেতে পারে এবং ইনপুটটির একক পাসের সময় একাধিক অনুসন্ধানগুলি "সমান্তরাল" তে চলতে পারে, তবে কীভাবে তা আমি এখনও বুঝতে পারি নি।


আহা হ্যাঁ এই একই সমাধান আমি Q2 এর জন্য এলাম, আবার যোগফল গণনা করে আবার N / 2 এর নীচে সমস্ত সংখ্যার জন্য negative ণাত্মক নিয়েছি , তবে এটি আরও ভাল!
xjcl

2

আমি মনে করি কোনও জটিল গাণিতিক সমীকরণ এবং তত্ত্বগুলি ছাড়াই এটি করা যায়। নীচে একটি স্থান এবং ও (2 এন) সময় জটিলতার সমাধানের জন্য প্রস্তাব দেওয়া হল:

ইনপুট ফর্ম অনুমান:

ব্যাগে সংখ্যার সংখ্যা = এন

# অনুপস্থিত সংখ্যা = কে

ব্যাগের সংখ্যাগুলি দৈর্ঘ্যের একটি অ্যারের দ্বারা প্রতিনিধিত্ব করা হয়

আলগো = এন এর জন্য ইনপুট অ্যারের দৈর্ঘ্য

অ্যারেতে অনুপস্থিত এন্ট্রিগুলি (ব্যাগ থেকে নেওয়া সংখ্যাগুলি) অ্যারেতে প্রথম উপাদানটির মান দ্বারা প্রতিস্থাপিত হয়।

যেমন। প্রাথমিকভাবে ব্যাগ [2,9,3,7,8,6,4,5,1,10] এর মতো দেখাচ্ছে। যদি 4 আউট নেওয়া হয় তবে 4 এর মান 2 হবে (অ্যারের প্রথম উপাদান)। সুতরাং ব্যাগটি চারটি বের করার পরে [2,9,3,7,8,6,2,5,1,10] এর মতো দেখাবে]

এই সমাধানের মূলটি হ'ল অ্যারেটি ট্র্যাভারসড হওয়ায় সেই INDEX এ মানটিকে উপেক্ষা করে একটি পরিদর্শন করা সংখ্যার আইএনডেক্সকে ট্যাগ করা।

    IEnumerable<int> GetMissingNumbers(int[] arrayOfNumbers)
    {
        List<int> missingNumbers = new List<int>();
        int arrayLength = arrayOfNumbers.Length;

        //First Pass
        for (int i = 0; i < arrayLength; i++)
        {
            int index = Math.Abs(arrayOfNumbers[i]) - 1;
            if (index > -1)
            {
                arrayOfNumbers[index] = Math.Abs(arrayOfNumbers[index]) * -1; //Marking the visited indexes
            }
        }

        //Second Pass to get missing numbers
        for (int i = 0; i < arrayLength; i++)
        {                
            //If this index is unvisited, means this is a missing number
            if (arrayOfNumbers[i] > 0)
            {
                missingNumbers.Add(i + 1);
            }
        }

        return missingNumbers;
    }

এটি খুব বেশি স্মৃতি ব্যবহার করে।
থমাস আহলে

2

এই জাতীয় স্ট্রিমিং অ্যালগরিদমগুলিকে সাধারণীকরণের একটি সাধারণ উপায় রয়েছে। আশা kকরা যায় যে উপাদানগুলি স্বাধীন সাব সমস্যাগুলিতে 'ছড়িয়ে' দেওয়ার জন্য কিছুটা এলোমেলোভাবে ব্যবহার করা, যেখানে আমাদের মূল অ্যালগোরিদম আমাদের জন্য সমস্যাটি সমাধান করে। এই কৌশলটি অন্যান্য জিনিসের পাশাপাশি বিচ্ছিন্ন সংকেত পুনর্গঠনে ব্যবহৃত হয়।

যদি সমস্ত অনুপস্থিত নম্বরগুলি বিভিন্ন বালতিতে নিয়ে যায় তবে অ্যারের অ-শূন্য উপাদানগুলিতে এখন অনুপস্থিত সংখ্যা থাকবে contain

কোনও নির্দিষ্ট জুটিকে একই বালতিতে প্রেরণের সম্ভাবনা, 1/uসার্বজনীন হ্যাশ ফাংশনের সংজ্ঞা অনুসারে কম । যেহেতু চলেছেন k^2/2জোড়া, আমরা যে ত্রুটি সম্ভাব্যতা সর্বাধিক আছে k^2/2/u=1/2। এটি হ'ল, আমরা কমপক্ষে 50% সম্ভাবনা নিয়ে সফল হই এবং আমরা যদি বৃদ্ধি uকরি তবে আমাদের সম্ভাবনা বৃদ্ধি করে।

লক্ষ্য করুন যে এই অ্যালগরিদম k^2 lognস্থান বিট নেয় (আমাদের lognঅ্যারে বালতি প্রতি বিট প্রয়োজন ।) এটি @ ডিমিট্রিস অ্যান্ড্রু এর উত্তর দ্বারা প্রয়োজনীয় স্থানের সাথে মেলে (বিশেষত বহুত্বগত কারণের প্রয়োজন হয়, যা এলোমেলোভাবে ঘটে বলেও মনে হয়।) এই অ্যালগরিদমে স্থিরও থাকে kপাওয়ার-অঙ্কের ক্ষেত্রে সময়ের চেয়ে পরিবর্তে আপডেটের সময় ।

আসলে, আমরা মন্তব্যে বর্ণিত কৌশলটি ব্যবহার করে পাওয়ার যোগফল পদ্ধতির চেয়ে আরও দক্ষ হতে পারি।


দ্রষ্টব্য: আমাদের মেশিনে এটি যদি দ্রুত হয় তবে আমরা xorপ্রতিটি বালতিতেও ব্যবহার করতে পারি sum
টমাস আহলে

আকর্ষণীয় তবে আমি মনে করি এটি কেবল স্থান সীমাবদ্ধতার প্রতি সম্মান জানায় k <= sqrt(n)- কমপক্ষে যদি u=k^2? ধরুন কে = 11 এবং এন = 100, তাহলে আপনার কাছে 121 বালতি থাকবে এবং অ্যালগরিদমটি 100 বিটের অ্যারে থাকার সমান হবে যা আপনি প্রতিটি # স্ট্রিম থেকে পড়ার সাথে সাথে পরীক্ষা করে ফেলবেন। ক্রমবর্ধমান uসাফল্যের সম্ভাবনাগুলিকে উন্নতি করে তবে স্থান সীমাবদ্ধতা অতিক্রম করার আগে আপনি এটি কতটা বাড়িয়ে দিতে পারবেন তার সীমা রয়েছে।
ফাজিট্রি

1
আমি মনে করি, সমস্যাটি তার nচেয়ে অনেক বড় ক্ষেত্রে সবচেয়ে বেশি অর্থবোধ করে k, তবে আপনি k lognস্থির সময়ের আপডেট থাকার পরেও বর্ণিত হ্যাশিংয়ের অনুরূপ একটি পদ্ধতির সাহায্যে স্থান পেতে পারেন । এটি gnunet.org/eppstein-set-recشتہ মধ্যে বর্ণিত হয়েছে , ক্ষমতার পদ্ধতির যোগফলের মতো, তবে মূলত আপনি ট্যাবুলেশন হ্যাশিংয়ের মতো শক্তিশালী হ্যাশ ফাংশন সহ 'দুটি কে' বালতিতে হ্যাশ করেন যা গ্যারান্টি দেয় যে কিছু বালতিতে কেবল একটি উপাদান থাকবে will । ডিকোড করার জন্য, আপনি সেই বালতিটি শনাক্ত করুন এবং এর দুটি বালতি থেকে উপাদানটি সরিয়ে ফেলুন, যা (সম্ভবত) অন্য বালতি মুক্ত করে দেয়
থমাস অহলে

2

কিউ 2 এর একটি খুব সহজ সমাধান যা আমি অবাক হয়েছি কেউই এরই মধ্যে উত্তর দেয় নি। দুটি অনুপস্থিত সংখ্যার যোগফল খুঁজতে Q1 থেকে পদ্ধতিটি ব্যবহার করুন। আসুন এটি এস দ্বারা বোঝান, তারপরে অনুপস্থিত একটি সংখ্যার এস / 2 এর চেয়ে ছোট এবং অন্যটি এস / 2 (দুহ) এর চেয়ে বড়। 1 থেকে এস / 2 পর্যন্ত সমস্ত সংখ্যার যোগ করুন এবং অনুপস্থিত সংখ্যার মধ্যে নিম্নটি ​​খুঁজে পেতে সূত্রের ফলাফলের সাথে (Q1 তে থাকা পদ্ধতির অনুরূপ) তুলনা করুন। বৃহত্তর নিখোঁজ নম্বরটি পেতে এটি এস থেকে বিয়োগ করুন।


আমি মনে করি এটি সোভালোরজেনের উত্তরের সমান , তবে আপনি এটি আরও ভাল কথায় ব্যাখ্যা করেছেন। কিউকে এটিকে সাধারণীকরণ করতে কীভাবে কোনও ধারণা আছে?
জন ম্যাকক্লেইন

অন্য উত্তর মিস করার জন্য দুঃখিত। আমি এটিকে ize Q_k to এ সাধারণীকরণ করা সম্ভব কিনা তা আমি নিশ্চিত নই সে ক্ষেত্রে আপনি ক্ষুদ্রতম অনুপস্থিত উপাদানটিকে কিছু পরিসরে আবদ্ধ করতে পারবেন না। আপনি জানেন যে কিছু উপাদান অবশ্যই $ এস / কে than এর চেয়ে ছোট হওয়া উচিত তবে এটি একাধিক উপাদানগুলির পক্ষে সত্য হতে পারে
গিলাদ ডয়েশ

1

খুব সুন্দর সমস্যা। আমি কিউকে জন্য একটি নির্দিষ্ট পার্থক্য ব্যবহার করতে যাব। এমনকি অনেকগুলি প্রোগ্রামিং ভাষার পক্ষে এর পক্ষে সমর্থন রয়েছে, যেমন রুবি:

missing = (1..100).to_a - bag

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


1
এটি খুব বেশি স্থান ব্যবহার করে।
থমাস আহলে

@ থমাসএহলে: আপনি প্রতি দ্বিতীয় উত্তরে কেন অকেজো মন্তব্য যুক্ত করছেন? এটি অতিরিক্ত স্থান ব্যবহার করে আপনার কী বোঝাতে চাইছেন?
ডার্কডাস্ট

কারণ প্রশ্নটি বলে যে "আমরা এন এর সমানুপাতিক কোনও অতিরিক্ত স্থান বহন করতে পারি না।" এই সমাধানটি ঠিক তাই করে।
থমাস আহলে

1

আপনি একটি ব্লুম ফিল্টার ব্যবহার করে দেখতে পারেন । ফুলটিতে ব্যাগের প্রতিটি সংখ্যা সন্নিবেশ করান, তারপরে প্রতিটি 1 টি না পেয়ে রিপোর্ট করা পর্যন্ত সম্পূর্ণ 1-কে সেট দিয়ে পুনরাবৃত্তি করুন। এটি সমস্ত পরিস্থিতিতে উত্তরটি নাও পেতে পারে তবে এটি যথেষ্ট ভাল সমাধান হতে পারে।


এছাড়াও গণনা ব্লুম ফিল্টার রয়েছে, যা মুছতে সক্ষম করে। তারপরে আপনি কেবল সমস্ত নম্বর যুক্ত করতে পারেন এবং স্রোতে আপনি যেগুলি দেখেন তা মুছতে পারেন।
টমাস আহলে 21

হাহা এটি সম্ভবত আরও ব্যবহারিক উত্তরগুলির মধ্যে একটি, তবে খুব কম মনোযোগ পান।
ldog

1

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

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

এটি অবশ্যই কারণ পুরো জিনিস রান সংখ্যার ব্যাচ প্রসেসিং প্রাক উত্পন্ন ব্যাগ জন্য দ্রুততম পদ্ধতি নয় O((log 1 + log 2 + ... + log n) + (log n + log n-1 + ... + log k))। তবে এটি কোনও মূল্যের জন্য কাজ করে k(এটি সময়ের আগে জানা না গেলেও) এবং উপরের উদাহরণে এটি এমনভাবে প্রয়োগ করা হয়েছিল যা সবচেয়ে গুরুত্বপূর্ণ ব্যবধানকে হ্রাস করে।


আপনার যদি কেবল ও (কে ^ 2) অতিরিক্ত মেমরি থাকে তবে এটি কাজ করবে?
থমাস আহলে

1

প্রতিস্থাপনের ক্ষেত্রে (গোষ্ঠীগুলি, গণিত ভাষায়) বিবেচনা করে সমাধানটি উদ্বুদ্ধ করতে পারেন। সংখ্যার সেটের ক্রম যাই হোক না কেন, উত্তরটি একই হওয়া উচিত। যদি আপনি kঅনুপস্থিত উপাদানগুলি নির্ধারণ করতে সহায়তা করতে ফাংশন ব্যবহার করতে যাচ্ছেন তবে আপনার কী কী ফাংশনগুলির মধ্যে সেই সম্পত্তি আছে তা নিয়ে চিন্তা করা উচিত: প্রতিসম। ফাংশনটি s_1(x) = x_1 + x_2 + ... + x_nএকটি প্রতিসম ফাংশনের উদাহরণ, তবে উচ্চতর ডিগ্রির অন্যরাও রয়েছেন। বিশেষত, প্রাথমিক প্রতিসাম্য কার্যাদি বিবেচনা করুন । ডিগ্রি 2 এর প্রাথমিক প্রতিসম ফাংশন হ'ল s_2(x) = x_1 x_2 + x_1 x_3 + ... + x_1 x_n + x_2 x_3 + ... + x_(n-1) x_nদুটি উপাদানের সমস্ত পণ্যের যোগফল। একইভাবে 3 ডিগ্রি এবং উচ্চতর প্রাথমিক প্রতিসাম্য কার্যের জন্য। তারা স্পষ্টতই প্রতিসম হয়। তদ্ব্যতীত, দেখা যাচ্ছে যে তারা সমস্ত প্রতিসাম্য কার্যের জন্য বিল্ডিং ব্লক।

এটি লক্ষ করে আপনি প্রাথমিক প্রতিসাম্য ফাংশনগুলি তৈরি করতে পারেন s_2(x,x_(n+1)) = s_2(x) + s_1(x)(x_(n+1))। আরও চিন্তাভাবনা আপনাকে s_3(x,x_(n+1)) = s_3(x) + s_2(x)(x_(n+1))তাও বোঝাতে হবে এবং এগুলিও যাতে একটি পাসে তাদের গণনা করা যায়।

অ্যারে থেকে কোন আইটেমগুলি অনুপস্থিত ছিল তা আমরা কীভাবে বলতে পারি? বহুবর্ষ সম্পর্কে চিন্তা করুন (z-x_1)(z-x_2)...(z-x_n)0আপনি কোনও সংখ্যার মধ্যে রাখেন কিনা তা মূল্যায়ন করে x_i। বহুপদী প্রসারিত, আপনি পাবেন z^n-s_1(x)z^(n-1)+ ... + (-1)^n s_n। প্রাথমিক প্রতিসাম্য ফাংশনগুলি এখানেও উপস্থিত হয়, যা সত্যিই অবাক হওয়ার কিছু নেই, যেহেতু আমরা যদি শিকড়গুলিতে কোনও অনুক্রম প্রয়োগ করি তবে বহুবচন একই থাকবে the

সুতরাং আমরা বহুপদী তৈরি করতে পারি এবং সেটগুলি নির্ধারণ করার চেষ্টা করতে পারি যে অন্যান্য সংখ্যা উল্লেখ করে কোন সংখ্যাটি সেটে নেই।

অবশেষে, যদি আমরা প্রচুর সংখ্যার সাথে মেমরি উপচে পড়ার বিষয়ে উদ্বিগ্ন (নবম প্রতিসাম্য বহুপদী ক্রম হবে 100!), তবে আমরা এই গণনাগুলি করতে পারি mod pযেখানে p১০০ এর চেয়ে বড় একটি প্রধান। সেক্ষেত্রে আমরা বহুপদীকে মূল্যায়ন করি mod pএবং এটি আবার পরীক্ষা করে দেখেছি যে এটি আবার মূল্যায়ন করে থেকে 0যখন ইনপুট সেটে একটি সংখ্যা, এবং এটি একটি অ শূন্য মান মূল্যায়ন করে যখন ইনপুট একটি সংখ্যা সেট নেই। যাইহোক, অন্যরা যেমন উল্লেখ করেছে, সময়ের সাথে বহুত্বের মূল্যবোধগুলি বের করার জন্য যা নির্ভর করে k, তা নয় N, আমাদের বহুপদীকে গুণন করতে হবে mod p


1

তবুও অন্য উপায় অবলম্বন গ্রাফ ফিল্টারিং ব্যবহার করা হয়।

মনে করুন আমাদের 1 থেকে 4 নম্বর রয়েছে এবং 3 টি অনুপস্থিত রয়েছে। বাইনারি উপস্থাপনা নিম্নলিখিত,

1 = 001 বি, 2 = 010 বি, 3 = 011 বি, 4 = 100 বি

এবং আমি নীচের মত একটি ফ্লো-গ্রাফ তৈরি করতে পারি।

                   1
             1 -------------> 1
             |                | 
      2      |     1          |
0 ---------> 1 ----------> 0  |
|                          |  |
|     1            1       |  |
0 ---------> 0 ----------> 0  |
             |                |
      1      |      1         |
1 ---------> 0 -------------> 1

নোট করুন যে ফ্লো গ্রাফটিতে এক্স নোড রয়েছে, এবং x বিটের সংখ্যা being এবং সর্বাধিক সংখ্যার সংখ্যা (২ * x) -২।

সুতরাং 32 বিট পূর্ণসংখ্যার জন্য এটি O (32) স্পেস বা O (1) স্পেস গ্রহণ করবে।

এখন যদি আমি 1,2,4 থেকে শুরু করে প্রতিটি সংখ্যার জন্য ক্ষমতাটি সরিয়ে ফেলি তবে আমার একটি অবশিষ্ট গ্রাফ থাকবে।

0 ----------> 1 ---------> 1

শেষ পর্যন্ত আমি নীচের মতো একটি লুপ চালাব,

 result = []
 for x in range(1,n):
     exists_path_in_residual_graph(x)
     result.append(x)

এখন ফলাফলটি resultএমন সংখ্যায় রয়েছে যা পাশাপাশি অনুপস্থিত (মিথ্যা ধনাত্মক)। কিন্তু ট <= (ফলাফল আকারের) <= ঢ যখন আছে kঅনুপস্থিত উপাদান।

ফলাফলটি হারিয়ে যাওয়া বা না পারার জন্য আমি শেষবারের মতো প্রদত্ত তালিকায় যাব।

সুতরাং সময় জটিলতা ও (এন) হবে।

অবশেষে, এটা নোড গ্রহণ করে মিথ্যা ইতিবাচক (এবং স্থান প্রয়োজনীয়) সংখ্যা কমাতে করা সম্ভব 00, 01, 11, 10পরিবর্তে শুধু 0এবং 1


আমি আপনার গ্রাফ ডায়াগ্রাম বুঝতে পারি না। নোড, প্রান্ত এবং সংখ্যাগুলি কী উপস্থাপন করে? কিছু কিনারা কেন নির্দেশিত এবং অন্যগুলি নয়?
দিন

আসলে আমি আপনার উত্তরটি আদৌ বুঝতে পারি না, আপনি আরও কিছু পরিষ্কার করতে পারেন?
ডেইন

1

ও (কে) বলতে কী বোঝায় সে সম্পর্কে আপনার সম্ভবত ব্যাখ্যা দরকার।

নির্বিচারে কে এর জন্য একটি তুচ্ছ সমাধান: আপনার সংখ্যার প্রতিটি সেটের জন্য 2 ^ v এর যোগফল সংগ্রহ করুন। শেষে, 1 থেকে N পর্যন্ত লুপ করুন bit যদি 2 ^ i সহ বিটওয়াইড অ্যান্ডেড সমষ্টি হয় তবে আমি অনুপস্থিত। (অথবা সংখ্যাগতভাবে, যোগফলের তল যদি 2 ^ i দিয়ে ভাগ করা হয় তবে সমান Or বা sum modulo 2^(i+1)) < 2^i))

সহজ, তাই না? ও (এন) সময়, ও (1) সঞ্চয়স্থান এবং এটি নির্বিচারে কে সমর্থন করে।

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

সুতরাং আপনি বুদ্ধিমান হতে পারেন এবং বর্গের যোগফল এবং কিউবসের যোগফলটি গণনা করতে পারেন ... v ^ কে যোগফল পর্যন্ত, এবং ফলাফলটি বের করার জন্য অভিনব গণিতটি করতে পারেন। তবে এগুলিও বড় সংখ্যা, যা প্রশ্নটি জাগায়: আমরা অপারেশনের কোন বিমূর্ত মডেলটির কথা বলছি? ও (1) স্পেসে কতটা ফিট করে এবং আপনার যে পরিমাণ আকারের প্রয়োজন তার সংখ্যার যোগ করতে কতক্ষণ সময় লাগে?


চমৎকার উত্তর! একটি ছোট্ট জিনিস: "যদি যোগফলগুলি 2 ^ i শূন্য হয় তবে আমি অনুপস্থিত" ভুল is তবে এটি কী উদ্দেশ্য তা স্পষ্ট। আমি মনে করি "যদি যোগফল 2 ^ (i + 1) 2 ^ i এর চেয়ে কম হয় তবে আমি অনুপস্থিত" সঠিক হবে। (অবশ্যই, বেশিরভাগ প্রোগ্রামিং ভাষায় আমরা মডিউল গণনার পরিবর্তে বিট শিফটিং ব্যবহার করতাম Sometimes কখনও কখনও প্রোগ্রামিং ল্যাঙ্গুয়েজগুলি সাধারণ গাণিতিক স্বরলিপিটির তুলনায় কিছুটা বেশি প্রকাশিত হয়: :-))
জেএসাহাওয়ানওয়াল্ড গোফন্ডমোনিকা

1
ধন্যবাদ, তুমি পুরোপুরি ঠিক! স্থির, যদিও আমি অলস এবং গাণিতিক স্বরলিপি থেকে বিপথগামী ... ওহ, এবং আমি এটিও গোলযোগ পেয়েছি। আবার ঠিক করা হচ্ছে ...
স্ফিংক করুন

1

এখানে এমন একটি সমাধান রয়েছে যা জটিল গণিতের উপর নির্ভর করে না কারণ এসডিসিভিভিসি / দিমিত্রিস অ্যান্ড্রেউ'র উত্তরগুলি করে, ক্যাফে এবং কর্নেল প্যানিকের মতো ইনপুট অ্যারে পরিবর্তন করে না এবং ক্রিস লিকার, জেরেমিপ এবং বিশাল আকারের বিটসেট ব্যবহার করে না Chris আরও অনেকেই করেছিলেন। মূলত, আমি স্যালোর্জেন / গিলাদ দেউচের ধারণাগুলি কিউ 2-এর সাথে শুরু করেছি, এটিকে সাধারণ ঘটনা Qk তে সাধারণীকরণ করেছি এবং আলগোরিদম কাজ করে তা প্রমাণ করার জন্য জাভাতে প্রয়োগ করেছি।

বুদ্ধিটা

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

এখন আমরা এস এবং কি দেখুন । যদি প্রশ্ন = 1 , এর অর্থ হ'ল আমি তখন নিখোঁজ সংখ্যাগুলির মধ্যে একটি অন্তর্ভুক্ত করেছি এবং এই সংখ্যাটি স্পষ্টভাবে এস । আমরা সমাপ্ত হিসাবে চিহ্নিত করেছি (এটি প্রোগ্রামে "দ্ব্যর্থহীন" বলা হয়) এবং আরও বিবেচনা থেকে এড়িয়ে যান। অন্যদিকে, প্রশ্ন> 1 , আমরা আইটিতে থাকা নিখোঁজ সংখ্যাগুলির গড় A = S / Q গণনা করতে পারি । হিসাবে সমস্ত নম্বর স্বতন্ত্র, এই ধরনের সংখ্যার অন্তত একটি কঠোরভাবে কম একটি এবং অন্তত একটি থেকে যথাযথভাবে বেশী হয় একটি । এখন আমরা বিভক্ত আমি যে একজনদুটি ছোট বিরতিতে প্রতিটি অন্তত একটি অনুপস্থিত সংখ্যা রয়েছে। মনে রাখবেন যে এটি পূর্ণসংখ্যার ক্ষেত্রে আমরা কোন অন্তরকে A নির্ধারণ করি তা বিবেচ্য নয়।

আমরা প্রতিটি ব্যবধানের জন্য আলাদা আলাদা (তবে একই পাসে) এবং এর পরে Q = 1 এবং Q> 1 এর সাথে বিভক্ত বিরতিগুলির পরে পৃথক অ্যারে পাসটি গণনা করে এস এবং কিউ তৈরি করি । কোনও নতুন "অস্পষ্ট" অন্তর না হওয়া পর্যন্ত আমরা এই প্রক্রিয়াটি চালিয়ে যাচ্ছি, অর্থাত্ আমাদের বিভাজনের কিছু নেই কারণ প্রতিটি বিরতিতে ঠিক একটি অনুপস্থিত নম্বর থাকে (এবং আমরা এই সংখ্যাটি সবসময় জানি কারণ আমরা এসকে জানি । আমরা সম্ভাব্য সংখ্যাগুলি (যেমন প্রশ্নের মধ্যে [1..N] ) সমন্বিত একমাত্র "সম্পূর্ণ ব্যাপ্তি" অন্তর থেকে শুরু করি ।

সময় এবং স্থান জটিলতার বিশ্লেষণ

পাস মোট সংখ্যা P আমরা যতক্ষণ না প্রক্রিয়া স্টপ করতে হবে অনুপস্থিত সংখ্যা গণনা চেয়ে কখনো বেশী । অসমতা p <= কে কঠোরভাবে প্রমাণ করা যেতে পারে। অন্যদিকে, এছাড়াও আছে একটি গবেষণামূলক সর্বোচ্চ সীমা পি <লগ 2 n + 3 যে বৃহৎ মান জন্য দরকারী । আমাদের যে ইনপুট অ্যারে এর অন্তর্গত তা নির্ধারণের জন্য প্রতিটি সংখ্যার জন্য বাইনারি অনুসন্ধান করতে হবে। এটি সময় জটিলতায় লগ কে গুণক যোগ করে ।

মোট, সময়ের জটিলতা হ'ল ও (এন ᛫ মিনিট (কে, লগ এন) ᛫ লগ কে) । নোট করুন যে লার্জ কে এর জন্য এটি এসডিসিভিভিসি / ডিমিট্রিস অ্যান্ড্রেউর পদ্ধতির চেয়ে উল্লেখযোগ্যভাবে ভাল যা ও (এন ᛫ কে)

এর কাজের জন্য, অ্যালগরিদমের বেশিরভাগ কে-এর অন্তরগুলিতে স্টোর করার জন্য ও (কে) অতিরিক্ত স্থান প্রয়োজন , এটি "বিটসেট" সমাধানগুলিতে ও (এন) এর চেয়ে উল্লেখযোগ্যভাবে ভাল ।

জাভা বাস্তবায়ন

এখানে একটি জাভা ক্লাস যা উপরের অ্যালগরিদম প্রয়োগ করে। এটি সর্বদা অনুপস্থিত সংখ্যার সাজানো অ্যারে প্রদান করে। তদ্ব্যতীত, এটি কে অনুপস্থিত সংখ্যা গণনা করার দরকার নেই কারণ এটি এটি প্রথম পাসে গণনা করে। সংখ্যার পুরো পরিসরটি minNumberএবং maxNumberপরামিতি দ্বারা দেওয়া হয় (উদাহরণস্বরূপ প্রশ্নের প্রথম উদাহরণের জন্য 1 এবং 100)।

public class MissingNumbers {
    private static class Interval {
        boolean ambiguous = true;
        final int begin;
        int quantity;
        long sum;

        Interval(int begin, int end) { // begin inclusive, end exclusive
            this.begin = begin;
            quantity = end - begin;
            sum = quantity * ((long)end - 1 + begin) / 2;
        }

        void exclude(int x) {
            quantity--;
            sum -= x;
        }
    }

    public static int[] find(int minNumber, int maxNumber, NumberBag inputBag) {
        Interval full = new Interval(minNumber, ++maxNumber);
        for (inputBag.startOver(); inputBag.hasNext();)
            full.exclude(inputBag.next());
        int missingCount = full.quantity;
        if (missingCount == 0)
            return new int[0];
        Interval[] intervals = new Interval[missingCount];
        intervals[0] = full;
        int[] dividers = new int[missingCount];
        dividers[0] = minNumber;
        int intervalCount = 1;
        while (true) {
            int oldCount = intervalCount;
            for (int i = 0; i < oldCount; i++) {
                Interval itv = intervals[i];
                if (itv.ambiguous)
                    if (itv.quantity == 1) // number inside itv uniquely identified
                        itv.ambiguous = false;
                    else
                        intervalCount++; // itv will be split into two intervals
            }
            if (oldCount == intervalCount)
                break;
            int newIndex = intervalCount - 1;
            int end = maxNumber;
            for (int oldIndex = oldCount - 1; oldIndex >= 0; oldIndex--) {
                // newIndex always >= oldIndex
                Interval itv = intervals[oldIndex];
                int begin = itv.begin;
                if (itv.ambiguous) {
                    // split interval itv
                    // use floorDiv instead of / because input numbers can be negative
                    int mean = (int)Math.floorDiv(itv.sum, itv.quantity) + 1;
                    intervals[newIndex--] = new Interval(mean, end);
                    intervals[newIndex--] = new Interval(begin, mean);
                } else
                    intervals[newIndex--] = itv;
                end = begin;
            }
            for (int i = 0; i < intervalCount; i++)
                dividers[i] = intervals[i].begin;
            for (inputBag.startOver(); inputBag.hasNext();) {
                int x = inputBag.next();
                // find the interval to which x belongs
                int i = java.util.Arrays.binarySearch(dividers, 0, intervalCount, x);
                if (i < 0)
                    i = -i - 2;
                Interval itv = intervals[i];
                if (itv.ambiguous)
                    itv.exclude(x);
            }
        }
        assert intervalCount == missingCount;
        for (int i = 0; i < intervalCount; i++)
            dividers[i] = (int)intervals[i].sum;
        return dividers;
    }
}

ন্যায্যতার জন্য, এই শ্রেণিটি NumberBagবস্তুর আকারে ইনপুট গ্রহণ করে। NumberBagঅ্যারে পরিবর্তন এবং এলোমেলো অ্যাক্সেসের অনুমতি দেয় না এবং ক্রমান্বয়ে ট্র্যাভার্সিংয়ের জন্য অ্যারে কতবার অনুরোধ করা হয়েছিল তাও গণনা করে। এটি বড় অ্যারে পরীক্ষার জন্যও বেশি উপযুক্ত Iterable<Integer>কারণ এটি আদিম intমানের বক্সিং এড়ানো এবং int[]সুবিধাজনক পরীক্ষার প্রস্তুতির জন্য বৃহতের একটি অংশ মোড়ানোর অনুমতি দেয় । ফরচারে দুটি ফোল্ডারে পরিবর্তন করে, স্বাক্ষর NumberBagদ্বারা int[]বা স্বাক্ষর দ্বারা Iterable<Integer>টাইপ করে প্রতিস্থাপন করা শক্ত findনয়।

import java.util.*;

public abstract class NumberBag {
    private int passCount;

    public void startOver() {
        passCount++;
    }

    public final int getPassCount() {
        return passCount;
    }

    public abstract boolean hasNext();

    public abstract int next();

    // A lightweight version of Iterable<Integer> to avoid boxing of int
    public static NumberBag fromArray(int[] base, int fromIndex, int toIndex) {
        return new NumberBag() {
            int index = toIndex;

            public void startOver() {
                super.startOver();
                index = fromIndex;
            }

            public boolean hasNext() {
                return index < toIndex;
            }

            public int next() {
                if (index >= toIndex)
                    throw new NoSuchElementException();
                return base[index++];
            }
        };
    }

    public static NumberBag fromArray(int[] base) {
        return fromArray(base, 0, base.length);
    }

    public static NumberBag fromIterable(Iterable<Integer> base) {
        return new NumberBag() {
            Iterator<Integer> it;

            public void startOver() {
                super.startOver();
                it = base.iterator();
            }

            public boolean hasNext() {
                return it.hasNext();
            }

            public int next() {
                return it.next();
            }
        };
    }
}

টেস্ট

এই ক্লাসগুলির ব্যবহার দেখানোর জন্য সাধারণ উদাহরণ নীচে দেওয়া হয়েছে।

import java.util.*;

public class SimpleTest {
    public static void main(String[] args) {
        int[] input = { 7, 1, 4, 9, 6, 2 };
        NumberBag bag = NumberBag.fromArray(input);
        int[] output = MissingNumbers.find(1, 10, bag);
        System.out.format("Input: %s%nMissing numbers: %s%nPass count: %d%n",
                Arrays.toString(input), Arrays.toString(output), bag.getPassCount());

        List<Integer> inputList = new ArrayList<>();
        for (int i = 0; i < 10; i++)
            inputList.add(2 * i);
        Collections.shuffle(inputList);
        bag = NumberBag.fromIterable(inputList);
        output = MissingNumbers.find(0, 19, bag);
        System.out.format("%nInput: %s%nMissing numbers: %s%nPass count: %d%n",
                inputList, Arrays.toString(output), bag.getPassCount());

        // Sieve of Eratosthenes
        final int MAXN = 1_000;
        List<Integer> nonPrimes = new ArrayList<>();
        nonPrimes.add(1);
        int[] primes;
        int lastPrimeIndex = 0;
        while (true) {
            primes = MissingNumbers.find(1, MAXN, NumberBag.fromIterable(nonPrimes));
            int p = primes[lastPrimeIndex]; // guaranteed to be prime
            int q = p;
            for (int i = lastPrimeIndex++; i < primes.length; i++) {
                q = primes[i]; // not necessarily prime
                int pq = p * q;
                if (pq > MAXN)
                    break;
                nonPrimes.add(pq);
            }
            if (q == p)
                break;
        }
        System.out.format("%nSieve of Eratosthenes. %d primes up to %d found:%n",
                primes.length, MAXN);
        for (int i = 0; i < primes.length; i++)
            System.out.format(" %4d%s", primes[i], (i % 10) < 9 ? "" : "\n");
    }
}

আরও বড় অ্যারে টেস্টিং এইভাবে করা যেতে পারে:

import java.util.*;

public class BatchTest {
    private static final Random rand = new Random();
    public static int MIN_NUMBER = 1;
    private final int minNumber = MIN_NUMBER;
    private final int numberCount;
    private final int[] numbers;
    private int missingCount;
    public long finderTime;

    public BatchTest(int numberCount) {
        this.numberCount = numberCount;
        numbers = new int[numberCount];
        for (int i = 0; i < numberCount; i++)
            numbers[i] = minNumber + i;
    }

    private int passBound() {
        int mBound = missingCount > 0 ? missingCount : 1;
        int nBound = 34 - Integer.numberOfLeadingZeros(numberCount - 1); // ceil(log_2(numberCount)) + 2
        return Math.min(mBound, nBound);
    }

    private void error(String cause) {
        throw new RuntimeException("Error on '" + missingCount + " from " + numberCount + "' test, " + cause);
    }

    // returns the number of times the input array was traversed in this test
    public int makeTest(int missingCount) {
        this.missingCount = missingCount;
        // numbers array is reused when numberCount stays the same,
        // just Fisher–Yates shuffle it for each test
        for (int i = numberCount - 1; i > 0; i--) {
            int j = rand.nextInt(i + 1);
            if (i != j) {
                int t = numbers[i];
                numbers[i] = numbers[j];
                numbers[j] = t;
            }
        }
        final int bagSize = numberCount - missingCount;
        NumberBag inputBag = NumberBag.fromArray(numbers, 0, bagSize);
        finderTime -= System.nanoTime();
        int[] found = MissingNumbers.find(minNumber, minNumber + numberCount - 1, inputBag);
        finderTime += System.nanoTime();
        if (inputBag.getPassCount() > passBound())
            error("too many passes (" + inputBag.getPassCount() + " while only " + passBound() + " allowed)");
        if (found.length != missingCount)
            error("wrong result length");
        int j = bagSize; // "missing" part beginning in numbers
        Arrays.sort(numbers, bagSize, numberCount);
        for (int i = 0; i < missingCount; i++)
            if (found[i] != numbers[j++])
                error("wrong result array, " + i + "-th element differs");
        return inputBag.getPassCount();
    }

    public static void strideCheck(int numberCount, int minMissing, int maxMissing, int step, int repeats) {
        BatchTest t = new BatchTest(numberCount);
        System.out.println("╠═══════════════════════╬═════════════════╬═════════════════╣");
        for (int missingCount = minMissing; missingCount <= maxMissing; missingCount += step) {
            int minPass = Integer.MAX_VALUE;
            int passSum = 0;
            int maxPass = 0;
            t.finderTime = 0;
            for (int j = 1; j <= repeats; j++) {
                int pCount = t.makeTest(missingCount);
                if (pCount < minPass)
                    minPass = pCount;
                passSum += pCount;
                if (pCount > maxPass)
                    maxPass = pCount;
            }
            System.out.format("║ %9d  %9d  ║  %2d  %5.2f  %2d  ║  %11.3f    ║%n", missingCount, numberCount, minPass,
                    (double)passSum / repeats, maxPass, t.finderTime * 1e-6 / repeats);
        }
    }

    public static void main(String[] args) {
        System.out.println("╔═══════════════════════╦═════════════════╦═════════════════╗");
        System.out.println("║      Number count     ║      Passes     ║  Average time   ║");
        System.out.println("║   missimg     total   ║  min  avg   max ║ per search (ms) ║");
        long time = System.nanoTime();
        strideCheck(100, 0, 100, 1, 20_000);
        strideCheck(100_000, 2, 99_998, 1_282, 15);
        MIN_NUMBER = -2_000_000_000;
        strideCheck(300_000_000, 1, 10, 1, 1);
        time = System.nanoTime() - time;
        System.out.println("╚═══════════════════════╩═════════════════╩═════════════════╝");
        System.out.format("%nSuccess. Total time: %.2f s.%n", time * 1e-9);
    }
}

আইডিয়নে এগুলি ব্যবহার করে দেখুন


0

আমি বিশ্বাস করি যে আমার কাছে O(k)সময় এবং O(log(k))স্থানের অ্যালগরিদম রয়েছে, যেহেতু আপনার কাছে নির্বিচারে বড় পূর্ণসংখ্যার জন্য কাজ floor(x)এবং log2(x)কার্যকারিতা রয়েছে:

আপনি একটি যুক্ত kদীর্ঘ দীর্ঘ পূর্ণসংখ্যক (সেইজন্য log8(k)স্থান) যেখানে আপনি যোগ করেন x^2, যেখানে এক্স আপনি পরবর্তী ব্যাগটি খুঁজে পাবেন: s=1^2+2^2+...এটি O(N)সময় নেয় (যা সাক্ষাত্কারকারীর জন্য কোনও সমস্যা নয়)। শেষে আপনি j=floor(log2(s))যা সন্ধান করছেন এটি সর্বাধিক নম্বর। তারপরে s=s-jএবং আপনি উপরেরটি আবার করুন:

for (i = 0 ; i < k ; i++)
{
  j = floor(log2(s));
  missing[i] = j;
  s -= j;
}

এখন, আপনার কাছে সাধারণত- 2756বিট পূর্ণসংখ্যার জন্য ফ্লোর এবং লগ 2 ফাংশন নেই তবে ডাবলসের পরিবর্তে। তাই? সহজভাবে, প্রতিটি 2 বাইট (বা 1, বা 3, বা 4) এর জন্য আপনি এই ফাংশনগুলি পছন্দসই সংখ্যাগুলি পেতে ব্যবহার করতে পারেন, তবে এটি O(N)সময়ের জটিলতায় একটি কারণকে যুক্ত করে


0

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

সুতরাং, যেহেতু আপনি সমস্ত নম্বর দেখতে পাচ্ছেন, কেবল যে নম্বরটি অনুপস্থিত তা সন্ধান করুন। যখন দুটি সংখ্যা নিখোঁজ থাকে তখন একই হয়। খুব সহজ আমি মনে করি। আপনি যখন ব্যাগে থাকা সংখ্যাগুলি দেখতে পান তখন কোনও সমীকরণ ব্যবহার করার কোনও অর্থ নেই।


2
আমি মনে করি তাদের সংক্ষিপ্ত করার সুবিধাটি হ'ল আপনি ইতিমধ্যে কোন সংখ্যাটি দেখেছেন তা মনে রাখার দরকার নেই (উদাঃ, কোনও অতিরিক্ত মেমরির প্রয়োজন নেই)। অন্যথায় একমাত্র বিকল্প হ'ল সমস্ত মানগুলির একটি সেট বজায় রাখা এবং তারপরে সেই অস্তিত্বটি খুঁজে পাওয়া যায় না তার জন্য পুনরায় সেটের উপর পুনরাবৃত্তি।
ড্যান তাও

3
এই প্রশ্নটি সাধারণত ও (1) স্থান জটিলতার শর্ত দিয়ে জিজ্ঞাসা করা হয়।

প্রথম এন সংখ্যাগুলির যোগফল হ'ল এন (এন + 1) / 2। এন = 100 এর জন্য, যোগফল = 100 * (101) / 2 = 5050;
tmarthal

0

আমি মনে করি এটি এটিকে সাধারণীকরণ করা যেতে পারে:

পাটিগণিত সিরিজ এবং গুণনের যোগফলের প্রাথমিক মান হিসাবে এস, এমকে চিহ্নিত করুন।

S = 1 + 2 + 3 + 4 + ... n=(n+1)*n/2
M = 1 * 2 * 3 * 4 * .... * n 

এটি গণনা করার জন্য আমার কোনও সূত্র সম্পর্কে চিন্তা করা উচিত, তবে এটি বিন্দু নয়। যাইহোক, যদি একটি নম্বর অনুপস্থিত থাকে তবে আপনি ইতিমধ্যে সমাধানটি সরবরাহ করেছেন। যাইহোক, যদি দুটি সংখ্যা অনুপস্থিত থাকে তবে এস 1 এবং এম 1 দ্বারা নতুন যোগফল এবং মোট এককটি বোঝাতে দিন যা নীচের মত হবে:

S1 = S - (a + b)....................(1)

Where a and b are the missing numbers.

M1 = M - (a * b)....................(2)

আপনি যেহেতু এস 1, এম 1, এম এবং এস জানেন তাই উপরের সমীকরণটি একটি এবং বি, অনুপস্থিত সংখ্যাগুলি সন্ধান করার জন্য সমাধানযোগ্য।

এখন তিনটি নম্বর অনুপস্থিত:

S2 = S - ( a + b + c)....................(1)

Where a and b are the missing numbers.

M2 = M - (a * b * c)....................(2)

এখন আপনার অজানা 3 টি যখন আপনার কেবল দুটি সমীকরণ রয়েছে যা থেকে আপনি সমাধান করতে পারেন।


গুণটি যদিও বেশ বড় হয় .. এছাড়াও, আপনি কীভাবে 2 টিরও বেশি অনুপস্থিত সংখ্যায় সাধারণীকরণ করবেন?
টমাস আহলে

আমি এই সূত্রগুলি খুব সাধারণ ক্রমের সাথে এন = 3 এবং অনুপস্থিত সংখ্যা = {1, 2 with দিয়ে চেষ্টা করেছি} আমি কাজ করি নি, কারণ আমি বিশ্বাস করি ত্রুটিটি সূত্রগুলিতে রয়েছে (২) যা পড়তে হবে M1 = M / (a * b)( সেই উত্তরটি দেখুন )। তারপরে এটি কাজ করে।
dma_k

0

আমি এটি দক্ষ বা না জানি না তবে আমি এই সমাধানটি প্রস্তাব করতে চাই।

  1. 100 টি উপাদানগুলির গণনা জোর
  2. 98 টি উপাদানের গণনা জোর (2 উপাদানগুলি সরানোর পরে)
  3. এখন (1 এর ফলাফল) XOR (2 এর ফলাফল) আপনাকে দুটি অনুপস্থিত সংখ্যার xor দেয় i..ea XOR b যদি a এবং b অনুপস্থিত উপাদান হয়
    4. আপনার স্বাভাবিক পদ্ধতির সাথে নিখোঁজ সংখ্যাগুলির যোগফলটি পান যোগফল সূত্রটি পৃথক করে এবং আসুন ডিফটি ডিটি বলে দেয়।

সম্ভাব্য জোড়া (পি, কিউ) পাওয়ার জন্য একটি লুপ চালান যা উভয়ই [1, 100] এর মধ্যে থাকে এবং d এর যোগফল হয়।

যখন একটি জুড়ি পাওয়া যায় তখন পরীক্ষা করুন (3 এর ফলাফল) এক্সওআর পি = কিউ এবং যদি হ্যাঁ আমরা সম্পন্ন করেছি।

আমি ভুল হলে আমাকে সংশোধন করুন এবং এটি সঠিক হলে সময়ের জটিলতার বিষয়েও মন্তব্য করুন


2
আমি মনে করি না যোগফল এবং xor স্বতন্ত্রভাবে দুটি সংখ্যা সংজ্ঞায়িত করে। সমস্ত সম্ভাব্য কে-টিপলস পেতে যে পরিমাণে ডি যোগ হয় তার জন্য একটি লুপ চালানো সময় নেবে O (C (n, k-1)) = O (n <sup> কে-1 </sup>), যা কে> 2 এর জন্য, খারাপ.
তেপীম্মে

0

আমরা কি করতে পারি চতুর্থাংশ 1 এবং Q2 এর মধ্যে হে (লগ ঢ) অধিকাংশ সময়।

ধরুন আমাদের সংখ্যার memory chipঅ্যারে nরয়েছে test tubes। এবং xটেস্ট টিউবে একটি নম্বর x milliliterরাসায়নিক তরল দ্বারা প্রতিনিধিত্ব করা হয় ।

ধরুন আমাদের প্রসেসরটি একটি laser light। যখন আমরা লেজারটি আলোকিত করি তখন এটি সমস্ত টিউবগুলিকে দৈর্ঘ্যের দিকে লম্বভাবে ঘুরিয়ে দেয়। যতবারই এটি রাসায়নিক তরল দিয়ে যায়, ততক্ষণ শক্তি কমে যায় 1। এবং নির্দিষ্ট মিলিলিটার চিহ্নে আলো পাস করা একটি অপারেশন O(1)

এখন যদি আমরা টেস্ট-টিউবটির মাঝখানে আমাদের লেজারটি আলোকিত করি এবং আলোকিততার আউটপুট পাই

  • পূর্ব-গণনা করা মানের সমান (যখন কোনও সংখ্যা অনুপস্থিত ছিল তখন গণনা করা হয়), তবে অনুপস্থিত সংখ্যাগুলি এর চেয়ে বেশি হয় n/2
  • আমাদের আউটপুট যদি ছোট হয়, তবে কমপক্ষে একটি অনুপস্থিত সংখ্যা যা তার চেয়ে কম n/2। আমরা যদি ঔজ্জ্বল্য হ্রাস করে পরীক্ষা করতে পারবেন 1বা 2। যদি 1এরপরে এটি হ্রাস পায় তবে একটি অনুপস্থিত সংখ্যা এর চেয়ে ছোট n/2এবং অন্যটি এর চেয়ে বড় n/2। যদি এটির দ্বারা হ্রাস হয় 2তবে উভয় সংখ্যা এর চেয়ে কম হবে n/2

আমরা আমাদের সমস্যার ডোমেনটিকে সংকুচিত করে উপরের প্রক্রিয়াটিকে পুনরাবৃত্তি করতে পারি। প্রতিটি পদক্ষেপে, আমরা ডোমেনটি অর্ধেক দ্বারা ছোট করি। এবং অবশেষে আমরা আমাদের ফলাফল পেতে পারেন।

সমান্তরাল অ্যালগরিদমগুলি যা উল্লেখযোগ্য (কারণ তারা আকর্ষণীয়),

  • কিছু সমান্তরাল অ্যালগরিদম অনুসারে বাছাই করা, উদাহরণস্বরূপ, সমান্তরাল মার্জ O(log^3 n)সময়ে করা যেতে পারে । এবং তারপরে অনুপস্থিত নম্বরটি O(log n)সময়ে বাইনারি অনুসন্ধানের মাধ্যমে পাওয়া যাবে ।
  • তাত্ত্বিকভাবে, যদি আমাদের nপ্রসেসর থাকে তবে প্রতিটি প্রক্রিয়া ইনপুটগুলির মধ্যে একটি চেক করতে পারে এবং কিছু পতাকা সেট করতে পারে যা নম্বরটি চিহ্নিত করে (সুবিধাজনকভাবে একটি অ্যারেতে)। এবং পরবর্তী পদক্ষেপে প্রতিটি প্রক্রিয়া প্রতিটি পতাকা চেক করতে এবং অবশেষে পতাকাঙ্কিত নয় এমন নম্বর আউটপুট করতে পারে। পুরো প্রক্রিয়াতে O(1)সময় লাগবে । এটির অতিরিক্ত O(n)স্থান / স্মৃতিশক্তি প্রয়োজন।

দ্রষ্টব্য, উপরে প্রদত্ত দুটি সমান্তরাল অ্যালগরিদমের মন্তব্যে উল্লিখিত অতিরিক্ত স্থানের প্রয়োজন হতে পারে


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

1
আপনার বাছাইয়ের পদ্ধতি হিসাবে, এটি নির্ভর করবে এমন অতিরিক্ত পরিমাণের জায়গা Nএবং O(N)সময়ের চেয়ে বেশি (এর উপর নির্ভরতার দিক দিয়ে N), যা আমরা এর চেয়ে আরও ভাল করতে চাইছি take
স্যারগ্যু

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