Problem solving in programming is the ability to understand a problem, break it into smaller parts, choose the right logic and data structures, and convert that logic into efficient code.
Coding is not about typing syntax. Coding is about thinking, decision-making, and optimization.
A strong problem solver follows a clear mental process:
Problem: Given an array, find the maximum element.
Thinking process:
int max = arr[0];
for(int i = 1; i < n; i++){
if(arr[i] > max){
max = arr[i];
}
}
This solution is simple, efficient, and scalable.
Time and space complexity help us understand how an algorithm behaves as input size grows. In competitive programming and interviews, inefficient solutions often fail due to time limit exceeded (TLE) or memory limit exceeded (MLE).
Time complexity measures how execution time increases with input size n.
Big-O represents the maximum time an algorithm may take.
Example: Linear Search
for(int i = 0; i < n; i++){
if(arr[i] == key) return i;
}
Worst case: element found at the last index
Time Complexity: O(n)
Big-Ω represents the minimum time required.
Example: Key found at index 0
Time Complexity: Ω(1)
Big-Θ represents the tight bound, showing average performance.
Example: Element found in the middle
Time Complexity: Θ(n)
Space complexity measures memory usage, including variables, arrays, and recursion stack.
Example:
int a = 10; // O(1)
int[] arr = new int[n]; // O(n)
Worst-case analysis ensures the solution won’t fail under extreme conditions. Best case shows potential efficiency. Average case reflects real-world performance.
Recursion is a technique where a function calls itself to solve a smaller version of the same problem.
int factorial(int n){
if(n == 0) return 1;
return n * factorial(n - 1);
}
You trust the function to solve smaller inputs and focus on combining results.
Each recursive call occupies stack memory.
Factorial time complexity: O(n)
Factorial space complexity: O(n) due to recursion stack
Mathematics helps reduce brute-force solutions, optimize loops, and handle large constraints efficiently.
Brute force approach:
int sum = 0;
for(int i = 1; i <= n; i++){
sum += i;
}
Time complexity: O(n)
Optimized approach:
int sum = n * (n + 1) / 2;
Time complexity: O(1)
if((n & 1) == 0){
System.out.println("Even");
}
Competitive programming often involves large input sizes. Slow input/output methods can cause TLE even with correct logic.
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String[] input = br.readLine().split(" ");
StringBuilder sb = new StringBuilder();
sb.append(result);
System.out.print(sb);
int n = Integer.parseInt(br.readLine());
String[] arr = br.readLine().split(" ");
Constraints tell you which algorithm is feasible and which will fail.
If n = 10⁵
O(n²) will fail
O(n log n) will pass
prefix[i] = prefix[i - 1] + arr[i];