Skip to content
Topic guide · Data Structures

Arrays and Linked Lists: Address Calculation, Types and Big-O · অ্যারে ও লিংকড লিস্ট: অ্যাড্রেস নির্ণয়, প্রকারভেদ ও বিগ-ও

An array stores elements of one type in contiguous memory, so any element is reached directly by its index in O(1) time (random access), but inserting or deleting in the middle costs O(n) because later elements must shift. A linked list stores each element in a separate node that holds the data and a pointer to the next node (a doubly linked list also keeps a pointer to the previous node, so each node has at least 3 fields), so it grows freely and inserts at a known position in O(1), but reaching the k-th element or searching costs O(n). In row-major order the address of A[i][j] in an m × n array is Base + w × (i × n + j), and in column-major order it is Base + w × (j × m + i), counting indices from 0.

অ্যারে একই টাইপের উপাদান পাশাপাশি (কন্টিগুয়াস) মেমোরিতে রাখে, তাই ইনডেক্স দিয়ে যেকোনো উপাদানে সরাসরি O(১) সময়ে পৌঁছানো যায় (random access), কিন্তু মাঝখানে ইনসার্ট বা ডিলিট করতে O(n) সময় লাগে, কারণ পরের উপাদানগুলো সরাতে হয়। লিংকড লিস্টে প্রতিটি উপাদান আলাদা নোডে থাকে, যাতে ডেটা ও পরের নোডের পয়েন্টার থাকে (ডাবলি লিংকড লিস্টে আগের নোডের পয়েন্টারও থাকে, তাই প্রতিটি নোডে অন্তত ৩টি ফিল্ড); এটি সহজে বাড়ানো যায় এবং জানা অবস্থানে O(১) সময়ে ইনসার্ট করা যায়, কিন্তু k-তম উপাদানে পৌঁছাতে বা সার্চ করতে O(n) লাগে। ০ থেকে ইনডেক্স গুনলে m × n অ্যারেতে রো-মেজর ক্রমে A[i][j]-এর অ্যাড্রেস = Base + w × (i × n + j), আর কলাম-মেজর ক্রমে = Base + w × (j × m + i)।

Asked in past exams
51
Papers
35

1. Arrays: the basic idea

An array is a collection of elements of the same data type stored in contiguous (side-by-side) memory locations and reached by an index (subscript). Because every element has the same size and they sit one after another, the computer can compute where any element is, so arrays give random (direct) access: A[700] costs the same as A[0].

  • Lower bound (LB) is the smallest index and upper bound (UB) the largest. C, C++, Java and Python start at 0; pseudocode and some exam questions start at 1 or at any number.
  • Number of elements = UB − LB + 1. An array A[−5 … 20] has 20 − (−5) + 1 = 26 elements.
  • A classic array has a fixed size set when it is created. Dynamic arrays (C++ vector, Java ArrayList, Python list) grow by copying into a bigger block when full.
  • A two-dimensional array is a table of rows and columns, so it is also called a matrix or table array.

2. Address calculation

One dimension. With base address B (the address of the first element), element size w bytes and lower bound LB:

Address of A[i] = B + w × (i − LB)

For a C array (LB = 0) this is B + w × i. Example: int A[], B = 1000, w = 2, LB = −5: A[7] is at 1000 + 2 × (7 + 5) = 1024.

Two dimensions. Memory is one long line, so a table must be laid out in some order:

  • Row-major: the whole of row 0, then row 1, and so on. C and C++ use it, and so does Python's NumPy by default. (Java builds a 2-D array as an array of separate row arrays, but exam questions still treat it as row-major.)
  • Column-major: the whole of column 0, then column 1, and so on. Fortran, MATLAB and R use it.

For A with rows LB₁ … UB₁ and columns LB₂ … UB₂, let R = UB₁ − LB₁ + 1 (rows) and C = UB₂ − LB₂ + 1 (columns). Then:

Order Address of A[i][j] With indices from 0 (m rows, n columns)
Row-major B + w × [(i − LB₁) × C + (j − LB₂)] B + w × (i × n + j)
Column-major B + w × [(j − LB₂) × R + (i − LB₁)] B + w × (j × m + i)

The memory picture: in row-major you skip whole rows (each C elements long) to reach row i, then step along the row; in column-major you skip whole columns (each R elements long).

A 2 × 3 array laid out in memory row by row (row-major) and column by column (column-major).

