Arrays: Static, Dynamic & Multi-dimensional
অ্যারে — static, dynamic, multi-dim
1. Why Arrays — The Original Data Structure
An array is the simplest and most fundamental data structure in computer science. It is a contiguous block of memory holding elements of the same type. Because the elements sit side-by-side, the CPU can compute the address of element i with a single multiplication — giving us O(1) random access, the property every other data structure envies.
vector যখন capacity শেষ করে double করে — তখন প্রতিটি push_back amortised O(1)।
2. Memory Layout — How an Array Lives in RAM
Suppose you declare int a[6]; and the compiler places it at address 0x1000.
Each int occupies 4 bytes, so element a[i] sits at
0x1000 + i × 4. The CPU can jump straight to it — no scan, no pointer chase.
int a[6]; declare করলেন এবং compiler array-টি 0x1000 address-এ বসালো। প্রতিটি int 4 byte নেয়, তাই a[i] থাকবে 0x1000 + i × 4 address-এ। CPU সরাসরি সেই জায়গায় চলে যেতে পারে — কোনো খোঁজাখুঁজি লাগে না।
a[6] in the array above is out-of-bounds. C++ does not check; you may read garbage, crash, or worse — silently corrupt unrelated data. সতর্কতা: উপরের array-তে
a[6] পড়লে out-of-bounds হবে। C++ check করে না — আপনি garbage পেতে পারেন, crash করতে পারে, এমনকি অন্য data নষ্ট হতে পারে।
3. Static vs Dynamic — Two Flavours
A static array (int a[100];) has a fixed size known at compile time.
A dynamic array (std::vector<int>) can grow at runtime.
How does vector grow? It allocates a bigger buffer, copies the old elements,
then frees the old one — typically doubling capacity each time. This doubling trick
is what makes push_back amortised O(1).
int a[100];)। Dynamic array (std::vector) runtime-এ বড় হতে পারে। কিভাবে? আগের চেয়ে বড় একটি buffer allocate করে পুরনো element-গুলো copy করে, পুরনোটিকে free করে দেয়। সাধারণত capacity প্রতিবার দ্বিগুণ করা হয় — এই doubling কৌশলই push_back-কে amortised O(1) রাখে।
4. Demo 1 — Build Your Own Dynamic Array
Let's implement a tiny DynArr that doubles its capacity on every overflow.
This is essentially what std::vector does under the hood.
DynArr বানাই, যেটি capacity শেষ হলে নিজেকে দ্বিগুণ করে। std::vector ভেতরে ভেতরে এটিই করে।
#include <bits/stdc++.h>
using namespace std;
struct DynArr {
int* data;
int sz, cap;
DynArr() { cap = 1; sz = 0; data = new int[cap]; }
void push_back(int x) {
if (sz == cap) {
cap *= 2;
int* nd = new int[cap];
for (int i = 0; i < sz; i++) nd[i] = data[i];
delete[] data;
data = nd;
}
data[sz++] = x;
}
int get(int i) { return data[i]; }
};
int main() {
DynArr a;
for (int i = 1; i <= 10; i++) a.push_back(i * i);
cout << "size = " << a.sz << ", capacity = " << a.cap << "\n";
for (int i = 0; i < a.sz; i++) cout << a.get(i) << " ";
cout << "\n";
return 0;
}
সারমর্ম: n element insert করতে সর্বোচ্চ ~2n copy লাগে — তাই গড়ে প্রতিটি insert O(1)।
5. Demo 2 — Rotate an Array Left by k
Given an array [1,2,3,4,5,6,7] and k=3, the result should be [4,5,6,7,1,2,3].
The clever three-reverse trick does it in O(n) time and O(1) extra space.
[1,2,3,4,5,6,7] এবং k=3 দিলে output হবে [4,5,6,7,1,2,3]। তিনবার reverse-এর কৌশলে এটি O(n) সময়ে এবং O(1) extra space-এ করা যায়: প্রথম k element reverse → বাকি n-k reverse → পুরো array reverse।
#include <bits/stdc++.h>
using namespace std;
void rev(vector<int>& a, int l, int r) {
while (l < r) swap(a[l++], a[r--]);
}
void rotateLeft(vector<int>& a, int k) {
int n = a.size();
k %= n;
rev(a, 0, k - 1);
rev(a, k, n - 1);
rev(a, 0, n - 1);
}
int main() {
vector<int> a = {1,2,3,4,5,6,7};
rotateLeft(a, 3);
for (int x : a) cout << x << " ";
cout << "\n";
return 0;
}
6. 2D Arrays & Matrices
A 2D array is just a 1D array laid out row-by-row in memory (row-major order in C/C++).
int m[3][4] takes 3 × 4 × 4 = 48 bytes; element m[i][j] sits at
base + (i × 4 + j) × 4.
m[i][j]-এর ঠিকানা = base + (i × cols + j) × sizeof(elem)। তাই matrix traversal-এ row-by-row লুপ করলে CPU cache অনেক বেশি hit করে — অনেক দ্রুত চলে।
| Operation | Static array | std::vector |
|---|---|---|
| Access by index | O(1) | O(1) |
| Insert at end | — | amortised O(1) |
| Insert at middle | — | O(n) |
| Erase at end | — | O(1) |
| Erase at middle | — | O(n) |
| Search (unsorted) | O(n) | O(n) |
7. Common Bugs & Pitfalls
✅ Best Practice
- Always check
i < nbeforea[i] - Use
vector::at()while debugging — it throws on OOB - Reserve capacity (
v.reserve(n)) when n is known - Pass large arrays by reference, never by value
⚠️ Mistakes to Avoid
- Off-by-one:
for(i=0;i<=n;i++) - Reading
a[n]after a loop ends - Using
sizeof(arr)/sizeof(arr[0])on a function parameter - Forgetting that
vectormay invalidate iterators on growth
vector reallocations inside an inner loop. Always v.reserve(n) for hot paths.
8. Practice Problems
Try each problem first, then click Show Answer to compare with a runnable solution.
-
Find the maximum subarray sum using the naive O(n²) approach.Naive O(n²) পদ্ধতিতে maximum subarray sum বের করুন।
✨ Show Answer (উত্তর দেখুন)
ans1.cpp#include <bits/stdc++.h> using namespace std; int main() { vector<int> a = {-2,1,-3,4,-1,2,1,-5,4}; int n = a.size(), best = INT_MIN; for (int i = 0; i < n; i++) { int s = 0; for (int j = i; j < n; j++) { s += a[j]; best = max(best, s); } } cout << best << "\n"; } -
Reverse an array in-place using two pointers.Two-pointer পদ্ধতিতে in-place একটি array reverse করুন।
✨ Show Answer (উত্তর দেখুন)
ans2.cpp#include <bits/stdc++.h> using namespace std; int main() { vector<int> a = {1,2,3,4,5}; int l = 0, r = a.size() - 1; while (l < r) swap(a[l++], a[r--]); for (int x : a) cout << x << " "; cout << "\n"; } -
Rotate an array right by k positions in O(n) time and O(1) space.O(n) সময় ও O(1) space-এ array-কে ডানে k বার rotate করুন।
✨ Show Answer (উত্তর দেখুন)
ans3.cpp#include <bits/stdc++.h> using namespace std; void rev(vector<int>& a,int l,int r){while(l<r) swap(a[l++],a[r--]);} int main() { vector<int> a = {1,2,3,4,5,6,7}; int n = a.size(), k = 3 % n; rev(a,0,n-1); rev(a,0,k-1); rev(a,k,n-1); for (int x : a) cout << x << " "; cout << "\n"; } -
Print a 2D matrix in spiral order.2D matrix-কে spiral order-এ print করুন।
✨ Show Answer (উত্তর দেখুন)
ans4.cpp#include <bits/stdc++.h> using namespace std; int main() { vector<vector<int>> m = {{1,2,3},{4,5,6},{7,8,9}}; int top=0, bot=m.size()-1, lt=0, rt=m[0].size()-1; while (top <= bot && lt <= rt) { for (int j=lt;j<=rt;j++) cout << m[top][j] << " "; top++; for (int i=top;i<=bot;i++) cout << m[i][rt] << " "; rt--; if (top <= bot) { for (int j=rt;j>=lt;j--) cout << m[bot][j] << " "; bot--; } if (lt <= rt) { for (int i=bot;i>=top;i--) cout << m[i][lt] << " "; lt++; } } cout << "\n"; } -
Find the second largest element in a single pass.Array-এ একবার ঘুরেই দ্বিতীয় সর্বোচ্চ element বের করুন।
✨ Show Answer (উত্তর দেখুন)
ans5.cpp#include <bits/stdc++.h> using namespace std; int main() { vector<int> a = {12,35,1,10,34,35,1}; int first = INT_MIN, second = INT_MIN; for (int x : a) { if (x > first) { second = first; first = x; } else if (x > second && x < first) second = x; } cout << second << "\n"; } -
Move all zeros to the end of the array, preserving order of non-zeros, in O(n).Array-এর সব 0-কে শেষে সরান (non-zero-দের আপেক্ষিক order বজায় রেখে), O(n)-এ।
✨ Show Answer (উত্তর দেখুন)
ans6.cpp#include <bits/stdc++.h> using namespace std; int main() { vector<int> a = {0,1,0,3,12}; int j = 0; for (int i = 0; i < (int)a.size(); i++) if (a[i] != 0) swap(a[i], a[j++]); for (int x : a) cout << x << " "; cout << "\n"; } -
Given two sorted arrays, merge them into a single sorted array.দুটি sorted array-কে merge করে একটি sorted array বানান।
✨ Show Answer (উত্তর দেখুন)
ans7.cpp#include <bits/stdc++.h> using namespace std; int main() { vector<int> a = {1,3,5,7}, b = {2,4,6,8,10}; vector<int> c; int i=0, j=0; while (i < (int)a.size() && j < (int)b.size()) { if (a[i] <= b[j]) c.push_back(a[i++]); else c.push_back(b[j++]); } while (i < (int)a.size()) c.push_back(a[i++]); while (j < (int)b.size()) c.push_back(b[j++]); for (int x : c) cout << x << " "; cout << "\n"; }
Summary — Module 06
Arrays are contiguous blocks of memory that give us O(1) random access. Static arrays have a fixed
compile-time size; dynamic arrays like std::vector grow by doubling capacity, making
push_back amortised O(1). 2D arrays are stored row-major in C/C++.
Watch for off-by-one and out-of-bounds bugs — they cause more crashes in CSE Bangladesh contests
than any other class of mistake.
std::vector capacity দ্বিগুণ করে বড় হয়, ফলে push_back amortised O(1)। 2D array C/C++-এ row-major-এ থাকে। off-by-one এবং out-of-bounds bug আজকের ICPC Dhaka contest-এ সবচেয়ে বেশি crash ঘটায় — সাবধান।