20. Linked List - Problems
লিঙ্কড লিস্টের কনসেপ্ট পরিষ্কার করার জন্য প্র্যাকটিক্যাল প্রবলেম সলভ করা জরুরি। এখানে ইন্টারভিউতে আসা জনপ্রিয় কিছু প্রবলেম এবং তাদের লজিক আলোচনা করা হলো।
1. লিঙ্কড লিস্ট রিভার্স করা (Reverse Linked List)
একটি লিঙ্কড লিস্টের সব নোডের লিঙ্ক উল্টে দেওয়া।
🛠 কর্মপদ্ধতি (Step-by-Step Logic)
- তিনটি পয়েন্টার নিন:
prev = null,curr = head, এবংnext = null। - লিস্টটি ট্রাভার্স করার সময় প্রতিটি নোডে:
next-কেcurr.next-এ সেভ করুন।curr.next-কেprev-এর দিকে পয়েন্ট করান (লিঙ্ক উল্টানো)।prev-কেcurrএবংcurr-কেnext-এ সরিয়ে নিন।
- সবশেষে
head-কেprev-এ আপডেট করুন।
Implementation
java
// Java Reverse
public Node reverse(Node head) {
Node prev = null, curr = head, next = null;
while (curr != null) {
next = curr.next;
curr.next = prev;
prev = curr;
curr = next;
}
return prev;
}python
# Python Reverse
def reverse(head):
prev, curr = None, head
while curr:
next_node = curr.next
curr.next = prev
prev = curr
curr = next_node
return prev📊 কমপ্লেক্সিটি অ্যানালাইসিস (Complexity Analysis)
- Time Complexity: O(n)
- Space Complexity: O(1)
2. সাইকেল ডিটেকশন (Detect Cycle - Floyd's Algorithm)
লিস্টের কোনো নোড কি পুনরায় আগের কোনো নোডকে পয়েন্ট করছে?
🛠 কর্মপদ্ধতি (Step-by-Step Logic)
- দুটি পয়েন্টার নিন:
slowএবংfast। দুইজনেই শুরুতেhead-এ থাকবে। slowএক ঘর এবংfastদুই ঘর করে আগাতে থাকবে।- যদি তারা কোনো এক সময় মিলিত হয় (meet), তবে লিস্টে সাইকেল আছে।
- যদি
fastনাল (null) হয়ে যায়, তবে সাইকেল নেই।
Implementation
java
// Java Cycle Detection
public boolean hasCycle(Node head) {
Node slow = head, fast = head;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
if (slow == fast) return true;
}
return false;
}python
# Python Cycle Detection
def has_cycle(head):
slow, fast = head, head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
if slow == fast: return True
return False📊 কমপ্লেক্সিটি অ্যানালাইসিস (Complexity Analysis)
- Time Complexity: O(n)
- Space Complexity: O(1)
3. মিডল এলিমেন্ট খুঁজে বের করা (Find Middle Element)
🛠 কর্মপদ্ধতি (Step-by-Step Logic)
- Two Pointer approach:
slowএক ঘর এবংfastদুই ঘর করে আগাতে থাকুন। যখনfastলিস্টের শেষে পৌঁছাবে, তখনslowথাকবে ঠিক মাঝখানে।
Implementation
java
// Java Find Middle
public Node findMiddle(Node head) {
Node slow = head, fast = head;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
}
return slow;
}python
# Python Find Middle
def find_middle(head):
slow, fast = head, head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
return slow4. ডুপ্লিকেট রিমুভ করা (Remove Duplicates)
🛠 কর্মপদ্ধতি (Step-by-Step Logic) - Sorted List
- বর্তমান নোড এবং তার পরের নোড তুলনা করুন।
- যদি তারা এক হয়, তবে বর্তমান নোডের
next-কে এক ঘর বাদ দিয়ে পরের নোডে পয়েন্ট করান।
Implementation
java
// Java Remove Duplicates
public Node removeDuplicates(Node head) {
Node curr = head;
while (curr != null && curr.next != null) {
if (curr.data == curr.next.data) curr.next = curr.next.next;
else curr = curr.next;
}
return head;
}python
# Python Remove Duplicates
def remove_duplicates(head):
curr = head
while curr and curr.next:
if curr.data == curr.next.data:
curr.next = curr.next.next
else:
curr = curr.next
return head5. দুটি সর্টেড লিস্ট মার্চ করা (Merge Two Sorted Lists)
🛠 কর্মপদ্ধতি (Step-by-Step Logic)
- একটি ডামি (Dummy) নোড নিন এবং রেজাল্ট লিস্টটি সেখান থেকে শুরু করুন।
- দুটি লিস্টের সামনের নোড তুলনা করুন। যেটির ভ্যালু ছোট, সেটিকে নতুন লিস্টে যোগ করুন এবং সেই প্রসংশিত লিস্টের হেড এক ঘর এগিয়ে নিন।
- এভাবে চলতে থাকুন যতক্ষণ না কোনো একটি লিস্ট শেষ হয়।
Implementation
java
// Java Merge
public Node mergeTwoLists(Node l1, Node l2) {
Node dummy = new Node(0);
Node curr = dummy;
while (l1 != null && l2 != null) {
if (l1.data < l2.data) {
curr.next = l1;
l1 = l1.next;
} else {
curr.next = l2;
l2 = l2.next;
}
curr = curr.next;
}
if (l1 != null) curr.next = l1;
if (l2 != null) curr.next = l2;
return dummy.next;
}python
# Python Merge
def merge_two_lists(l1, l2):
dummy = Node(0)
curr = dummy
while l1 and l2:
if l1.data < l2.data:
curr.next = l1
l1 = l1.next
else:
curr.next = l2
l2 = l2.next
curr = curr.next
curr.next = l1 or l2
return dummy.next6. প্যালিনড্রোম চেক (Palindrome Check)
🛠 কর্মপদ্ধতি (Step-by-Step Logic)
- মাঝখানের নোড খুঁজে বের করুন।
- দ্বিতীয় অর্ধেক অংশটি রিভার্স (Reverse) করুন।
- প্রথম অর্ধেক এবং দ্বিতীয় অর্ধেকের নোডগুলো এক এক করে তুলনা করুন।
7. ইন্টারসেকশন পয়েন্ট (Intersection Point)
দুটি লিঙ্কড লিস্ট এক জায়গায় মিলিত হয়েছে কি না তা বের করা।
🛠 কর্মপদ্ধতি (Step-by-Step Logic)
- দুটি লিস্টের লেন্থ (
L1ওL2) বের করুন। - বড় লিস্টের হেডকে
|L1 - L2|পরিমাণ আগিয়ে নিন যাতে তারা সমান দূরত্বে থাকে। - এবার দুই লিস্ট এক সাথে আগাতে থাকুন যতক্ষণ না একই নোড পাওয়া যায়।
8. শেষ থেকে N-তম নোড রিমুভ (Remove Nth node from end)
🛠 কর্মপদ্ধতি (Step-by-Step Logic)
- দুটি পয়েন্টার নিন:
firstএবংsecond। first-কে N ঘর আগে আগিয়ে নিন।- এবার
firstএবংsecondএকসাথে আগাতে থাকুন। যখনfirstশেষ নোডে পৌঁছাবে, তখনsecondথাকবে লক্ষ্য নোডের ঠিক আগে। second.next = second.next.nextকরে নোডটি রিমুভ করুন।
Implementation
java
// Java Remove Nth from End
public Node removeNthFromEnd(Node head, int n) {
Node dummy = new Node(0);
dummy.next = head;
Node first = dummy, second = dummy;
for (int i = 0; i <= n; i++) first = first.next;
while (first != null) {
first = first.next;
second = second.next;
}
second.next = second.next.next;
return dummy.next;
}python
# Python Remove Nth from End
def remove_nth_from_end(head, n):
dummy = Node(0)
dummy.next = head
first = second = dummy
for _ in range(n + 1):
first = first.next
while first:
first = first.next
second = second.next
second.next = second.next.next
return dummy.nextIMPORTANT
লিঙ্কড লিস্টের বেশিরভাগ সমস্যা Two Pointer (Slow & Fast) টেকনিক দিয়ে অত্যন্ত কার্যকরভাবে সমাধান করা যায়।
TIP
কোড করার সময় সবসময় null হ্যান্ডলিং এবং কর্নার কেস (যেমন: লিস্টে মাত্র ১টি নোড থাকা) মাথায় রাখবেন।