Worked example 1 (indices from 0). int M[4][5] (4 rows, 5 columns), base address 2000, w = 4 bytes. Find the address of M[2][3].

  1. Row-major: skip 2 full rows of 5 elements = 10 elements, then 3 more: offset 2 × 5 + 3 = 13 elements.
  2. Address = 2000 + 4 × 13 = 2052. (A C program printing &M[2][3] − &M[0][0] gives 52 bytes, the same offset.)
  3. Column-major: skip 3 full columns of 4 elements = 12 elements, then 2 more: 14 elements.
  4. Address = 2000 + 4 × 14 = 2056.

Worked example 2 (any lower bounds). A[−2 … 7][3 … 10], base 500, w = 4. Find A[4][6] in both orders.

  1. Rows: R = 7 − (−2) + 1 = 10. Columns: C = 10 − 3 + 1 = 8.
  2. Row offset i − LB₁ = 4 − (−2) = 6; column offset j − LB₂ = 6 − 3 = 3.
  3. Row-major: 500 + 4 × (6 × 8 + 3) = 500 + 4 × 51 = 704.
  4. Column-major: 500 + 4 × (3 × 10 + 6) = 500 + 4 × 36 = 644.

The usual slip is multiplying by the wrong count: row-major multiplies the row offset by the number of columns; column-major multiplies the column offset by the number of rows.

Sparse matrix. A matrix in which most elements are zero. Storing it in full wastes space, so only the non-zero elements are kept, as (row, column, value) triplets in an array, or in a linked list. A plain 2-D array is the wrong choice when, for example, 990 of 1,000 cells are 0.

3. Strings

A string is a sequence of characters, stored as an array of characters. In C a string ends with the null character '\0' (value 0), which takes one extra byte:

  • char s[] = "DHAKA"; → sizeof s = 6 bytes (5 letters + '\0'), strlen(s) = 5.
  • char t[10] = "DHAKA"; → sizeof t = 10 (the declared size), strlen(t) = 5.

strlen walks the array until it meets '\0', so it costs O(n). Java and Python store the length with the string (O(1) to read) and their strings are immutable: "changing" one makes a new string. With UTF-8 text, as in Bangla, one character can take 1 to 4 bytes, so bytes and characters are not the same count.

4. Linked lists and their types

A linked list is a chain of nodes. Each node holds the data and a pointer (link) to the next node; the nodes can be anywhere in memory. A pointer called head marks the first node, and the last node's next pointer is NULL. A linked list is a linear, dynamic data structure: nodes are created (malloc / new) and freed as needed.

struct node {
    int data;
    struct node *next;     /* a singly linked list node has 2 fields */
};

A structure that holds a pointer to its own type, like struct node, is called a self-referential structure; it is the building block of every linked list and tree. If malloc cannot find memory for a new node (it returns NULL) the list has an overflow; trying to delete from an empty list is an underflow. Some lists start with a header (sentinel) node that holds no real data, so that inserting or deleting at the front needs no special case.

