
Look at an ordinary day and you will see problems everywhere: finding the highest marks in a class list, deciding whether a number is even, or working out the shortest way home. A computational problem is simply a problem of this kind that can be handed to a computer — a challenge that can be solved through a computational process, using an algorithm, which is a set of step-by-step instructions a computer can actually carry out.
Every computational problem has the same three parts, and naming them before you start is half the work. The input is the data given at the beginning. The process is the set of steps or rules — the algorithm itself — applied to that input. The output is the result produced after processing. Take the class-marks problem: input, the list of marks; process, compare the marks one by one and keep the biggest seen so far; output, the highest mark. If any one of these three is unclear, the computer cannot be told what to do, and that is usually where a student gets stuck — not in the coding, but in the thinking before it.
📌 Book note: the chapter opens with this input–process–output idea because everything that follows — sorting, searching, even the hardest problems in the chapter — is just this same pattern dressed up in different clothes.
روزمرہ زندگی میں ہمیں ہر طرف مسائل نظر آتے ہیں: کلاس کی فہرست میں سب سے زیادہ نمبر تلاش کرنا، یہ جانچنا کہ کوئی عدد جفت ہے یا طاق، یا گھر کا سب سے چھوٹا راستہ نکالنا۔ کمپیوٹیشنل مسئلہ ایسا مسئلہ ہے جسے کمپیوٹر کے حوالے کیا جا سکے، یعنی ایک ایسا چیلنج جو کمپیوٹیشنل عمل سے حل ہو اور جس کے لیے الگورتھم ہو، یعنی قدم بہ قدم ایسی ہدایات جن پر کمپیوٹر عمل کر سکے۔
ہر کمپیوٹیشنل مسئلے کے تین حصے ہوتے ہیں، اور شروع کرنے سے پہلے ان کے نام لینا آدھا کام ہے۔ ان پٹ وہ ڈیٹا ہے جو شروع میں دیا جاتا ہے۔ پراسیس وہ اقدامات یا قواعد ہیں، یعنی خود الگورتھم، جو ان پٹ پر لاگو ہوتے ہیں۔ آؤٹ پٹ وہ نتیجہ ہے جو پراسیس کے بعد حاصل ہوتا ہے۔ کلاس کے نمبروں کی مثال لیں: ان پٹ نمبروں کی فہرست ہے، پراسیس یہ ہے کہ نمبروں کا ایک ایک کر کے موازنہ کریں اور اب تک کا سب سے بڑا نمبر محفوظ رکھیں، اور آؤٹ پٹ سب سے زیادہ نمبر ہے۔ اگر ان تین میں سے کوئی ایک بھی واضح نہ ہو تو کمپیوٹر کو بتایا ہی نہیں جا سکتا کہ کیا کرنا ہے، اور طالب علم عموماً یہیں اٹک جاتا ہے — کوڈنگ میں نہیں، بلکہ اس سے پہلے کی سوچ میں۔
To solve a problem computationally, the book says, you first have to characterise it: identify its inputs, its desired outputs, and the process that turns one into the other. Once that is clear, problems fall into four handy families. A decision problem answers with a simple “yes” or “no” — is this number even? A search problem asks you to find an item or a solution that meets certain criteria — find the student named Ahmed in this list. An optimization problem asks for the best solution by some measure — the shortest route, the cheapest ticket. And a counting problem asks how many ways certain conditions can be met — in how many ways can these books be arranged?
Problems can also be sorted by how clearly they are defined. A well-defined problem has a clear goal, clear inputs, a clear process and a clear output. The book's own example is deciding whether a number is even: goal, decide even or odd; input, one integer; process, check whether it is divisible by 2; output, “even” or “odd”. An ill-defined problem lacks clear definitions and has vague or ambiguous goals. The book's example is a project aimed at “how to reduce poverty in Pakistan” — a huge, vague goal with no single input, no single process and no single answer to check. The lesson is practical: if your problem reads like the second kind, your first job is not to code, but to sharpen it until it reads like the first.
⚠️ Book slip (numbering): the book prints “3.1.1” twice — once for “Characterizing” and again for “Classifying”. The second one is really subsection 3.1.1.1; nothing in the content changes, only the number is repeated.
کسی مسئلے کو کمپیوٹیشنل طور پر حل کرنے کے لیے پہلے اس کی خصوصیات سمجھنی ہوتی ہیں: اس کے ان پٹ، مطلوبہ آؤٹ پٹ، اور وہ عمل جو ایک کو دوسرے میں بدلتا ہے۔ جب یہ واضح ہو جائے تو مسائل چار خاندانوں میں بٹ جاتے ہیں۔ فیصلہ کن مسئلہ (Decision) کا جواب صرف ”ہاں“ یا ”نہیں“ ہوتا ہے، جیسے کیا یہ عدد جفت ہے؟ تلاش کا مسئلہ (Search) میں کسی ایسی چیز یا حل کو ڈھونڈنا ہوتا ہے جو شرائط پر پورا اترے، جیسے فہرست میں احمد نامی طالب علم تلاش کرنا۔ بہترین حل کا مسئلہ (Optimization) میں کسی پیمانے کے لحاظ سے بہترین حل چاہیے ہوتا ہے، جیسے سب سے چھوٹا راستہ یا سب سے سستا ٹکٹ۔ اور گنتی کا مسئلہ (Counting) میں یہ پوچھا جاتا ہے کہ شرائط کتنے طریقوں سے پوری ہو سکتی ہیں۔
مسائل کو اس لحاظ سے بھی بانٹا جا سکتا ہے کہ وہ کتنے واضح طور پر بیان ہوئے ہیں۔ واضح مسئلہ (Well-defined) میں مقصد، ان پٹ، پراسیس اور آؤٹ پٹ سب واضح ہوتے ہیں۔ کتاب کی مثال جفت عدد کی جانچ ہے: مقصد جفت یا طاق کا فیصلہ، ان پٹ ایک عدد، پراسیس 2 پر تقسیم کی جانچ، آؤٹ پٹ ”جفت“ یا ”طاق“۔ غیر واضح مسئلہ (Ill-defined) میں واضح تعریفیں نہیں ہوتیں اور مقاصد مبہم ہوتے ہیں۔ کتاب کی مثال ”پاکستان میں غربت کیسے کم کی جائے“ جیسا منصوبہ ہے — ایک بہت بڑا اور مبہم مقصد جس کا نہ کوئی واحد ان پٹ ہے، نہ واحد پراسیس، نہ جانچنے کے قابل واحد جواب۔ عملی سبق یہ ہے کہ اگر آپ کا مسئلہ دوسری قسم کا لگے تو پہلا کام کوڈ لکھنا نہیں، بلکہ اسے اتنا واضح کرنا ہے کہ وہ پہلی قسم جیسا لگنے لگے۔
An algorithm is a step-by-step procedure for solving a problem — the book compares it to a recipe, which gives steps for cooking a dish. Understanding algorithms matters because they supply the logic behind software: they let us solve complex problems, improve performance, and be sure of accuracy in all kinds of applications. A recipe that says “cook until done” without saying how long or at what heat is a bad recipe; an algorithm with a missing or vague step is a bad algorithm in exactly the same way. As a bit of colour, the book notes that Google's search engine uses a complex algorithm called PageRank, which weighs the number of links to a page and the quality of those links to rank search results.
One very general way of solving a problem is the Generate-and-Test method: generate a possible solution, test whether it meets the required conditions, and keep going until a satisfactory solution is found or every possibility has been exhausted. It is especially useful when the problem space is small enough to try everything, when there is no clear strategy for finding a solution directly, or when heuristics — rough rules of thumb — can cut down the number of candidates so the search stays feasible. Watch it work on a tiny problem: find a number between 10 and 20 that is divisible by both 3 and 4. Generate 10 — test: divisible by 3? No. Generate 11 — no. Generate 12 — divisible by 3 (12 ÷ 3 = 4) and by 4 (12 ÷ 4 = 3), so it passes, and we stop. The book also notes that this method is common in artificial-intelligence applications such as game playing, where trying out possibilities until one works is often the only sensible approach.
الگورتھم کسی مسئلے کو حل کرنے کا قدم بہ قدم طریقہ کار ہے — کتاب اسے کھانا پکانے کی ترکیب سے تشبیہ دیتی ہے جو کسی ڈش کے لیے اقدامات بتاتی ہے۔ الگورتھم کو سمجھنا اس لیے ضروری ہے کہ یہ سافٹ ویئر کے پیچھے کی منطق فراہم کرتے ہیں: ان سے پیچیدہ مسائل حل ہوتے ہیں، کارکردگی بہتر ہوتی ہے اور مختلف اطلاقات میں درستگی یقینی بنتی ہے۔ جس ترکیب میں یہ نہ لکھا ہو کہ کتنی دیر یا کتنی آنچ پر پکانا ہے وہ بری ترکیب ہے؛ جس الگورتھم میں کوئی قدم غائب یا مبہم ہو وہ بالکل اسی طرح برا الگورتھم ہے۔ کتاب ایک دلچسپ بات بتاتی ہے کہ گوگل کا سرچ انجن PageRank نامی ایک پیچیدہ الگورتھم استعمال کرتا ہے جو کسی صفحے کی طرف آنے والے لنکس کی تعداد اور ان کے معیار کو دیکھ کر سرچ نتائج کی درجہ بندی کرتا ہے۔
مسئلہ حل کرنے کا ایک بہت عام طریقہ Generate-and-Test ہے: ایک ممکنہ حل بناؤ، جانچو کہ وہ شرائط پر پورا اترتا ہے یا نہیں، اور اس وقت تک جاری رکھو جب تک کوئی تسلی بخش حل نہ مل جائے یا تمام امکانات ختم نہ ہو جائیں۔ یہ طریقہ خاص طور پر اس وقت مفید ہے جب مسئلے کا دائرہ اتنا چھوٹا ہو کہ سب کچھ آزمایا جا سکے، جب براہ راست حل تلاش کرنے کی کوئی واضح حکمت عملی نہ ہو، یا جب ہیورسٹکس، یعنی اندازے کے قواعد، امیدواروں کی تعداد کم کر کے تلاش کو ممکن بنا دیں۔ ایک چھوٹی مثال دیکھیں: 10 اور 20 کے درمیان ایسا عدد تلاش کریں جو 3 اور 4 دونوں سے تقسیم ہو۔ 10 بناؤ — جانچ: 3 سے تقسیم؟ نہیں۔ 11 بناؤ — نہیں۔ 12 بناؤ — 3 سے تقسیم (12 ÷ 3 = 4) اور 4 سے بھی (12 ÷ 4 = 3)، پس یہ کامیاب ہے اور ہم رک جاتے ہیں۔ کتاب یہ بھی بتاتی ہے کہ یہ طریقہ مصنوعی ذہانت کے اطلاقات، جیسے کھیل کھیلنے، میں عام ہے جہاں امکانات آزمانا ہی اکثر واحد معقول راستہ ہوتا ہے۔
Before asking how fast a problem can be solved, ask whether it can be solved at all. A problem is solvable if an algorithm can solve it within a finite amount of time: it has clearly defined inputs and outputs, and there is a step-by-step procedure that reaches the solution. The book's classic example is the greatest common divisor (GCD) of two integers, solved by the Euclidean algorithm. Work it out for 48 and 18, step by step: 48 = 2 × 18 + 12, so the remainder is 12. Then 18 = 1 × 12 + 6, remainder 6. Then 12 = 2 × 6 + 0, remainder 0 — and the moment the remainder hits 0, the last non-zero remainder, 6, is the GCD. Finite steps, definite answer, no guessing: that is what solvable looks like.
An unsolvable problem is one for which no algorithm can provide a solution in all cases — there is no general procedure that guarantees an answer for every possible input. The famous example is the Halting Problem: deciding whether a given program will eventually halt (finish running) or run forever. Alan Turing proved that no general algorithm can solve it for all program–input pairs. The book states this result without the proof, so here is the idea in simple words (an elaboration, not a book passage): suppose a checker program H could always tell us “this program halts” or “this program loops forever”. Now build a mischievous program that asks H about itself and then does the opposite — if H says “it halts”, it loops forever; if H says “it loops”, it stops at once. Whatever H says about this program is wrong, so H cannot exist. The book's practical tip is worth remembering: before throwing time and resources at a hard problem, first check that it is solvable at all.
یہ پوچھنے سے پہلے کہ کوئی مسئلہ کتنی تیزی سے حل ہو سکتا ہے، یہ پوچھیں کہ آیا وہ حل ہو بھی سکتا ہے یا نہیں۔ کوئی مسئلہ حل پذیر ہوتا ہے جب کوئی الگورتھم اسے محدود وقت میں حل کر سکے: اس کے ان پٹ اور آؤٹ پٹ واضح طور پر بیان شدہ ہوں اور اس تک پہنچنے کا قدم بہ قدم طریقہ موجود ہو۔ کتاب کی کلاسیکی مثال دو اعداد کا عاد اعظم (GCD) ہے جو اقلیدسی الگورتھم سے حل ہوتا ہے۔ 48 اور 18 کے لیے قدم بہ قدم دیکھیں: 48 = 2 × 18 + 12، پس باقی 12 ہے۔ پھر 18 = 1 × 12 + 6، باقی 6۔ پھر 12 = 2 × 6 + 0، باقی 0 — اور جس لمحے باقی صفر ہو جائے، آخری غیر صفر باقی، یعنی 6، ہی GCD ہے۔ محدود اقدامات، یقینی جواب، کوئی اندازہ نہیں: حل پذیر مسئلہ ایسا ہی ہوتا ہے۔
ناقابل حل مسئلہ وہ ہے جس کے لیے کوئی الگورتھم تمام صورتوں میں حل فراہم نہیں کر سکتا — ایسا کوئی عمومی طریقہ نہیں جو ہر ممکنہ ان پٹ کے لیے جواب کی ضمانت دے۔ مشہور مثال ہالٹنگ پرابلم ہے: یہ فیصلہ کرنا کہ کوئی پروگرام آخرکار رکے گا (چلنا ختم کرے گا) یا ہمیشہ چلتا رہے گا۔ ایلن ٹیورنگ نے ثابت کیا کہ کوئی عمومی الگورتھم تمام پروگرام–ان پٹ جوڑوں کے لیے اسے حل نہیں کر سکتا۔ کتاب یہ نتیجہ بغیر ثبوت کے دیتی ہے، اس لیے اس کا خیال سادہ الفاظ میں یہ ہے (یہ وضاحت کتاب کا اقتباس نہیں): فرض کریں ایک جانچنے والا پروگرام H ہمیشہ بتا سکتا ہے کہ ”یہ پروگرام رکتا ہے“ یا ”یہ ہمیشہ چلتا ہے“۔ اب ایک شریر پروگرام بنائیں جو H سے اپنے بارے میں پوچھے اور پھر اس کے الٹ کرے — اگر H کہے ”یہ رکتا ہے“ تو وہ ہمیشہ چلے، اور اگر H کہے ”یہ چلتا ہے“ تو وہ فوراً رک جائے۔ H اس پروگرام کے بارے میں جو بھی کہے گا غلط ہوگا، پس H موجود ہی نہیں ہو سکتا۔ کتاب کی عملی نصیحت یاد رکھنے کے قابل ہے: کسی مشکل مسئلے پر وقت اور وسائل لگانے سے پہلے یہ جانچ لیں کہ وہ حل پذیر بھی ہے یا نہیں۔
Once a problem is known to be solvable, the next question is how efficiently it can be solved — and here problems split into tractable and intractable ones, depending on the resources (time and space) they need. A problem is tractable if it can be solved in polynomial time, written as P: the time grows at a manageable rate, like a polynomial function, as the input grows. The book calls these “efficiently solvable”, and gives sorting a list with Merge Sort or Quick Sort, at O(n log n), as the example — double the list and the work grows, but only by a sane amount.
Intractable problems need super-polynomial time, often growing exponentially with the input, so they become impractical for large inputs even though they are solvable in principle. The book's example is the Travelling Salesman Problem (TSP): find the shortest route that visits a set of cities and returns to the start. The number of possible routes grows factorially with the number of cities. Count it yourself: with 5 cities there are (5 − 1)! ÷ 2 = 12 different tours; with 10 cities, 181,440; with 20 cities, about 60,000,000,000,000,000 tours. No computer can try them all for a big city list, which is why TSP is called intractable — and, as the book adds, NP-hard. The practical point is not to give up, but to change the goal: for such problems we usually accept a very good route found quickly instead of demanding the perfect one.
جب یہ معلوم ہو جائے کہ کوئی مسئلہ حل پذیر ہے تو اگلا سوال یہ ہے کہ وہ کتنی مؤثر طریقے سے حل ہو سکتا ہے — اور یہاں مسائل قابل عمل (Tractable) اور ناقابل عمل (Intractable) میں بٹ جاتے ہیں، اس بنیاد پر کہ انہیں کتنے وسائل (وقت اور جگہ) درکار ہیں۔ کوئی مسئلہ قابل عمل ہوتا ہے جب وہ کثیر رقمی وقت (Polynomial time) میں حل ہو سکے، جسے P لکھا جاتا ہے: ان پٹ بڑھنے پر وقت قابل برداشت شرح سے بڑھتا ہے، جیسے کثیر رقمی فنکشن۔ کتاب انہیں ”مؤثر طریقے سے حل پذیر“ کہتی ہے، اور مثال دیتی ہے کہ Merge Sort یا Quick Sort سے فہرست ترتیب دینا، جو O(n log n) ہے — فہرست دگنی کریں تو کام بڑھتا ہے، مگر صرف معقول حد تک۔
ناقابل عمل مسائل کو فوق کثیر رقمی وقت درکار ہوتا ہے، جو اکثر ان پٹ کے ساتھ کفایتی (exponential) انداز میں بڑھتا ہے، اس لیے بڑے ان پٹ کے لیے وہ ناقابل عمل ہو جاتے ہیں، حالانکہ اصولی طور پر حل پذیر ہوتے ہیں۔ کتاب کی مثال ٹریولنگ سیلزمین پرابلم (TSP) ہے: ایسا سب سے چھوٹا راستہ تلاش کرنا جو شہروں کے ایک مجموعے سے گزرے اور واپس شروعات پر آئے۔ ممکنہ راستوں کی تعداد شہروں کی تعداد کے ساتھ عاملی (factorial) انداز میں بڑھتی ہے۔ خود گنیں: 5 شہروں کے لیے (5 − 1)! ÷ 2 = 12 مختلف دورے؛ 10 شہروں کے لیے 181,440؛ 20 شہروں کے لیے تقریباً 60,000,000,000,000,000 دورے۔ کوئی کمپیوٹر بڑی فہرست کے لیے ان سب کو آزما نہیں سکتا، اسی لیے TSP کو ناقابل عمل — اور جیسا کہ کتاب مزید کہتی ہے، NP-hard — کہا جاتا ہے۔ عملی نکتہ ہار ماننا نہیں، بلکہ مقصد بدلنا ہے: ایسے مسائل کے لیے ہم عموماً کامل راستے کا مطالبہ کرنے کے بجائے جلدی ملنے والا بہت اچھا راستہ قبول کر لیتے ہیں۔
Complexity classes are boxes into which problems are sorted by how hard they are to solve and to check. Class P holds problems a computer can solve efficiently, quickly even as the problem grows. The book's example is sorting: take [4, 1, 3, 2, 5] and arrange it in ascending order to get [1, 2, 3, 4, 5]. Going from 5 numbers to 10 numbers takes more time, but it stays within a reasonable limit — that manageable growth is the whole idea of P.
Class NP is subtler, and students often misread it: NP does not mean “non-polynomial”. It means that if a solution is given to you, a computer can check it quickly, even though finding it might be difficult and time-consuming. The book's example is Sudoku: filling a 9 × 9 grid so every row, column and 3 × 3 box contains the digits 1 to 9 exactly once can take a long search, but once someone hands you a completed grid, checking each row, column and box is quick, mechanical work. NP-hard problems are at least as difficult as the hardest problems in NP, and no efficient algorithm is known for them — the Travelling Salesman Problem from the last section is the book's example. NP-complete problems are the special subset that sit inside NP and are as hard as the hardest NP problems, so solving one of them efficiently would let you solve all NP problems efficiently. The book's classic example is the Knapsack Problem: a bag with a maximum weight capacity, and items each with a weight and a value — choose the most valuable combination without exceeding the capacity. Try it: capacity 10 kg, items A (5 kg, value 10), B (4 kg, value 9), C (6 kg, value 12), D (3 kg, value 5). Check the promising pairs: A + B = 9 kg, value 19; B + C = 10 kg, value 21; A + C = 11 kg, over capacity; C + D = 9 kg, value 17. The winner is B + C at value 21. With four items you can check by hand; with forty, the checking explodes — and that is exactly the NP-complete feeling. Finally, the book notes that whether P equals NP is one of the most important unsolved problems in computer science, with big implications for cryptography and algorithm design.
پیچیدگی کی جماعتیں وہ خانے ہیں جن میں مسائل کو اس بنیاد پر رکھا جاتا ہے کہ انہیں حل کرنا اور جانچنا کتنا مشکل ہے۔ جماعت P میں وہ مسائل ہیں جنہیں کمپیوٹر مؤثر طریقے سے حل کر سکتا ہے، مسئلہ بڑھنے پر بھی جلدی۔ کتاب کی مثال ترتیب دینا ہے: [4, 1, 3, 2, 5] لیں اور صعودی ترتیب میں [1, 2, 3, 4, 5] بنائیں۔ 5 اعداد سے 10 اعداد تک جانے میں زیادہ وقت لگتا ہے، مگر وہ معقول حد میں رہتا ہے — یہ قابل برداشت بڑھوتری ہی P کا پورا خیال ہے۔
جماعت NP زیادہ باریک ہے، اور طلبہ اکثر اسے غلط سمجھتے ہیں: NP کا مطلب ”غیر کثیر رقمی“ نہیں ہے۔ اس کا مطلب یہ ہے کہ اگر آپ کو کوئی حل دے دیا جائے تو کمپیوٹر اسے جلدی جانچ سکتا ہے، اگرچہ اسے تلاش کرنا مشکل اور وقت طلب ہو سکتا ہے۔ کتاب کی مثال سوڈوکو ہے: 9 × 9 گرڈ اس طرح بھرنا کہ ہر قطار، کالم اور 3 × 3 خانے میں 1 سے 9 تک کے ہندسے صرف ایک بار آئیں، ایک طویل تلاش ہو سکتی ہے، مگر جب کوئی آپ کو مکمل گرڈ دے دے تو ہر قطار، کالم اور خانے کی جانچ تیز اور میکانیکی کام ہے۔ NP-hard مسائل کم از کم NP کے مشکل ترین مسائل جتنے مشکل ہوتے ہیں، اور ان کے لیے کوئی مؤثر الگورتھم معلوم نہیں — پچھلے حصے کا ٹریولنگ سیلزمین پرابلم کتاب کی مثال ہے۔ NP-complete مسائل وہ خاص ذیلی مجموعہ ہیں جو NP کے اندر بھی ہیں اور NP کے مشکل ترین مسائل جتنے مشکل ہیں، اس لیے ان میں سے کسی ایک کو مؤثر طریقے سے حل کرنا آپ کو تمام NP مسائل مؤثر طریقے سے حل کرنے کے قابل بنا دے گا۔ کتاب کی کلاسیکی مثال نیپ سیک پرابلم ہے: ایک تھیلا جس کی وزن کی زیادہ سے زیادہ گنجائش ہے، اور اشیاء جن میں سے ہر ایک کا وزن اور قیمت ہے — گنجائش سے تجاوز کیے بغیر سب سے قیمتی مجموعہ چنیں۔ آزمائیں: گنجائش 10 کلو، اشیاء A (5 کلو، قیمت 10)، B (4 کلو، قیمت 9)، C (6 کلو، قیمت 12)، D (3 کلو، قیمت 5)۔ امید افزا جوڑے جانچیں: A + B = 9 کلو، قیمت 19؛ B + C = 10 کلو، قیمت 21؛ A + C = 11 کلو، گنجائش سے زیادہ؛ C + D = 9 کلو، قیمت 17۔ فاتح B + C ہے جس کی قیمت 21 ہے۔ چار اشیاء کے ساتھ آپ ہاتھ سے جانچ سکتے ہیں؛ چالیس کے ساتھ جانچ پھٹ پڑتی ہے — اور یہی NP-complete کا احساس ہے۔ آخر میں کتاب بتاتی ہے کہ آیا P برابر NP ہے، یہ کمپیوٹر سائنس کے اہم ترین حل طلب مسائل میں سے ایک ہے، جس کے خفیہ نگاری اور الگورتھم کی تیاری پر بڑے اثرات ہیں۔
Algorithm analysis means working out the computational complexity of an algorithm — its time and space complexity — so you can predict its performance and pick the best algorithm for a particular task. Time complexity measures how the running time grows as the size of the input data grows. Sorting five numbers is quick whatever you do; sorting five million is a different story, and time complexity is what lets you predict that story before you run anything.
Big O notation is the mathematical way of describing time complexity. It gives an upper bound on the time an algorithm will take as the input size grows — roughly, how bad things can get — and it lets you compare algorithms at a glance. Four cases carry the whole chapter. O(1), constant time: the runtime stays the same whatever the input size — for example, reading the first element of a list. O(n), linear time: the runtime grows in step with the input size. The book's example: n students, each with a unique ID, and you search through the list for one student — the time depends on how many students there are. O(n²), quadratic time: the runtime grows with the square of the input size. The book's example is comparing every student with every other student to pick the best team. ⚠️ Book slip, corrected here: the book says the number of comparisons “can be approximated as n(n − 1)”; the exact number of pairs is n(n − 1) ÷ 2. The order is still quadratic, so the Big O conclusion is unchanged, but the count itself is off by a factor of 2. O(log n), logarithmic time: the runtime grows very slowly — the book's guessing game: think of a number between 1 and 100, and I may only ask yes/no questions. Guess 50 — too high. Guess 25 — too low. Guess 37 — correct, in just 3 questions, because every question halves the range. That halving is exactly what binary search does, and it is why O(log n) beats O(n) so dramatically on large inputs.
الگورتھم کا تجزیہ کا مطلب کسی الگورتھم کی کمپیوٹیشنل پیچیدگی معلوم کرنا ہے — اس کی وقتی اور جگہ کی پیچیدگی — تاکہ آپ اس کی کارکردگی کا اندازہ لگا سکیں اور کسی خاص کام کے لیے بہترین الگورتھم چن سکیں۔ وقتی پیچیدگی یہ ناپتی ہے کہ ان پٹ ڈیٹا کا حجم بڑھنے پر چلنے کا وقت کیسے بڑھتا ہے۔ پانچ اعداد ترتیب دینا جو بھی کریں تیز ہے؛ پچاس لاکھ ترتیب دینا بالکل مختلف کہانی ہے، اور وقتی پیچیدگی ہی وہ چیز ہے جو آپ کو کچھ چلانے سے پہلے اس کہانی کا اندازہ دیتی ہے۔
Big O نوٹیشن وقتی پیچیدگی بیان کرنے کا ریاضیاتی طریقہ ہے۔ یہ اس وقت کی بالائی حد دیتا ہے جو الگورتھم ان پٹ کا حجم بڑھنے پر لے گا — تقریباً یہ کہ حالات کتنے خراب ہو سکتے ہیں — اور اس سے آپ ایک نظر میں الگورتھم کا موازنہ کر سکتے ہیں۔ چار صورتیں پورا باب سنبھالتی ہیں۔ O(1)، مستقل وقت: چلنے کا وقت ان پٹ کے حجم سے قطع نظر ایک سا رہتا ہے — مثلاً فہرست کا پہلا عنصر پڑھنا۔ O(n)، خطی وقت: چلنے کا وقت ان پٹ کے حجم کے ساتھ ساتھ بڑھتا ہے۔ کتاب کی مثال: n طلبہ، ہر ایک کی منفرد شناخت، اور آپ فہرست میں ایک طالب علم تلاش کرتے ہیں — وقت اس بات پر منحصر ہے کہ طلبہ کتنے ہیں۔ O(n²)، مربعی وقت: چلنے کا وقت ان پٹ کے حجم کے مربع کے ساتھ بڑھتا ہے۔ کتاب کی مثال بہترین ٹیم چننے کے لیے ہر طالب علم کا ہر دوسرے طالب علم سے موازنہ ہے۔ ⚠️ کتاب کی غلطی، یہاں درست کی گئی: کتاب کہتی ہے کہ موازنوں کی تعداد ”تقریباً n(n − 1)“ ہے؛ جوڑوں کی درست تعداد n(n − 1) ÷ 2 ہے۔ ترتیب اب بھی مربعی ہے، اس لیے Big O کا نتیجہ نہیں بدلتا، مگر گنتی خود 2 کے عامل سے غلط ہے۔ O(log n)، لوگارتھمی وقت: چلنے کا وقت بہت آہستہ بڑھتا ہے — کتاب کا اندازہ لگانے کا کھیل: 1 سے 100 کے درمیان کوئی عدد سوچیں، اور میں صرف ہاں/نہیں والے سوالات پوچھ سکتا ہوں۔ 50 اندازہ لگائیں — بہت زیادہ۔ 25 اندازہ لگائیں — بہت کم۔ 37 اندازہ لگائیں — صرف 3 سوالات میں درست، کیونکہ ہر سوال حد کو آدھا کر دیتا ہے۔ یہ آدھا کرنا بالکل وہی ہے جو بائنری سرچ کرتی ہے، اور اسی لیے بڑے ان پٹ پر O(log n) O(n) سے اتنا ڈرامائی طور پر بہتر ہے۔
Time is only half the bill; the other half is memory. Space complexity measures how the amount of memory or space an algorithm uses changes as the size of the input data increases. The book's example is plain: if an algorithm has to store a list of numbers, its space complexity tells you how much memory will be needed as the volume of numbers increases. A list of n numbers needs roughly n slots, so that is O(n) space — double the list, double the memory.
The trick students miss is that two algorithms can do the same job with very different memory footprints. Suppose you want the sum of n numbers. One approach copies the whole list into a second list and then adds it up — that second list alone costs O(n) extra space. The other approach walks through the original list once, keeping a single running total in one variable — that extra space stays constant no matter how long the list is, which is O(1) extra space. Same answer, same time in spirit, wildly different memory. That is why a good algorithm choice weighs both: a blazingly fast algorithm that needs far more memory than the machine has is not a good choice at all.
وقت صرف آدھا خرچ ہے؛ دوسرا آدھا میموری ہے۔ جگہ کی پیچیدگی یہ ناپتی ہے کہ کسی الگورتھم کے استعمال کردہ میموری یا جگہ کی مقدار ان پٹ ڈیٹا کا حجم بڑھنے پر کیسے بدلتی ہے۔ کتاب کی مثال سیدھی ہے: اگر کسی الگورتھم کو اعداد کی فہرست محفوظ کرنی ہو تو اس کی جگہ کی پیچیدگی بتاتی ہے کہ اعداد کا حجم بڑھنے پر کتنی میموری درکار ہوگی۔ n اعداد کی فہرست کو تقریباً n خانے چاہیے، پس یہ O(n) جگہ ہے — فہرست دگنی، میموری دگنی۔
وہ چال جو طلبہ چھوڑ جاتے ہیں یہ ہے کہ دو الگورتھم ایک ہی کام بہت مختلف میموری کے ساتھ کر سکتے ہیں۔ فرض کریں آپ n اعداد کا مجموعہ چاہتے ہیں۔ ایک طریقہ پوری فہرست کو دوسری فہرست میں نقل کر کے پھر جمع کرتا ہے — صرف وہ دوسری فہرست O(n) اضافی جگہ لیتی ہے۔ دوسرا طریقہ اصل فہرست سے ایک بار گزرتا ہے اور ایک ہی متغیر میں چلتا ہوا مجموعہ رکھتا ہے — وہ اضافی جگہ فہرست کی لمبائی سے قطع نظر مستقل رہتی ہے، جو O(1) اضافی جگہ ہے۔ ایک ہی جواب، بنیادی طور پر ایک ہی وقت، مگر میموری میں بہت بڑا فرق۔ اسی لیے الگورتھم کا اچھا انتخاب دونوں کو تولتا ہے: ایک بہت تیز الگورتھم جسے مشین کی میموری سے کہیں زیادہ میموری چاہیے ہو، بالکل اچھا انتخاب نہیں ہے۔
Divide and Conquer is a design technique that works by breaking a large problem into smaller, more manageable parts, solving each smaller part independently, and then combining their solutions to solve the original problem. It is particularly effective for problems that can be divided into similar smaller problems, because then the same method can be applied again and again until the pieces are trivially small. Think of it as the opposite of panicking at a huge task: instead of staring at the whole mountain, you split it into hills, climb each hill, and put the results together.
The book's illustration is Merge Sort on [14, 7, 3, 12]. Divide: split the list into [14, 7] and [3, 12]. Divide again: [14, 7] becomes [14] and [7]; [3, 12] becomes [3] and [12]. Conquer: sort each tiny piece — [14] and [7] sort into [7, 14], and [3] and [12] sort into [3, 12]. Combine: merge the two sorted halves by repeatedly taking the smaller front element — 3, then 7, then 12, then 14 — giving [3, 7, 12, 14]. The book also notes, in a “Do You Know?” box, that Big O notation helps computer scientists understand an algorithm's efficiency in the worst case, so they can predict how well it will perform as the input data increases — and Merge Sort's steady O(n log n) is exactly why it is trusted for large data.
تقسیم کرو اور فتح کرو (Divide and Conquer) ایک ڈیزائن تکنیک ہے جو بڑے مسئلے کو چھوٹے، زیادہ قابل انتظام حصوں میں توڑ کر کام کرتی ہے، ہر چھوٹے حصے کو آزادانہ طور پر حل کرتی ہے، اور پھر ان کے حلوں کو ملا کر اصل مسئلہ حل کرتی ہے۔ یہ ان مسائل کے لیے خاص طور پر مؤثر ہے جنہیں ملتے جلتے چھوٹے مسائل میں تقسیم کیا جا سکے، کیونکہ تب وہی طریقہ بار بار لگایا جا سکتا ہے جب تک ٹکڑے نہایت چھوٹے نہ ہو جائیں۔ اسے بڑے کام کے سامنے گھبرانے کے الٹ سمجھیں: پورے پہاڑ کو گھورنے کے بجائے آپ اسے ٹیلوں میں بانٹتے ہیں، ہر ٹیلہ چڑھتے ہیں، اور نتائج کو اکٹھا کر دیتے ہیں۔
کتاب کی مثال [14, 7, 3, 12] پر Merge Sort ہے۔ تقسیم: فہرست کو [14, 7] اور [3, 12] میں بانٹیں۔ دوبارہ تقسیم: [14, 7] سے [14] اور [7] بنتے ہیں؛ [3, 12] سے [3] اور [12]۔ فتح: ہر چھوٹے ٹکڑے کو ترتیب دیں — [14] اور [7] سے [7, 14] بنتا ہے، اور [3] اور [12] سے [3, 12]۔ ملانا: دونوں ترتیب شدہ آدھوں کو اس طرح ملائیں کہ بار بار چھوٹا سامنے والا عنصر لیں — 3، پھر 7، پھر 12، پھر 14 — جس سے [3, 7, 12, 14] ملتا ہے۔ کتاب ایک ”کیا آپ جانتے ہیں؟“ خانے میں یہ بھی بتاتی ہے کہ Big O نوٹیشن کمپیوٹر سائنس دانوں کو بدترین صورت میں الگورتھم کی کارکردگی سمجھنے میں مدد دیتی ہے، تاکہ وہ اندازہ لگا سکیں کہ ان پٹ ڈیٹا بڑھنے پر وہ کیسی کارکردگی دکھائے گا — اور Merge Sort کا مستقل O(n log n) ہی وہ وجہ ہے جس سے بڑے ڈیٹا کے لیے اس پر بھروسہ کیا جاتا ہے۔
A greedy algorithm works by making a sequence of choices, each of which is locally optimal — the best-looking move right now — in the hope that these choices will lead to a globally optimal solution, the best overall answer. It is often used when a problem has optimal substructure, meaning that the optimal solution to the whole problem can be built from optimal solutions to its subproblems. The book's classic example is the Coin Change problem: you have coins of different denominations and you want to make a specific amount with the fewest coins possible. The greedy rule is to choose the largest denomination coin that does not exceed the remaining amount, subtract it, and repeat until the amount is reached.
Work it with coins of 50, 20, 10, 5 and 1, making 87. Largest coin not exceeding 87 is 50; remaining 37. Largest not exceeding 37 is 20; remaining 17. Largest not exceeding 17 is 10; remaining 7. Largest not exceeding 7 is 5; remaining 2. Then 1, remaining 1; then 1, remaining 0. Answer: 50 + 20 + 10 + 5 + 1 + 1 = 87, in 6 coins. But — and the book's “Tidbits” box insists on this — greedy algorithms are often faster and easier to implement than other techniques, yet they do not always guarantee the optimal solution for every problem, so always analyse whether a greedy approach is appropriate. Here is a counter-example (derived, not from the book): with coins of 4, 3 and 1, making 6, greedy picks 4 first, then 1, then 1 — three coins — while 3 + 3 uses only two. The greedy choice looked best at the time and still lost. That is the whole danger and the whole charm of being greedy: it never looks back.
لالچی الگورتھم (Greedy) فیصلوں کے ایک سلسلے سے کام کرتا ہے، جن میں سے ہر ایک مقامی طور پر بہترین ہوتا ہے — یعنی اس وقت سب سے اچھی لگنے والی چال — اس امید پر کہ یہ فیصلے عالمی طور پر بہترین حل تک لے جائیں گے، یعنی مجموعی طور پر بہترین جواب۔ یہ اکثر اس وقت استعمال ہوتا ہے جب کسی مسئلے میں بہترین ذیلی ساخت (Optimal Substructure) ہو، یعنی پورے مسئلے کا بہترین حل اس کے ذیلی مسائل کے بہترین حلوں سے بنایا جا سکے۔ کتاب کی کلاسیکی مثال سکوں کی تبدیلی (Coin Change) ہے: آپ کے پاس مختلف مالیت کے سکے ہیں اور آپ کم سے کم سکوں سے ایک مخصوص رقم بنانا چاہتے ہیں۔ لالچی قاعدہ یہ ہے کہ سب سے بڑا ایسا سکہ چنیں جو باقی رقم سے زیادہ نہ ہو، اسے گھٹائیں، اور رقم مکمل ہونے تک دہرائیں۔
50، 20، 10، 5 اور 1 کے سکوں سے 87 بنائیں۔ 87 سے زیادہ نہ ہونے والا سب سے بڑا سکہ 50 ہے؛ باقی 37۔ 37 سے زیادہ نہ ہونے والا سب سے بڑا سکہ 20 ہے؛ باقی 17۔ 17 سے زیادہ نہ ہونے والا سب سے بڑا سکہ 10 ہے؛ باقی 7۔ 7 سے زیادہ نہ ہونے والا سب سے بڑا سکہ 5 ہے؛ باقی 2۔ پھر 1، باقی 1؛ پھر 1، باقی 0۔ جواب: 50 + 20 + 10 + 5 + 1 + 1 = 87، 6 سکوں میں۔ لیکن — اور کتاب کا ”ٹڈبٹس“ خانہ اس پر زور دیتا ہے — لالچی الگورتھم اکثر دوسری تکنیکوں سے تیز اور نافذ کرنے میں آسان ہوتے ہیں، پھر بھی وہ ہر مسئلے کے لیے بہترین حل کی ضمانت نہیں دیتے، اس لیے ہمیشہ تجزیہ کریں کہ لالچی طریقہ مناسب ہے یا نہیں۔ ایک مخالف مثال (اخذ شدہ، کتاب سے نہیں): 4، 3 اور 1 کے سکوں سے 6 بنانے میں لالچی پہلے 4 چنتا ہے، پھر 1، پھر 1 — تین سکے — جبکہ 3 + 3 صرف دو سکے استعمال کرتا ہے۔ لالچی فیصلہ اس وقت سب سے اچھا لگا تھا اور پھر بھی ہار گیا۔ یہی لالچی ہونے کا پورا خطرہ اور پوری کشش ہے: یہ کبھی پیچھے مڑ کر نہیں دیکھتا۔
Dynamic Programming (DP) is an optimization technique that solves problems by breaking them down into simpler subproblems and storing the results of those subproblems, so the same work is never done twice. It is particularly useful for problems with overlapping subproblems — the same small problem cropping up again and again — and optimal substructure, where the best answer to the whole problem is built from the best answers to its parts. If Divide and Conquer is about splitting a problem up, DP is about splitting it up and remembering.
The book's example is the Fibonacci sequence, where each number is the sum of the two before it: F(0) = 0, F(1) = 1, and F(n) = F(n − 1) + F(n − 2). Work it with DP, filling a table once from the bottom up: F(0) = 0, F(1) = 1, F(2) = 1 + 0 = 1, F(3) = 1 + 1 = 2, F(4) = 2 + 1 = 3, F(5) = 3 + 2 = 5, F(6) = 5 + 3 = 8. Every value is computed exactly once and then simply read back whenever it is needed again. Without that table, a naive recursive program recomputes F(3), F(2) and F(1) over and over, like a student who solves the same sum fresh every time instead of writing the answer in the margin. Storing results is a small idea with an enormous payoff, and it is the entire difference between an exponential program and a linear one for this problem.
ڈائنامک پروگرامنگ (DP) ایک بہترین بنانے کی تکنیک ہے جو مسائل کو آسان ذیلی مسائل میں توڑ کر اور ان ذیلی مسائل کے نتائج محفوظ کر کے حل کرتی ہے، تاکہ وہی کام دوبارہ کبھی نہ کرنا پڑے۔ یہ ان مسائل کے لیے خاص طور پر مفید ہے جن میں اوورلیپنگ ذیلی مسائل ہوں — یعنی وہی چھوٹا مسئلہ بار بار سامنے آئے — اور بہترین ذیلی ساخت ہو، جہاں پورے مسئلے کا بہترین جواب اس کے حصوں کے بہترین جوابوں سے بنتا ہو۔ اگر Divide and Conquer مسئلے کو بانٹنے کے بارے میں ہے تو DP اسے بانٹنے اور یاد رکھنے کے بارے میں ہے۔
کتاب کی مثال فبوناچی سلسلہ ہے، جہاں ہر عدد اس سے پہلے کے دو اعداد کا مجموعہ ہوتا ہے: F(0) = 0، F(1) = 1، اور F(n) = F(n − 1) + F(n − 2)۔ DP سے اسے نیچے سے اوپر جدول بھر کر حل کریں: F(0) = 0، F(1) = 1، F(2) = 1 + 0 = 1، F(3) = 1 + 1 = 2، F(4) = 2 + 1 = 3، F(5) = 3 + 2 = 5، F(6) = 5 + 3 = 8۔ ہر قیمت صرف ایک بار نکالی جاتی ہے اور پھر جب بھی دوبارہ ضرورت ہو اسے بس پڑھ لیا جاتا ہے۔ اس جدول کے بغیر ایک سادہ تکراری پروگرام F(3)، F(2) اور F(1) کو بار بار نکالتا ہے، جیسے وہ طالب علم جو ہر بار وہی جمع حاشیے میں جواب لکھنے کے بجائے نئے سرے سے حل کرتا ہے۔ نتائج محفوظ کرنا ایک چھوٹا خیال ہے جس کا فائدہ بہت بڑا ہے، اور یہی اس مسئلے کے لیے کفایتی پروگرام اور خطی پروگرام کے درمیان پورا فرق ہے۔
Backtracking is a method for problems where you build a solution step by step, and if you find that a particular path does not lead to a solution, you simply go back and try a different path. The book's own comparison is trying out different routes on a map and turning back when you find you are going the wrong way. It is often used for problems where you need to look at all possible options, like puzzles or problems that involve different combinations.
Picture a small maze with one junction. You enter, reach the junction, and try the left passage first. It ends in a dead end — a wall, no exit. A backtracking solver does not panic and does not start the whole maze again: it steps back to the last junction, marks the left passage as tried and failed, and takes the right passage instead, which leads to the exit. That is the whole method in one image: try, fail, step back, try differently, and never waste time re-trying a path you already know is dead. It is the same spirit you will meet again in Depth-First Search, which explores one branch to its end before backtracking to the next — and it is also how a human solves a Sudoku square by pencil: try a digit, and if it breaks a row, erase it and try the next one.
بیک ٹریکنگ ان مسائل کا طریقہ ہے جہاں آپ قدم بہ قدم حل بناتے ہیں، اور اگر آپ کو معلوم ہو کہ کوئی خاص راستہ حل تک نہیں لے جاتا تو آپ بس واپس جا کر کوئی مختلف راستہ آزماتے ہیں۔ کتاب کی اپنی تشبیہ نقشے پر مختلف راستے آزمانے کی ہے اور غلط سمت میں جانے پر واپس مڑنے کی ہے۔ یہ اکثر ان مسائل کے لیے استعمال ہوتا ہے جہاں آپ کو تمام ممکنہ اختیارات دیکھنے ہوتے ہیں، جیسے پہیلیاں یا مختلف مجموعوں والے مسائل۔
ایک چھوٹی بھول بھلیاں تصور کریں جس میں ایک موڑ ہے۔ آپ داخل ہوتے ہیں، موڑ تک پہنچتے ہیں، اور پہلے بایاں راستہ آزماتے ہیں۔ وہ بند گلی میں ختم ہوتا ہے — ایک دیوار، کوئی راستہ نہیں۔ بیک ٹریکنگ والا حل گھبراتا نہیں اور پوری بھول بھلیاں دوبارہ شروع نہیں کرتا: وہ آخری موڑ تک واپس جاتا ہے، بائیں راستے کو آزمایا ہوا اور ناکام نشان زد کرتا ہے، اور اس کے بجائے دایاں راستہ لیتا ہے جو باہر نکلنے تک لے جاتا ہے۔ یہی ایک تصویر میں پورا طریقہ ہے: آزماؤ، ناکام ہو، واپس جاؤ، مختلف طریقے سے آزماؤ، اور کبھی اس راستے کو دوبارہ آزمانے میں وقت ضائع نہ کرو جس کے بارے میں آپ پہلے ہی جانتے ہیں کہ وہ بند ہے۔ یہی روح آپ کو Depth-First Search میں دوبارہ ملے گی، جو اگلی شاخ پر جانے سے پہلے ایک شاخ کو اس کے آخر تک کھوجتی ہے — اور اسی طرح انسان پنسل سے سوڈوکو کا خانہ حل کرتا ہے: ایک ہندسہ آزماؤ، اور اگر وہ قطار خراب کر دے تو اسے مٹا کر اگلا آزماؤ۔
Bubble Sort is one of the simplest sorting algorithms. It works by repeatedly stepping through the list, comparing adjacent elements, and swapping them if they are in the wrong order. This process is repeated until the list is sorted. The book's process, in order: start from the beginning of the list; compare each pair of adjacent elements; swap them if they are in the wrong order; continue the process until no more swaps are needed. The name comes from the picture: big values “bubble” up to the end of the list, one pass at a time, like bubbles rising in water.
Now trace the book's example completely — [5, 3, 8, 4, 2] — and do not skip a pass, because the exam loves exactly this. Pass 1: compare 5 and 3, swap → [3, 5, 8, 4, 2]; compare 5 and 8, no swap; compare 8 and 4, swap → [3, 5, 4, 8, 2]; compare 8 and 2, swap → [3, 5, 4, 2, 8]. The 8 has bubbled to the end. Pass 2: 3 and 5, no swap; 5 and 4, swap → [3, 4, 5, 2, 8]; 5 and 2, swap → [3, 4, 2, 5, 8]; 5 and 8, no swap. Pass 3: 3 and 4, no swap; 4 and 2, swap → [3, 2, 4, 5, 8]; the rest need no swaps. Pass 4: 3 and 2, swap → [2, 3, 4, 5, 8]; nothing else moves. Sorted: [2, 3, 4, 5, 8], matching the book's answer. The time complexity is O(n²), making it inefficient for large datasets, but it is easy to understand and implement, which is why it survives in teaching — and why the book's tip is to reach for Quick Sort or Merge Sort once the data gets large.
ببل سارٹ آسان ترین ترتیب دینے والے الگورتھم میں سے ایک ہے۔ یہ فہرست سے بار بار گزر کر، ساتھ والے عناصر کا موازنہ کر کے، اور غلط ترتیب میں ہونے پر انہیں بدل کر کام کرتا ہے۔ یہ عمل اس وقت تک دہرایا جاتا ہے جب تک فہرست ترتیب نہ پا جائے۔ کتاب کا عمل ترتیب وار یہ ہے: فہرست کے آغاز سے شروع کریں؛ ساتھ والے عناصر کے ہر جوڑے کا موازنہ کریں؛ غلط ترتیب میں ہونے پر انہیں بدلیں؛ یہ عمل اس وقت تک جاری رکھیں جب تک مزید تبدیلیوں کی ضرورت نہ رہے۔ اس کا نام اس تصویر سے آیا ہے: بڑی قدریں ایک ایک گزر میں فہرست کے آخر تک ”بلبلوں“ کی طرح اوپر آتی ہیں، جیسے پانی میں بلبلے اوپر اٹھتے ہیں۔
اب کتاب کی مثال کو مکمل طور پر ٹریس کریں — [5, 3, 8, 4, 2] — اور کوئی گزر نہ چھوڑیں، کیونکہ امتحان کو بالکل یہی پسند ہے۔ پہلا گزر: 5 اور 3 کا موازنہ، تبدیلی → [3, 5, 8, 4, 2]؛ 5 اور 8، کوئی تبدیلی نہیں؛ 8 اور 4، تبدیلی → [3, 5, 4, 8, 2]؛ 8 اور 2، تبدیلی → [3, 5, 4, 2, 8]۔ 8 آخر تک بلبلے کی طرح پہنچ گیا۔ دوسرا گزر: 3 اور 5، کوئی تبدیلی نہیں؛ 5 اور 4، تبدیلی → [3, 4, 5, 2, 8]؛ 5 اور 2، تبدیلی → [3, 4, 2, 5, 8]؛ 5 اور 8، کوئی تبدیلی نہیں۔ تیسرا گزر: 3 اور 4، کوئی تبدیلی نہیں؛ 4 اور 2، تبدیلی → [3, 2, 4, 5, 8]؛ باقی کو تبدیلی کی ضرورت نہیں۔ چوتھا گزر: 3 اور 2، تبدیلی → [2, 3, 4, 5, 8]؛ باقی کچھ نہیں ہلتا۔ ترتیب شدہ: [2, 3, 4, 5, 8]، جو کتاب کے جواب سے میل کھاتا ہے۔ وقتی پیچیدگی O(n²) ہے، جو اسے بڑے ڈیٹا سیٹس کے لیے غیر مؤثر بناتی ہے، مگر یہ سمجھنے اور نافذ کرنے میں آسان ہے، اسی لیے یہ تدریس میں باقی ہے — اور اسی لیے کتاب کی نصیحت یہ ہے کہ ڈیٹا بڑا ہونے پر Quick Sort یا Merge Sort کی طرف جائیں۔
Selection Sort is another simple sorting algorithm, and its idea is almost the opposite of Bubble Sort's neighbour-swapping. It works by selecting the smallest (or largest, depending on the desired order) element from the unsorted part of the list and swapping it with the first element of the unsorted part. The book's process: find the minimum element in the unsorted part; swap it with the first unsorted element; move the boundary between the sorted and unsorted sections by one element; repeat for the remaining elements. The sorted part grows from the left, one element at a time, like filling seats in a row from the front.
Trace the book's example — [29, 10, 14, 37, 13] — all the way. Step 1: the unsorted part is the whole list; its minimum is 10, so swap 10 with the first element, 29 → [10, 29, 14, 37, 13]. Sorted part: [10]. Step 2: the unsorted part is [29, 14, 37, 13]; its minimum is 13, so swap 13 with 29 → [10, 13, 14, 37, 29]. Step 3: the unsorted part is [14, 37, 29]; its minimum is 14, which is already first, so no swap → [10, 13, 14, 37, 29]. Step 4: the unsorted part is [37, 29]; its minimum is 29, so swap 29 with 37 → [10, 13, 14, 29, 37]. Sorted, and it matches the book's description that the process continues until the list is fully sorted. The time complexity is O(n²), like Bubble Sort, so it is not efficient for large datasets, but it is straightforward to implement — and it has one quiet advantage students should notice: it performs far fewer swaps than Bubble Sort, at most one per step, which matters when swapping is expensive.
سلیکشن سارٹ ایک اور آسان ترتیب دینے والا الگورتھم ہے، اور اس کا خیال ببل سارٹ کی پڑوسیوں کی تبدیلی کے تقریباً الٹ ہے۔ یہ فہرست کے غیر ترتیب شدہ حصے سے سب سے چھوٹا (یا مطلوبہ ترتیب کے لحاظ سے سب سے بڑا) عنصر چن کر اور اسے غیر ترتیب شدہ حصے کے پہلے عنصر سے بدل کر کام کرتا ہے۔ کتاب کا عمل: غیر ترتیب شدہ حصے میں کم سے کم عنصر تلاش کریں؛ اسے پہلے غیر ترتیب شدہ عنصر سے بدلیں؛ ترتیب شدہ اور غیر ترتیب شدہ حصوں کے درمیان حد کو ایک عنصر آگے بڑھائیں؛ باقی عناصر کے لیے دہرائیں۔ ترتیب شدہ حصہ بائیں سے ایک ایک عنصر بڑھتا ہے، جیسے قطار میں سامنے سے نشستیں بھرنا۔
کتاب کی مثال کو آخر تک ٹریس کریں — [29, 10, 14, 37, 13]۔ پہلا قدم: غیر ترتیب شدہ حصہ پوری فہرست ہے؛ اس کا کم سے کم 10 ہے، پس 10 کو پہلے عنصر 29 سے بدلیں → [10, 29, 14, 37, 13]۔ ترتیب شدہ حصہ: [10]۔ دوسرا قدم: غیر ترتیب شدہ حصہ [29, 14, 37, 13] ہے؛ اس کا کم سے کم 13 ہے، پس 13 کو 29 سے بدلیں → [10, 13, 14, 37, 29]۔ تیسرا قدم: غیر ترتیب شدہ حصہ [14, 37, 29] ہے؛ اس کا کم سے کم 14 ہے، جو پہلے سے پہلے ہے، پس کوئی تبدیلی نہیں → [10, 13, 14, 37, 29]۔ چوتھا قدم: غیر ترتیب شدہ حصہ [37, 29] ہے؛ اس کا کم سے کم 29 ہے، پس 29 کو 37 سے بدلیں → [10, 13, 14, 29, 37]۔ ترتیب مکمل ہے، اور یہ کتاب کی وضاحت سے میل کھاتا ہے کہ عمل اس وقت تک جاری رہتا ہے جب تک فہرست مکمل طور پر ترتیب نہ پا جائے۔ وقتی پیچیدگی O(n²) ہے، جیسے ببل سارٹ، اس لیے یہ بڑے ڈیٹا سیٹس کے لیے مؤثر نہیں، مگر نافذ کرنا سیدھا ہے — اور اس کا ایک خاموش فائدہ طلبہ کو نوٹ کرنا چاہیے: یہ ببل سارٹ سے کہیں کم تبدیلیاں کرتا ہے، ہر قدم میں زیادہ سے زیادہ ایک، جو اس وقت اہم ہے جب تبدیلی مہنگی ہو۔
Search algorithms are designed to find specific elements within a dataset, and they matter for information retrieval, database queries and decision-making. Linear search is the straightforward one: check each item one by one until you find what you are looking for. The book's steps: start at the beginning and look at the first item; compare the item you are looking for with the current item; if they do not match, move to the next item; repeat until you find the item or reach the end of the list. Its own example uses cities: [Karachi, Lahore, Islamabad, Faisalabad], searching for Islamabad. Start with Karachi — not Islamabad, move on. Next is Lahore — not Islamabad, move on. Next is Islamabad — that is the city you are looking for, found on the third check. If Islamabad were not in the list, you would check all four cities one by one and then conclude it is not there. It is called linear because you check in a straight line, start to finish, and it works on unsorted data — but in the worst case it costs O(n) checks.
Binary search is the efficient alternative, but it comes with a condition: the list must be sorted. It works by repeatedly dividing the search interval in half and discarding the half the item cannot be in, until the item is found or the interval is empty. The book's steps: start with the middle element of the sorted list; if it is the target, return its position; if the target is smaller, repeat on the left half; if larger, repeat on the right half. ⚠️ Book gap, filled here: the book's first binary-search example gives the sorted list [1, 3, 5, 7, 9, 11, 13] and says binary search “will start at the middle element (7) and find the target immediately”, without naming the target. The only reading that fits is that the target is 7, the middle element itself, so it is found in one check — and that is how it is presented here. The book's fuller worked figure searches for 78 in [21, 34, 43, 57, 66, 78]: first mid is 43; 78 is larger, so look in the right half; new mid is 66; 78 is larger, so look in the right half; new mid is 78 — element found at mid. Three checks instead of six. The time complexity is O(log n), much faster than linear search for large datasets, and the book's warning is blunt: binary search is only effective on sorted lists; if your data is not sorted, sort it first, for example with Merge Sort, before applying binary search.
تلاش کے الگورتھم ڈیٹا سیٹ کے اندر مخصوص عناصر تلاش کرنے کے لیے بنائے گئے ہیں، اور یہ معلومات کی بازیافت، ڈیٹا بیس کے سوالات اور فیصلہ سازی کے لیے اہم ہیں۔ لینیئر سرچ سیدھا طریقہ ہے: ہر شے کو ایک ایک کر کے جانچیں جب تک آپ کو مطلوبہ چیز نہ مل جائے۔ کتاب کے اقدامات: آغاز سے شروع کریں اور پہلی شے کو دیکھیں؛ مطلوبہ شے کا موجودہ شے سے موازنہ کریں؛ اگر وہ نہ ملیں تو اگلی شے پر جائیں؛ اس وقت تک دہرائیں جب تک شے مل نہ جائے یا فہرست ختم نہ ہو جائے۔ کتاب کی اپنی مثال شہروں کی ہے: [Karachi, Lahore, Islamabad, Faisalabad]، Islamabad تلاش کرنا ہے۔ Karachi سے شروع کریں — Islamabad نہیں، آگے بڑھیں۔ اگلا Lahore ہے — Islamabad نہیں، آگے بڑھیں۔ اگلا Islamabad ہے — یہی وہ شہر ہے جسے آپ تلاش کر رہے ہیں، تیسری جانچ پر مل گیا۔ اگر Islamabad فہرست میں نہ ہوتا تو آپ چاروں شہروں کو ایک ایک کر کے جانچتے اور پھر نتیجہ نکالتے کہ وہ موجود نہیں۔ اسے لینیئر اس لیے کہتے ہیں کہ آپ سیدھی لکیر میں آغاز سے آخر تک جانچتے ہیں، اور یہ غیر ترتیب شدہ ڈیٹا پر بھی کام کرتا ہے — مگر بدترین صورت میں اس کی قیمت O(n) جانچیں ہیں۔
بائنری سرچ مؤثر متبادل ہے، مگر اس کی ایک شرط ہے: فہرست ترتیب شدہ ہونی چاہیے۔ یہ تلاش کے وقفے کو بار بار آدھا کر کے اور اس آدھے کو خارج کر کے کام کرتی ہے جس میں شے نہیں ہو سکتی، جب تک شے مل نہ جائے یا وقفہ خالی نہ ہو جائے۔ کتاب کے اقدامات: ترتیب شدہ فہرست کے درمیانی عنصر سے شروع کریں؛ اگر وہی ہدف ہے تو اس کی جگہ واپس کریں؛ اگر ہدف چھوٹا ہے تو بائیں آدھے پر دہرائیں؛ اگر بڑا ہے تو دائیں آدھے پر دہرائیں۔ ⚠️ کتاب کا خلا، یہاں پُر کیا گیا: کتاب کی پہلی بائنری سرچ مثال ترتیب شدہ فہرست [1, 3, 5, 7, 9, 11, 13] دیتی ہے اور کہتی ہے کہ بائنری سرچ ”درمیانی عنصر (7) سے شروع ہوگی اور ہدف فوراً مل جائے گا“، بغیر ہدف کا نام بتائے۔ واحد پڑھت جو اس سے میل کھاتی ہے وہ یہ ہے کہ ہدف خود 7 ہے، یعنی درمیانی عنصر، پس وہ ایک ہی جانچ میں مل جاتا ہے — اور یہاں اسے اسی طرح پیش کیا گیا ہے۔ کتاب کی مکمل شکل والی مثال 78 کو [21, 34, 43, 57, 66, 78] میں تلاش کرتی ہے: پہلا درمیانی 43 ہے؛ 78 بڑا ہے، پس دائیں آدھے میں دیکھیں؛ نیا درمیانی 66 ہے؛ 78 بڑا ہے، پس دائیں آدھے میں دیکھیں؛ نیا درمیانی 78 ہے — عنصر درمیان میں مل گیا۔ چھ کی بجائے تین جانچیں۔ وقتی پیچیدگی O(log n) ہے، بڑے ڈیٹا سیٹس کے لیے لینیئر سرچ سے کہیں تیز، اور کتاب کی تنبیہ دو ٹوک ہے: بائنری سرچ صرف ترتیب شدہ فہرستوں پر مؤثر ہے؛ اگر آپ کا ڈیٹا ترتیب شدہ نہیں تو بائنری سرچ لگانے سے پہلے اسے ترتیب دیں، مثلاً Merge Sort سے۔
Graph algorithms explore and analyse graphs — data structures made up of nodes (vertices) connected by edges. They are essential for network analysis, route planning and social network analysis, and the chapter closes with the two classic ways of walking through a graph. Breadth-First Search (BFS) explores all the nodes of a graph level by level, starting from a given node, often called the root, and it uses a queue to keep track of the nodes that need to be explored. The book's process: start from the root node and enqueue it; dequeue a node, process it, and enqueue all its unvisited neighbours; repeat until the queue is empty. Its example is a social network, where each node is a person and each edge is a friendship: BFS can find the shortest path between two people, for instance the degree of separation between two users. The time complexity is O(V + E), where V is the number of vertices and E the number of edges, which makes it efficient for exploring large graphs.
Depth-First Search (DFS) is the other temperament entirely: it explores as far down a branch as possible before backtracking to explore other branches, and it uses a stack to manage the nodes to be explored. The book's process: start from the root node and push it onto the stack; pop a node, process it, and push all its unvisited neighbours onto the stack; repeat until the stack is empty. The book's figure compares the two on the same graph, and the outputs are worth memorising: BFS gives 0, 1, 2, 3, 4, 5, 6, 7 — level by level, in order — while DFS gives 0, 1, 4, 5, 2, 6, 3, 7 — plunging down one branch before returning. DFS suits puzzles like mazes, the book says, where the algorithm explores one possible path to the end and, if it hits a dead end, backtracks and tries another path. Its time complexity is also O(V + E), similar to BFS, but the book adds that DFS is more memory-efficient for deep graphs, while BFS is more suited for shallow graphs. Queue for breadth, stack for depth: if you remember nothing else from this section, remember that pairing and the two output orders.
گراف الگورتھم گراف کو کھوجتے اور تجزیہ کرتے ہیں — ایسے ڈیٹا سٹرکچر جو نوڈز (ورٹیسز) سے بنتے ہیں جو کناروں (ایجز) سے جڑے ہوتے ہیں۔ یہ نیٹ ورک کے تجزیے، راستے کی منصوبہ بندی اور سوشل نیٹ ورک کے تجزیے کے لیے ضروری ہیں، اور باب گراف سے گزرنے کے دو کلاسیکی طریقوں پر ختم ہوتا ہے۔ بریڈتھ فرسٹ سرچ (BFS) گراف کے تمام نوڈز کو سطح بہ سطح کھوجتی ہے، ایک دیے گئے نوڈ سے شروع کر کے، جسے اکثر روٹ کہا جاتا ہے، اور یہ کھوجے جانے والے نوڈز کا حساب رکھنے کے لیے قطار (Queue) استعمال کرتی ہے۔ کتاب کا عمل: روٹ نوڈ سے شروع کریں اور اسے قطار میں ڈالیں؛ ایک نوڈ نکالیں، اس پر عمل کریں، اور اس کے تمام غیر دیکھے ہوئے پڑوسیوں کو قطار میں ڈالیں؛ اس وقت تک دہرائیں جب تک قطار خالی نہ ہو جائے۔ کتاب کی مثال سوشل نیٹ ورک ہے، جہاں ہر نوڈ ایک شخص ہے اور ہر کنارہ دوستی ہے: BFS دو لوگوں کے درمیان سب سے چھوٹا راستہ تلاش کر سکتی ہے، مثلاً دو صارفین کے درمیان علیحدگی کی ڈگری۔ وقتی پیچیدگی O(V + E) ہے، جہاں V ورٹیسز کی تعداد ہے اور E کناروں کی تعداد، جو اسے بڑے گراف کھوجنے کے لیے مؤثر بناتی ہے۔
ڈیپتھ فرسٹ سرچ (DFS) بالکل دوسرا مزاج ہے: یہ دوسری شاخوں کو کھوجنے کے لیے واپس جانے سے پہلے ایک شاخ میں جتنا ممکن ہو نیچے تک کھوجتی ہے، اور یہ کھوجے جانے والے نوڈز کو سنبھالنے کے لیے اسٹیک استعمال کرتی ہے۔ کتاب کا عمل: روٹ نوڈ سے شروع کریں اور اسے اسٹیک پر رکھیں؛ ایک نوڈ نکالیں، اس پر عمل کریں، اور اس کے تمام غیر دیکھے ہوئے پڑوسیوں کو اسٹیک پر رکھیں؛ اس وقت تک دہرائیں جب تک اسٹیک خالی نہ ہو جائے۔ کتاب کی شکل دونوں کا ایک ہی گراف پر موازنہ کرتی ہے، اور آؤٹ پٹ یاد رکھنے کے قابل ہیں: BFS دیتی ہے 0, 1, 2, 3, 4, 5, 6, 7 — سطح بہ سطح، ترتیب سے — جبکہ DFS دیتی ہے 0, 1, 4, 5, 2, 6, 3, 7 — واپس آنے سے پہلے ایک شاخ میں گہرائی تک جاتی ہوئی۔ DFS بھول بھلیوں جیسی پہیلیوں کے لیے موزوں ہے، کتاب کہتی ہے، جہاں الگورتھم ایک ممکنہ راستے کو آخر تک کھوجتا ہے اور اگر وہ بند گلی سے ٹکرائے تو واپس جا کر دوسرا راستہ آزماتا ہے۔ اس کی وقتی پیچیدگی بھی O(V + E) ہے، BFS جیسی، مگر کتاب مزید کہتی ہے کہ DFS گہرے گراف کے لیے میموری میں زیادہ مؤثر ہے، جبکہ BFS اتھلے گراف کے لیے زیادہ موزوں ہے۔ چوڑائی کے لیے قطار، گہرائی کے لیے اسٹیک: اگر آپ اس حصے سے اور کچھ یاد نہ رکھیں تو یہ جوڑا اور دونوں آؤٹ پٹ کی ترتیبیں یاد رکھیں۔
Below are all questions of the Unit 3 exercise from the official book (printed pages 54–55): 10 multiple-choice questions, 8 short questions and 5 long questions = 23 answer blocks. MCQ keys are cross-checked against the book's Answers section (printed page 141). The book has no separate inquisitive, review or numerical section in this unit, so none is invented here. Where an answer is derived rather than quoted from a book passage, the answer says so. ⚠️ One flawed question is flagged at MCQ 5.
1. The characteristic of a well-defined problem is:
Answer: (c) Clear goals, inputs, processes, and outputs — that is the book's own definition of a well-defined problem (section 3.1.1.2), illustrated by the even-number test. واضح مسئلے کی پہچان یہی ہے کہ اس کا مقصد، ان پٹ، پراسیس اور آؤٹ پٹ سب واضح ہوں۔
2. Complexity class representing problems solvable efficiently by a deterministic algorithm:
Answer: (d) P — class P is exactly the set of problems a computer can solve efficiently, in polynomial time. جماعت P میں وہ مسائل ہیں جنہیں کمپیوٹر مؤثر طریقے سے، کثیر رقمی وقت میں حل کر سکتا ہے۔
3. The statement that applies to unsolvable problems:
Answer: (b) They cannot be solved by any algorithm — that is the definition in section 3.3.1; the Halting Problem is the book's example. Note that (d) describes intractable problems, which are solvable but slow — a different category. ناقابل حل مسئلے کی تعریف یہی ہے کہ اسے کوئی الگورتھم حل نہیں کر سکتا؛ (d) ناقابل عمل مسائل کی صفت ہے جو حل پذیر مگر سست ہوتے ہیں۔
4. The meaning of NP in computational complexity is:
Answer: (a) Non-deterministic Polynomial time — the book defines NP as Non-deterministic Polynomial time (section 3.3.3). Remember the working meaning: a proposed solution can be checked quickly. NP کا مطلب Non-deterministic Polynomial time ہے؛ عملی مطلب یہ ہے کہ دیے گئے حل کو جلدی جانچا جا سکتا ہے۔
5. Search algorithm more efficient for large datasets:
Answer: (d) Quick Sort — keyed as the book's Answers section (printed page 141) gives it. ⚠️ Flawed question, flagged: the question says “search algorithm”, but all four options are sorting algorithms, not searching ones. Read with the book's intended meaning — the most efficient sorting algorithm in the list for large datasets — Quick Sort (average O(n log n)) is the intended answer. ⚠️ سوال میں خامی ہے: سوال ”سرچ الگورتھم“ کہتا ہے مگر چاروں آپشن ترتیب دینے والے الگورتھم ہیں۔ کتاب کے جوابات کے مطابق (d) ہی مطلوبہ جواب ہے۔
6. A scenario where Dynamic Programming proves most useful:
Answer: (c) Problems with overlapping subproblems and optimal substructure — the book's two conditions for DP (section 3.5.3); (b) describes greedy algorithms and (d) describes divide and conquer. DP کی دو شرطیں یہی ہیں: اوورلیپنگ ذیلی مسائل اور بہترین ذیلی ساخت؛ (b) لالچی اور (d) تقسیم کرو اور فتح کرو کی صفت ہے۔
7. An algorithm that sorts data by stepping through the list and swapping adjacent elements if needed is:
Answer: (c) Bubble Sort — stepping through and swapping adjacent out-of-order elements is the book's definition of Bubble Sort (section 3.6.1.1). فہرست سے گزر کر ساتھ والے غلط ترتیب والے عناصر کو بدلنا ببل سارٹ کی ہی تعریف ہے۔
8. Time complexity of Depth-First Search (DFS) in a graph is:
Answer: (c) O(V + E) — the book states DFS costs O(V + E), where V is the number of vertices and E the number of edges, the same as BFS. کتاب کے مطابق DFS کی قیمت O(V + E) ہے، جہاں V ورٹیسز اور E کناروں کی تعداد ہے، بالکل BFS جیسی۔
9. Best description of time complexity:
Answer: (b) Time taken as a function of input size — the book's definition in section 3.4.1. Note (a) and (d) describe space complexity, and (c) is close but vaguer; the book's key is (b). وقتی پیچیدگی کی کتابی تعریف یہی ہے: ان پٹ کے حجم کے فنکشن کے طور پر لیا گیا وقت؛ (a) اور (d) جگہ کی پیچیدگی کی صفت ہیں۔
10. An algorithm with a time complexity of O(n log n):
Answer: (c) Merge Sort — the book gives Merge Sort (and Quick Sort) as O(n log n); Bubble Sort is O(n²) and Binary Search is O(log n). کتاب کے مطابق Merge Sort (اور Quick Sort) O(n log n) ہیں؛ ببل سارٹ O(n²) اور بائنری سرچ O(log n) ہے۔
A well-defined problem has a clear goal, clear inputs, a clear process and a clear output, so a computer can be given exact instructions — the book's example is deciding whether a number is even (input one integer, check divisibility by 2, output “even” or “odd”). An ill-defined problem lacks clear definitions and has vague or ambiguous goals and requirements — the book's example is “how to reduce poverty in Pakistan”, which has no single input, process or checkable answer. In short: well-defined problems can be coded directly; ill-defined ones must first be sharpened into well-defined form. واضح مسئلے میں مقصد، ان پٹ، پراسیس اور آؤٹ پٹ سب واضح ہوتے ہیں، جیسے جفت عدد کی جانچ؛ غیر واضح مسئلے میں مقاصد مبہم ہوتے ہیں، جیسے ”پاکستان میں غربت کیسے کم کی جائے“، جسے پہلے واضح شکل دینا ضروری ہے۔
Step 1: Generate a possible (candidate) solution to the problem. Step 2: Test it against the required conditions. Step 3: If it passes, stop — a satisfactory solution is found. Step 4: If it fails, generate the next candidate and test again. Step 5: Continue until a solution is found or all possible solutions have been exhausted. The method works best when the problem space is small, when no direct strategy exists, or when heuristics can prune the candidates. پہلے ایک ممکنہ حل بنائیں، پھر اسے شرائط پر جانچیں؛ کامیاب ہو تو رک جائیں، ناکام ہو تو اگلا امیدوار بنائیں اور جانچیں؛ اس وقت تک جاری رکھیں جب تک حل نہ مل جائے یا تمام امکانات ختم نہ ہو جائیں۔
Tractable problems can be solved in polynomial time (class P) — the time grows at a manageable rate with input size, so they are called “efficiently solvable”; the book's example is sorting with Merge Sort or Quick Sort at O(n log n). Intractable problems need super-polynomial, often exponential, time — solvable in principle but impractical for large inputs; the book's example is the Travelling Salesman Problem, whose possible routes grow factorially with the number of cities. The difference is not solvable versus unsolvable, but feasible versus infeasible as inputs grow. قابل عمل مسائل کثیر رقمی وقت میں حل ہوتے ہیں، جیسے O(n log n) میں ترتیب دینا؛ ناقابل عمل مسائل کو فوق کثیر رقمی، اکثر کفایتی وقت چاہیے، جیسے TSP جس کے راستے عاملی انداز میں بڑھتے ہیں — اصولی طور پر حل پذیر مگر بڑے ان پٹ کے لیے ناقابل عمل۔
The key idea is to make a sequence of choices, each locally optimal — the best-looking move at that moment — hoping the chain of local bests leads to a globally optimal solution. It suits problems with optimal substructure, where the best whole answer is built from best sub-answers. The book's example is coin change: repeatedly take the largest coin not exceeding the remaining amount. The caution is that greedy does not always guarantee the optimal answer, so the problem must be analysed first. بنیادی خیال یہ ہے کہ ہر قدم پر مقامی طور پر بہترین فیصلہ کریں، اس امید پر کہ یہ سلسلہ عالمی طور پر بہترین حل دے گا؛ سکوں کی مثال میں ہر بار سب سے بڑا سکہ لیں جو باقی رقم سے زیادہ نہ ہو — مگر یہ ہمیشہ بہترین حل کی ضمانت نہیں دیتا۔
Dynamic Programming breaks a problem into simpler subproblems and stores their results, so overlapping subproblems are solved only once instead of again and again. This avoids redundant calculations and can turn an exponential-time computation into a polynomial (for Fibonacci, linear) one — the book's example stores each Fibonacci number as computed and reads it back when needed. It also fits problems with optimal substructure, where the best whole answer is assembled from best sub-answers, giving both speed and a clear table of intermediate results to check. DP ذیلی مسائل کے نتائج محفوظ کر کے بار بار کی گنتی سے بچاتا ہے، جس سے کفایتی وقت والا حساب کثیر رقمی (فبوناچی کے لیے خطی) بن جاتا ہے؛ فبوناچی کی ہر قیمت ایک بار نکالی جاتی ہے اور پھر جدول سے پڑھی جاتی ہے۔
BFS explores level by level using a queue, so it finds the shortest path in an unweighted graph (for example, the degree of separation between two people in a social network) and is well suited to shallow graphs; its output on the book's graph is 0, 1, 2, 3, 4, 5, 6, 7. DFS explores as far down a branch as possible using a stack, backtracking at dead ends, so it suits mazes and puzzles and is more memory-efficient for deep graphs; its output on the same graph is 0, 1, 4, 5, 2, 6, 3, 7. Both cost O(V + E); the choice depends on whether you need shortest paths and level order (BFS) or deep exploration with less memory (DFS). BFS قطار سے سطح بہ سطح کھوجتا ہے، اس لیے غیر وزنی گراف میں سب سے چھوٹا راستہ دیتا ہے اور اتھلے گراف کے لیے موزوں ہے؛ DFS اسٹیک سے ایک شاخ کی گہرائی تک جاتا ہے، اس لیے بھول بھلیوں اور گہرے گراف کے لیے میموری میں زیادہ مؤثر ہے؛ دونوں کی قیمت O(V + E) ہے۔
Breaking a problem down turns one overwhelming task into smaller, manageable parts that can be understood, solved independently and then combined — the Divide and Conquer idea, and the same instinct behind DP's subproblems and backtracking's step-by-step building. Small parts are easier to test, easier to reason about, and easier to reuse; a bug can be traced to one part instead of the whole program. It also reveals the problem's real structure — its inputs, outputs and repeated subproblems — which is what lets you choose the right technique instead of guessing. This answer is elaborated from the chapter's design-technique sections, since the book states the techniques without a separate passage on this question. مسئلے کو چھوٹے حصوں میں توڑنا اسے قابل انتظام بناتا ہے: ہر حصہ آزادانہ طور پر سمجھا، حل اور جانچا جا سکتا ہے، اور پھر نتائج ملا کر اصل مسئلہ حل ہوتا ہے — یہی Divide and Conquer، DP اور بیک ٹریکنگ کی مشترکہ روح ہے۔ یہ جواب باب کی تکنیکوں سے اخذ شدہ وضاحت ہے۔
The book evaluates an algorithm mainly by its time complexity — how running time grows with input size, expressed in Big O notation (O(1), O(n), O(n²), O(log n)) — and its space complexity — how memory use grows with input size. Beyond those two, the chapter's discussion adds correctness (does it give the right answer for all inputs, i.e. is the problem even solvable), efficiency and scalability (does it stay practical as inputs grow, the tractable/intractable question), and ease of implementation (Bubble Sort survives in teaching because it is simple, even though it is O(n²)). الگورتھم کی کارکردگی جانچنے کے بنیادی عوامل وقتی پیچیدگی (Big O میں، جیسے O(1)، O(n)، O(n²)، O(log n)) اور جگہ کی پیچیدگی ہیں؛ اس کے ساتھ درستگی، مؤثریت اور پیمانہ پذیری (بڑے ان پٹ پر بھی عملی رہنا) اور نفاذ کی آسانی بھی شامل ہے۔
The Halting Problem asks: given any program and its input, will it eventually halt or run forever? It is unsolvable because no general algorithm can answer it correctly for every program–input pair — Alan Turing proved this, as the book states. The reason, in simple words (this proof sketch is an elaboration of the book's statement, not a book passage): suppose a checker H always answered correctly. Build a program D that asks H about itself and does the opposite — if H says “D halts”, D loops forever; if H says “D loops”, D stops at once. Whatever H says about D is wrong, so such an H cannot exist. The implications are deep: there are hard limits on what computers can ever decide, so programmers must not waste effort chasing a perfect general bug-detector or a universal program analyser; instead, they test, restrict the problem, or accept partial answers. It also draws the line the whole chapter respects — first check solvability, then worry about speed — and it underpins the P/NP discussion, since even among solvable problems many resist efficient solutions. ہالٹنگ پرابلم یہ پوچھتا ہے کہ کوئی پروگرام آخرکار رکے گا یا ہمیشہ چلے گا؛ یہ ناقابل حل ہے کیونکہ کوئی عمومی الگورتھم ہر پروگرام–ان پٹ کے لیے درست جواب نہیں دے سکتا — ٹیورنگ نے یہ ثابت کیا۔ سادہ دلیل یہ ہے کہ اگر کوئی جانچنے والا H ہمیشہ درست جواب دے تو ایک پروگرام D بنایا جا سکتا ہے جو H سے اپنے بارے میں پوچھ کر اس کے الٹ کرے، پس H کا ہر جواب غلط ہوگا۔ اس کا نتیجہ یہ ہے کہ کمپیوٹر کی فیصلہ کرنے کی صلاحیت کی حدود ہیں، اس لیے کامل عمومی بگ ڈیٹیکٹر کا پیچھا کرنے کے بجائے جانچ، مسئلے کو محدود کرنا یا جزوی جواب قبول کرنا پڑتا ہے۔ یہ ثبوت کا خاکہ کتاب کے بیان کی وضاحت ہے، کتاب کا اقتباس نہیں۔
A search problem asks you to find an item or a solution that meets certain criteria — for example, finding a named student in a list or a value in a dataset. Its characteristics are a set of candidates to search through, a target or condition to match, and an answer that is either the item's position (or the item itself) or the conclusion that it is absent. Linear search checks items one by one from the start: it works on unsorted data and is simple, but costs O(n) checks in the worst case — for the book's cities [Karachi, Lahore, Islamabad, Faisalabad], Islamabad is found on the third check, and an absent city would cost all four. Binary search repeatedly halves a sorted list — middle element, then the left or right half — costing only O(log n) checks; the book's figure finds 78 in [21, 34, 43, 57, 66, 78] in three checks instead of six. So binary search is dramatically faster on large data, but it demands sorted input (sort first, e.g. with Merge Sort, if it is not sorted), while linear search is the only choice of the two for unsorted data. تلاش کے مسئلے میں امیدواروں کے مجموعے میں سے کسی شرط پر پورا اترنے والی شے تلاش کرنی ہوتی ہے؛ جواب یا تو اس کی جگہ ہوتی ہے یا یہ نتیجہ کہ وہ موجود نہیں۔ لینیئر سرچ ایک ایک کر کے جانچتا ہے، غیر ترتیب شدہ ڈیٹا پر کام کرتا ہے مگر بدترین صورت میں O(n) قیمت لیتا ہے؛ بائنری سرچ ترتیب شدہ فہرست کو بار بار آدھا کرتی ہے اور صرف O(log n) قیمت لیتی ہے — کتاب کی مثال میں 78 چھ کی بجائے تین جانچوں میں ملتا ہے — مگر اسے ترتیب شدہ ان پٹ چاہیے۔
An optimization problem asks not just for any valid solution but for the best one according to some measure — shortest, cheapest, fastest, or most valuable. That “best by a measure” is its nature: there is an objective to maximise or minimise, subject to constraints, and usually many candidate solutions to compare. Real-world applications from the chapter: the Travelling Salesman Problem — the shortest route visiting a set of cities and returning to the start, used in delivery routing and trip planning; the Knapsack Problem — the most valuable combination of items within a weight capacity, used in cargo loading and resource allocation; and the coin-change problem — making an amount with the fewest coins, the everyday face of minimisation. Sorting and searching feed into optimization too, since finding the best route or the cheapest option usually starts by organising and searching data efficiently. Note that optimization problems are often the hard ones: TSP is intractable and knapsack is NP-complete, so in practice a very good solution found quickly is often accepted instead of the perfect one. بہترین حل کے مسئلے میں کوئی بھی درست حل نہیں بلکہ کسی پیمانے کے لحاظ سے بہترین حل چاہیے ہوتا ہے — سب سے چھوٹا، سستا، تیز یا قیمتی۔ حقیقی مثالیں: TSP یعنی شہروں کا سب سے چھوٹا دورہ (ڈیلیوری کی روٹنگ)، نیپ سیک یعنی وزن کی حد میں سب سے قیمتی مجموعہ (کارگو اور وسائل کی تقسیم)، اور سکوں کی تبدیلی یعنی کم سے کم سکوں سے رقم بنانا۔ یہ مسائل اکثر مشکل ہوتے ہیں — TSP ناقابل عمل اور نیپ سیک NP-complete ہے — اس لیے عملی طور پر جلدی ملنے والا بہت اچھا حل قبول کر لیا جاتا ہے۔
Bubble Sort repeatedly steps through the list, compares adjacent elements, and swaps them if they are in the wrong order, repeating until no swaps are needed. On the book's [5, 3, 8, 4, 2]: Pass 1 gives [3, 5, 4, 2, 8]; Pass 2 gives [3, 4, 2, 5, 8]; Pass 3 gives [3, 2, 4, 5, 8]; Pass 4 gives [2, 3, 4, 5, 8]. Each pass compares roughly n pairs and there are roughly n passes, so the time complexity is O(n²) — doubling the list roughly quadruples the work. Compare with Merge Sort (the chosen comparison, from section 3.5.1): Merge Sort divides the list in half again and again and merges sorted halves, costing O(n log n). For n = 1,000, Bubble Sort needs on the order of 1,000,000 operations while Merge Sort needs on the order of 10,000 — about a hundred times less work — and the gap only widens as n grows. Bubble Sort's only real advantages are simplicity and the fact that it needs no extra list; for large data, Merge Sort (or Quick Sort) is the efficient choice, which is exactly the book's own tip. ببل سارٹ بار بار فہرست سے گزر کر ساتھ والے غلط ترتیب والے عناصر کو بدلتا ہے جب تک تبدیلی کی ضرورت نہ رہے؛ [5, 3, 8, 4, 2] پر چار گزر کے بعد [2, 3, 4, 5, 8] ملتا ہے، اور وقتی پیچیدگی O(n²) ہے۔ مقابلے میں Merge Sort فہرست کو آدھا کر کے ترتیب شدہ آدھوں کو ملاتا ہے اور O(n log n) لیتا ہے — n = 1,000 پر تقریباً 10,000 کے مقابلے میں 1,000,000 آپریشن، یعنی سو گنا کم کام — اس لیے بڑے ڈیٹا کے لیے Merge Sort ہی مؤثر انتخاب ہے۔
Time complexity measures how an algorithm's running time grows as input size grows; space complexity measures how its memory use grows as input size grows. Both are expressed in Big O notation, but they price different resources: time prices speed, space prices memory. An algorithm can be fast but memory-hungry (copying a whole list costs O(n) extra space) or memory-light but slow (recomputing values instead of storing them, as naive Fibonacci does). The choice for a specific problem weighs both against the machine and the task: on a phone with little memory, an O(1)-extra-space algorithm may beat a faster O(n)-space one; for a huge dataset that must be processed quickly, O(n log n) time may matter more than a little extra memory; and if neither a fast nor a light algorithm exists, the problem may be intractable, and a good-enough approximate answer becomes the sensible choice. Good algorithm selection, in the chapter's terms, is therefore a trade-off — predict performance with time and space analysis first, then pick the best balance for the task at hand. وقتی پیچیدگی یہ ناپتی ہے کہ ان پٹ بڑھنے پر چلنے کا وقت کیسے بڑھتا ہے، اور جگہ کی پیچیدگی یہ کہ میموری کا استعمال کیسے بڑھتا ہے؛ دونوں Big O میں بیان ہوتی ہیں مگر مختلف وسائل کی قیمت لگاتی ہیں۔ کوئی الگورتھم تیز مگر میموری کا بھوکا ہو سکتا ہے (پوری فہرست کی نقل O(n) اضافی جگہ لیتی ہے) یا میموری میں ہلکا مگر سست (نتائج محفوظ کرنے کے بجائے دوبارہ نکالنا)۔ کسی خاص مسئلے کے لیے انتخاب مشین اور کام کے لحاظ سے دونوں کو تولتا ہے: کم میموری والے فون پر O(1) اضافی جگہ والا الگورتھم تیز مگر O(n) جگہ والے سے بہتر ہو سکتا ہے، اور بڑے ڈیٹا کے لیے O(n log n) وقت تھوڑی اضافی میموری سے زیادہ اہم ہو سکتا ہے۔
اس باب میں کیا ہے؟ Computational problems کی پوری بنیاد: input–process–output سے شروع کر کے problem types (decision, search, optimization, counting), well-defined vs ill-defined, algorithms اور Generate-and-Test, solvable vs unsolvable (Halting Problem), tractable vs intractable (TSP), complexity classes P, NP, NP-hard اور NP-complete (Sudoku, Knapsack), time اور space complexity کے ساتھ Big O (O(1), O(n), O(n²), O(log n)), design techniques (Divide and Conquer, Greedy, Dynamic Programming, Backtracking), اور آخر میں اصل algorithms — Bubble Sort, Selection Sort, Linear اور Binary Search, BFS اور DFS — سب full traces کے ساتھ.
Revision guidance: پہلے Big O کی چار curves اور BFS/DFS کی output orders زبانی یاد کرو — یہ MCQs میں سیدھے آتے ہیں. پھر Bubble Sort اور Selection Sort کی traces ہاتھ سے لکھ کر practice کرو, بنا دیکھے. آخر میں Halting Problem کی دلیل اپنے الفاظ میں دو مرتبہ لکھو, اور P/NP/NP-complete کے فرق کو ایک line میں سمجھاؤ. Exercise: 📝 Official Exercise Questions — with Answers — MCQ 5 کی flaw اور section 3.4.1 کی گنتی کی correction کو خاص توڑ پر note کرو, کیونکہ paper میں book کی غلطی بھی پوچھی جا سکتی ہے.
اس باب میں کیا ہے؟ کمپیوٹیشنل مسائل کی پوری بنیاد: ان پٹ–پراسیس–آؤٹ پٹ سے شروع کر کے مسائل کی اقسام (فیصلہ، تلاش، بہترین حل، گنتی)، واضح و غیر واضح مسائل، الگورتھم اور Generate-and-Test، حل پذیر و ناقابل حل (ہالٹنگ پرابلم)، قابل عمل و ناقابل عمل (TSP)، پیچیدگی کی جماعتیں P، NP، NP-hard اور NP-complete (سوڈوکو، نیپ سیک)، وقتی اور جگہ کی پیچیدگی کے ساتھ Big O، ڈیزائن تکنیکیں (تقسیم کرو اور فتح کرو، لالچی، ڈائنامک پروگرامنگ، بیک ٹریکنگ)، اور آخر میں اصل الگورتھم — ببل سارٹ، سلیکشن سارٹ، لینیئر اور بائنری سرچ، BFS اور DFS — سب مکمل ٹریس کے ساتھ۔
دہرائی کی رہنمائی: پہلے Big O کی چار منحنیات اور BFS/DFS کی آؤٹ پٹ ترتیبیں زبانی یاد کریں — یہ MCQs میں براہ راست آتی ہیں۔ پھر ببل سارٹ اور سلیکشن سارٹ کی ٹریس ہاتھ سے لکھ کر مشق کریں، بغیر دیکھے۔ آخر میں ہالٹنگ پرابلم کی دلیل اپنے الفاظ میں دو مرتبہ لکھیں، اور P/NP/NP-complete کا فرق ایک سطر میں سمجھائیں۔ مشق: 📝 کتاب کی مشق — جوابات کے ساتھ — MCQ 5 کی خامی اور حصہ 3.4.1 کی گنتی کی تصحیح کو خاص طور پر نوٹ کریں۔
Chapter-wise tests, fresh random papers اور instant score کے لیے PunjabTest.com کا میں test section دیکھو:
PunjabTest.com — Complete Guide Book • FSc Part 1 Computer Science, Chapter 3 (New Book, Session 2026–27) • English + Urdu