Arrays
An array is a data structure that can hold a fixed number of elements, all of the same type. It is like a collection or a list where each element has a specific position or index. The elements in an array are stored in contiguous memory locations, meaning they are placed one after the other in the computer's memory.
Arrays are used to store and organize related data, such as a list of numbers, names, or any other type of information. The index of an element in an array represents its position, starting from zero for the first element, then one for the second, and so on.

Properties of Arrays:
- Fixed Size: Arrays have a fixed size, meaning they can hold a specific number of elements. Once an array is created, its size cannot be changed dynamically. You need to define the size of an array before using it.
- Ordered Elements: Elements in an array are ordered, which means they have a specific position or index. The order of elements is typically based on their insertion into the array.
- Indexing: Each element in an array can be accessed using its index. The index represents the element's position in the array, starting from zero for the first element. For example, the first element of an array is accessed using index 0, the second element with index 1, and so on.
- Homogeneous Elements: Arrays store elements of the same type. This means that all elements in an array must have the same data type, such as integers, floating-point numbers, characters, or custom objects.
- Random Access: Arrays allow for efficient random access to elements. Since elements are stored in contiguous memory locations, accessing an element by its index is a constant-time operation. This means that regardless of the size of the array, accessing any element takes the same amount of time.
- Iterating: It is easy to iterate over all the elements in an array using loops. By using a loop, you can sequentially access each element of the array and perform operations on them.
- Memory Efficiency: Arrays are memory-efficient because they store elements in a contiguous block of memory. This makes them suitable for situations where direct and efficient memory access is required.
- Mutability: The elements of an array can be modified, added, or removed. You can change the value of an element by assigning a new value to its corresponding index.
Where can arrays be used?
- Arrays should be used when the number of elementsto be stored is already known.
- Arrays are commonly used in computer programs to organize data so that a related set of values canbe easily sorted or searched.
- Generally, when we require very fast access times,we usually prefer arrays since they provide O(1) access times.
- Arrays work well when we have to organize data in multidimensional format. We can declare arrays of as many dimensions as we want.
- If the index of the element to be modified is known before hand, it can be efficiently modified using arrays due to quick access time and mutability.
Disadvantages of arrays
- Fixed Size: Arrays have a fixed size, meaning that once you define the size of an array, it cannot be easily changed. If you need to store more elements than the predefined size, you would have to create a new, larger array and copy the elements from the old array to the new one. This can be inefficient and time-consuming.
- Wasted Memory: Arrays may waste memory if they are not fully utilized. Since arrays have a fixed size, if you allocate an array with a larger size than necessary, you may end up with unused or empty elements. This can lead to inefficient memory usage.
- Insertion and Deletion: Inserting or deleting elements in an array can be inefficient. If you want to insert an element at the beginning or middle of an array, you would need to shift all the subsequent elements to make space. Similarly, deleting an element would require shifting all the elements after it. These operations can be time-consuming, especially for large arrays.
- Contiguous Memory Requirement: Arrays require contiguous memory locations to store elements. This means that if there is no continuous block of memory available to accommodate the array's size, creating an array can fail. In situations where memory fragmentation occurs or when working with large arrays, finding a contiguous block of memory can be a challenge.
- Lack of Flexibility: Arrays are not very flexible in terms of accommodating different data types or changing data sizes. As mentioned earlier, arrays can only store elements of the same type, and their size is fixed. If you need to store different types of data or have dynamic sizing requirements, other data structures like lists or dynamic arrays may be more suitable.
Time Complexity of various Operations
- Accessing an Element: O(1) - Constant time complexity. Accessing an element in an array by its index takes the same amount of time, regardless of the size of the array.
- Searching: O(n) - Linear time complexity. In the worst case, you may need to iterate through the entire array to find the desired element. The time it takes to search grows linearly with the size of the array.
- Insertion/Deletion at the End: O(1) - Constant time complexity. If you are inserting/deleting an element at the end of the array, it can be done in constant time since you know the index where the new element should go.
- Insertion/Deletion at the Beginning: O(n) - Linear time complexity. If you insert or delete an element at the beginning of an array, all the subsequent elements need to be shifted to accommodate the change. This requires iterating through and shifting elements, resulting in a time complexity that grows linearly with the size of the array.
- Insertion/Deletion in the Middle: O(n) - Linear time complexity. Similar to insertion/deletion at the beginning, inserting or deleting an element in the middle of an array requires shifting subsequent elements. This operation also has a time complexity that grows linearly with the size of the array.
- Appending: O(1) amortized - When appending elements to an array, the time complexity is usually considered amortized O(1). This means that although occasional reallocations and copying of the array may occur to accommodate a larger size, on average, the time complexity of appending elements remains constant.
- Sorting: O(n log n) - The most efficient sorting algorithms have a time complexity of O(n log n) when sorting an entire array. Examples of such algorithms include quicksort, mergesort, and heapsort. However, some specialized sorting algorithms, like counting sort or radix sort, can achieve better time complexities for specific data distributions or constraints.
arrayPractice.py
Top 50 Array Coding Problems for Interviews
Kadane’s Algorithm
Let's break down the Kadane's algorithm step by step in a way that is easy to understand:
- Step 1: Understanding the Problem
Kadane's algorithm is used to find the maximum sum of a subarray within a given array of numbers. A subarray is a contiguous (continuous) portion of the original array.
- Step 2: Starting with a Simple Example
Let's take a simple example to illustrate the algorithm. Consider the following array of numbers:
[1, -3, 4, 2, -1, 6, -2]
- Step 3: Initialization
Start by initializing two variables:
currentSum and maxSum. Set both of them to the value of the first element in the array. In our example, currentSum and maxSum will be initialized to 1.
- Step 4: Iterating through the Array
Now, we will iterate through the array from the second element (index 1) to the last element. For each element, we perform the following steps:
- Add the current element to the
currentSum. If the result is greater than the current element itself, update currentSum to the new value. Otherwise, keep the current element as the new currentSum.
- Compare
currentSum with maxSum. If currentSum is greater than maxSum, update maxSum to the value of currentSum. Otherwise, keep maxSum unchanged.
Let's go through the steps for our example:
-
Iteration 1:
- currentSum + current element (1 + (-3)) = -2
- Since -2 is less than the current element (-3), we update currentSum to -3.
- maxSum remains unchanged at 1.
-
Iteration 2:
- currentSum + current element (-3 + 4) = 1
- Since 1 is greater than the current element (4), we update currentSum to 1.
- maxSum remains unchanged at 1.
-
Iteration 3:
- currentSum + current element (1 + 2) = 3
- Since 3 is greater than the current maxSum (1), we update maxSum to 3.
- currentSum remains unchanged at 3.
-
Iteration 4:
- currentSum + current element (3 + (-1)) = 2
- Since 2 is greater than the current element (-1), we update currentSum to 2.
- maxSum remains unchanged at 3.
-
Iteration 5:
- currentSum + current element (2 + 6) = 8
- Since 8 is greater than the current maxSum (3), we update maxSum to 8.
- currentSum remains unchanged at 8.
-
Iteration 6:
- currentSum + current element (8 + (-2)) = 6
- Since 6 is greater than the current element (-2), we update currentSum to 6.
- maxSum remains unchanged at 8.
-
Step 5: Returning the Result
After iterating through the entire array, the value of maxSum will be the maximum sum of a subarray within the given array. In our example, the maximum sum is 8, which corresponds to the subarray [4, 2, -1, 6].
So, the result of applying Kadane's algorithm to the array [1, -3, 4, 2, -1, 6, -2] is 8, which represents the maximum sum of a subarray.
That's it! Kadane's algorithm is a simple yet effective technique to solve the maximum subarray sum problem.
What are some easy to hard level problems where we can use kadane's algorithms?
Kadane's algorithm is commonly used to solve a variety of problems related to finding the maximum subarray sum. Here are some examples of problems of varying difficulty levels where Kadane's algorithm can be applied:
-
Easy Level:
-
Maximum Subarray Sum: Given an array of integers, find the maximum sum of any contiguous subarray. (This is the classic problem that Kadane's algorithm is designed to solve.)
def maxSubarraySum(arr, n) :
sum = max_sum = 0
if n == 0:
return 0
for i in arr:
sum += i
if sum < 0:
sum = 0
max_sum = max(max_sum,sum)
return max_sum
-
Maximum Product Subarray: Given an array of integers, find the maximum product of any contiguous subarray.
-
Flip Bits: You are given an array of integers ARR[] of size N consisting of zeros and ones. You have to select a subset and flip bits of that subset. You have to return the count of maximum one’s that you can obtain by flipping chosen sub-array at most once.
def flipBits(arr, n):
count = 0
for i in range(n):
if arr[i] == 1:
arr[i] = -1
count +=1
else:
arr[i] = 1
return count + maxsum(arr)
def maxsum(arr):
cursum = maxsum = 0
for i in arr:
cursum +=i
if cursum<0:
cursum = 0
maxsum = max(maxsum, cursum)
return max(maxsum,0)
-
Medium Level:
-
Hard Level:
These are just a few examples to give you an idea of the types of problems where Kadane's algorithm can be applied. However, there are many other variations and extensions of the problem that require different approaches or modifications to Kadane's algorithm.