Type Links in each node Fields per node (minimum) Can move Last node points to
Singly linked next 2 (data, next) Forward only NULL
Doubly linked prev and next 3 (prev, data, next) Both ways NULL
Circular singly next 2 Forward, round and round The first node
Circular doubly prev and next 3 Both ways, round and round The first node (and the first node's prev points to the last)
A singly linked list with three nodes; each node points to the next and the last points to NULL.
A doubly linked list, where each node links to its previous and next node, and both ends point to NULL.
A circular linked list, where the last node points back to the first node instead of NULL.

Uses: singly lists for stacks, queues and the chains of a hash table; doubly lists for browser back/forward, undo and the LRU cache; circular lists for round-robin CPU scheduling and repeating playlists.

Inserting into a doubly linked list between nodes P and Q changes 4 links: the new node's prev (to P) and next (to Q), P's next and Q's prev. Inserting at the head changes the new node's next, the old head's prev and the head pointer itself.

5. Costs: the Big-O table

n is the number of elements.

Operation Array Singly linked list Doubly linked list
Access the k-th element O(1) O(n) O(n)
Search an unsorted list O(n) O(n) (n comparisons in the worst case) O(n)
Search a sorted list O(log n) with binary search O(n): no random access, so no binary search O(n)
Insert at the beginning O(n): shift everything O(1) O(1)
Insert at the end O(1) if there is room (amortised O(1) for a dynamic array) O(n); O(1) with a tail pointer O(1) with a tail pointer
Insert after a node you already hold O(n) shifting O(1) O(1)
Delete the first element O(n) shifting O(1) O(1)
Delete the last element O(1) O(n): you need the node before it, even with a tail pointer O(1) with a tail pointer
Delete a node you hold a pointer to O(n) shifting O(n) to find its predecessor (see trick 3 in section 8) O(1)
Count the elements O(1) (size known) O(n) unless a counter is kept O(n) unless a counter is kept

Worked example 3: n sorted insertions. Insert n numbers one by one into an empty linked list, keeping it sorted. In the worst case each new number belongs at the end, so the k-th insertion walks past all k − 1 nodes already there. Total comparisons = 0 + 1 + … + (n − 1) = n(n − 1)/2, which is Θ(n²). (A simulation for n = 10 counts 45 = 10 × 9/2.)

A queue on a singly linked list keeps two pointers: enqueue at the rear (O(1): link the new node after the tail) and dequeue at the front (O(1): move head forward). Doing it the other way round (adding at the front, removing at the rear) makes dequeue Θ(n), because the node before the rear must be found by walking from the head.

6. Array vs linked list

Point Array Linked list
Memory One contiguous block Nodes scattered, joined by pointers
Size Fixed when created (static) Grows and shrinks at run time (dynamic)
Access Random (direct), O(1) Sequential, O(n)
Insert or delete in the middle O(n), elements shift O(1) once the place is found
Extra memory None per element One pointer (singly) or two (doubly) per node
Cache behaviour Very good: neighbours are adjacent Poor: nodes are scattered
Wasted space Unused slots if declared too big None, apart from the pointers
Binary search Possible when sorted Not practical
Good for Lookup by index, matrices, fixed tables Frequent insertions and deletions, queues, unknown sizes

7. Classic linked-list questions

The functions below were compiled and run together on the list 10 → 20 → 30 → 40 → 50.

/* reverse in place: O(n) time, O(1) extra space */
struct node *reverse(struct node *head) {
    struct node *prev = NULL, *cur = head, *next;
    while (cur != NULL) {
        next = cur->next;          /* remember the rest of the list */
        cur->next = prev;          /* turn this link around */
        prev = cur;                /* step forward */
        cur = next;
    }
    return prev;                   /* the old last node is the new head */
}

/* middle: slow moves 1 step, fast moves 2 */
struct node *middle(struct node *head) {
    struct node *slow = head, *fast = head;
    while (fast != NULL && fast->next != NULL) {
        slow = slow->next;
        fast = fast->next->next;
    }
    return slow;                   /* for an even length: the second middle */
}

/* Floyd's cycle detection: returns 1 if there is a loop */
int has_cycle(struct node *head) {
    struct node *slow = head, *fast = head;
    while (fast != NULL && fast->next != NULL) {
        slow = slow->next;
        fast = fast->next->next;
        if (slow == fast) return 1;
    }
    return 0;
}

/* print in reverse order with recursion */
void print_reverse(struct node *p) {
    if (p == NULL) return;
    print_reverse(p->next);        /* print the rest first */
    printf("%d ", p->data);        /* then this node */
}

Results: reverse turns 10 20 30 40 50 into 50 40 30 20 10; middle returns 30 (and for six nodes, 60 50 40 30 20 10, it returns the second middle, 30); print_reverse on 50 40 30 20 10 prints 10 20 30 40 50; has_cycle returns 0, and 1 after the last node is linked back into the list.

Reversing, step by step. Three pointers walk the list. At each node: save next, point the node back at prev, then move prev and cur one step on. When cur becomes NULL, prev is the new head. Every node is visited once: O(n) time, O(1) extra memory.

Floyd's cycle check moves a slow pointer one step and a fast pointer two steps until they meet or the fast one reaches NULL.

Cycle trace. List 1 → 2 → 3 → 4 → 5 → 6, with 6 linked back to 3. After each step (slow, fast): (2, 3), (3, 5), (4, 3), (5, 5): they meet at node 5 after 4 steps, so there is a loop. Inside a loop the fast pointer gains one node per step on the slow one, so it must catch it; without a loop it reaches NULL. Floyd's method needs only two pointers, O(1) memory, against O(n) for remembering visited nodes in a hash set.

8. Tricky exam cases

  1. Array of a complete binary tree. Store the tree level by level. With indices from 0, the children of node i are at 2i + 1 and 2i + 2 and its parent at ⌊(i − 1)/2⌋. With indices from 1, the children are at 2i and 2i + 1 and the parent at ⌊i/2⌋. Read which convention the question uses.
  2. Sum of v[i][j] = i − j over an n × n array is 0: every pair (i, j) is matched by (j, i) with the opposite sign, and the diagonal is 0.
  3. Deleting a node of a singly linked list when you only have a pointer to it (and it is not the last node) takes O(1): copy the next node's data into it, then unlink the next node. It fails for the last node, which has no successor to copy.
  4. "Access methodology in an array" is random (direct) access; a linked list is sequential.
  5. Removing 11 from 3, 5, 7, 11, 13, 17: a linked list needs no data movement (one link changes), while an array must shift 13 and 17 left.
  6. Array vs structure: an array holds many values of the same type reached by index; a structure (struct) groups values of different types reached by member name.

Practice · অনুশীলন

  1. A[1 … 10][1 … 15] is stored in row-major order with base address 1000 and 2 bytes per element. What is the address of A[5][7]?
    Answer

    Columns C = 15. Offset = (5 − 1) × 15 + (7 − 1) = 60 + 6 = 66 elements. Address = 1000 + 2 × 66 = 1132. (In column-major order, with R = 10 rows: (7 − 1) × 10 + (5 − 1) = 64, so 1000 + 128 = 1128.)

  2. What is the minimum number of fields in a node of a doubly linked list, and what are they?
    Answer

    3: a pointer to the previous node, the data, and a pointer to the next node.

  3. What is the worst-case time to search for a value in a singly linked list of n nodes, and why can binary search not speed it up?
    Answer

    O(n), with n comparisons in the worst case. Binary search needs to jump to the middle element in O(1), but a linked list can only be walked node by node from the head.

  4. Write the idea of an algorithm to check whether a singly linked list has a loop.
    Answer

    Floyd's method: start two pointers at the head; each step move slow by one node and fast by two. If fast (or fast->next) becomes NULL there is no loop; if slow and fast ever point to the same node there is a loop. It runs in O(n) time with O(1) extra memory.

  5. How many bytes does the C declaration char name[] = "BANGLADESH"; reserve, and what does strlen(name) return?
    Answer

    11 bytes (10 letters plus the terminating '\0'); strlen returns 10.

Asked in past exams · আগের পরীক্ষায় যেভাবে এসেছে

Our past papers have 51 questions on this topic (22 MCQ, 29 written) from 35 exams. Here are 12 of them; each links to its full paper.

  1. Explain with proper example of singly linked list.

    Model answer on the paper page

  2. The minimum number of fields in each node of a doubly linked list is

    • a)1
    • b)2
    • c)3 (correct answer)
    • d)4
    Explanation · ব্যাখ্যা

    Correct answer: (c) 3

    Each node of a doubly linked list must be able to move both forward and backward, so it needs at least:

    1. data: the value stored in the node
    2. prev: a pointer to the previous node
    3. next: a pointer to the next node

    That makes 3 fields.

    Why the other options are wrong

    • (a) 1: Data alone gives no links at all, so there would be no list.
    • (b) 2: Data plus one link is a singly linked list node, which can move in only one direction.
    • (d) 4: A fourth field (for example a key alongside the data) is optional and not part of the minimum.

    Tip: Minimum fields: singly linked list = 2 (data, next) and doubly linked list = 3 (prev, data, next).

    Source: Problem Session 2 - 6.006 Introduction to Algorithms, MIT OpenCourseWare (Spring 2020)

  3. (a) Compare array and linked list with necessary diagram.

    Model answer on the paper page

  4. What is the access methodology in array?

    • a)Sequential
    • b)Random (correct answer)
    • c)Rational
    • d)Stochastic
    Explanation · ব্যাখ্যা

    Correct answer: (b) Random

    An array keeps its elements in one contiguous block of memory, and every element has the same size. The address of element i is therefore computed in one step: address = base address + i × element size. Any element can be read or written in O(1) time without visiting the elements before it. This is called random (direct) access.

    Why the other options are wrong

    • (a) Sequential: this is how a linked list or a tape file is accessed, where you must pass through the earlier items first. An array can be scanned in order, but that is not its defining access method.
    • (c) Rational: not an access method at all; the word belongs to numbers (rational numbers), not to data access.
    • (d) Stochastic: means governed by probability; it is not a term used for accessing data in a structure.

    Tip: Array → random access by index, O(1). Linked list → sequential access, O(n).

    Source: Arrays (C++) | Microsoft Learn

  5. Two dimensional arrays are also called?

    • a)table array
    • b)matrix array
    • c)both A and B (correct answer)
    • d)none of the above
    Explanation · ব্যাখ্যা

    Correct answer: (c) both A and B

    A two-dimensional array stores its elements in rows and columns: A[i][j] is the element in row i, column j. That layout is exactly a mathematical matrix, and it is also a table of rows and columns (for example, a marks sheet with students as rows and subjects as columns). So a 2-D array is commonly called both a matrix array and a table array. Microsoft's C++ documentation describes int i2[5][7] as conceptually a two-dimensional matrix of 5 rows and 7 columns, and Visual Basic documentation also calls it a rectangular array.

    Why the other options are wrong

    • (a) table array: a correct name, but only one of the two; option (c) covers it.
    • (b) matrix array: also correct, but again only half the answer.
    • (d) none of the above: wrong, because both names are used for 2-D arrays.

    Tip: 1-D array ↔ list/vector; 2-D array ↔ matrix/table (rows × columns).

    Source: Arrays (C++) | Microsoft Learn; Array Dimensions — Visual Basic | Microsoft Learn

  6. In an array-based implementation of a complete binary tree, what is the index of the left child of a node at index i (assuming zero-based indexing)?

  7. What is the worst case time complexity of inserting n elements into an empty linked list, if the linked list needs to be maintained in sorted order?

  8. (ক) Linked list কী? উহার প্রকারভেদ চিত্রসহ বর্ণনা করুন।

  9. (a) What are differences between Breadth first search (BFS) and Depth first search (DFS)? For what sort of problems it is better to use BFS than DFS?

  10. You are given a binary tree (a, b, c, d, e, f, g, h, i) nodes. The post order of the binary tree is: a b f c h d e g i nodes. Now draw the binary tree and show the array representation of this binary tree.

  11. Consider the two given arrays as pre[]={1,2,4,8,9,5,3,6,7} and post[]={8,9,4,5,2,6,7,3,1}; Draw a binary tree from above array.

  12. Algorithm for checking loop in singly linked list.

Common mistakes · সাধারণ ভুল

  • Multiplying by the wrong count in 2-D addresses: row-major uses the number of columns, column-major the number of rows.
  • Forgetting to subtract the lower bound when the array does not start at 0 (and miscounting elements: UB − LB + 1).
  • Saying linked-list access is O(1) or that binary search works on a linked list: access is sequential, O(n).
  • Calling linked-list insertion O(1) without the condition: it is O(1) only once you hold the node; finding the position is O(n).
  • Forgetting the '\0' byte of a C string, so sizeof is one more than strlen.
  • Mixing up 0-based (2i + 1, 2i + 2) and 1-based (2i, 2i + 1) child indices in the array form of a tree.

বাংলায় সংক্ষেপে

  • অ্যারে একই টাইপের উপাদান পাশাপাশি মেমোরিতে রাখে; সরাসরি অ্যাক্সেস (random access) পাওয়া যায়, O(১)। উপাদান সংখ্যা = UB − LB + ১।
  • এক মাত্রায় অ্যাড্রেস = B + w × (i − LB)।
  • রো-মেজরে A[i][j] = B + w × [(i − LB₁) × কলাম সংখ্যা + (j − LB₂)]; কলাম-মেজরে = B + w × [(j − LB₂) × সারি সংখ্যা + (i − LB₁)]।
  • সি-তে স্ট্রিং '\0' দিয়ে শেষ হয়, তাই "DHAKA"-এর জন্য ৬ বাইট লাগে কিন্তু strlen দেয় ৫।
  • সিঙ্গলি লিংকড লিস্টের নোডে ২টি ফিল্ড, ডাবলি লিংকড লিস্টে অন্তত ৩টি (prev, data, next); সার্কুলার লিস্টের শেষ নোড প্রথম নোডকে নির্দেশ করে।
  • লিংকড লিস্টে সার্চ ও k-তম উপাদানে যাওয়া O(n), শুরুতে ইনসার্ট O(১); সাজানো ক্রম বজায় রেখে একে একে n টি উপাদান ইনসার্ট করতে সবচেয়ে খারাপ ক্ষেত্রে Θ(n²) সময় লাগে।
  • লুপ শনাক্ত করতে ফ্লয়েডের পদ্ধতি: ধীর পয়েন্টার এক ধাপ, দ্রুত পয়েন্টার দুই ধাপ; দুটি মিলে গেলে লুপ আছে।

Updated 2026-10-18. Written by ARBS Academy; the past exam questions are from public recruitment exams.