Solving Array Coding Problems
Solving Array coding problems with explanation
1. Question list
- Subarray with given sum G4G, Leetcode
Easy
Google
- Missing number in array G4G Leetcode
Easy
- Sorting an array containing 0’s, 1’s and 2’s G4G Techie
Easy
- Product of array except self G4G Leetcode
Medium
- Find triplets with zero sum G4G Leetcode
Medium
todo - Rotate array G4G Leetcode
Medium
todo - Find All Duplicates in an Array G4G Leetcode
Medium
todo - K’th smallest/largest element G4G Leetcode Techie
Medium
todo - In place merge two sorted arrays G4G Leetcode Techie
Medium
todo - Maximum sum increasing subsequence G4G
Medium
DP
todo
2. C++ Implementation
Subarray with given sum
Given an unsorted array A of size N of non-negative integers, find a continuous sub-array that adds to a given number.
void subArraySum(int a[], int n, int val){
int start = 0, end = 0, sum = 0;
for(int i = 0; i < n; i++){
end = i;
sum += a[i];
while(sum > val && start < n){
sum -= a[start];
start++;
}
if(sum == val){
cout << start + 1 << " " << end + 1 << endl;
return;
}
}
cout << -1 << endl;
}
- Explanation
- The number of subarrays is uncertain, so we use start and end to track the indices.
- When the current
sum > target
, we keep subtracting the number from num from the beginning. - Time complexity looks more than O(n), but if we take a closer look at the program, then we can figure out the time complexity is O(n). We can prove it by counting the number of operations performed on every element of a[] in the worst case. There are at most 2 operations performed on every element: (a) the element is added to the sum (b) the element is subtracted from the sum. So the upper bound on the number of operations is 2n which is O(n).
- The above solution doesn’t handle negative numbers. We can use hashing to handle negative numbers.
Given an array of integers, return indices of the two numbers such that they add up to a specific target. You may assume that each input would have exactly one solution, and you may not use the same element twice.
vector<int> twoSum(vector<int>& nums, int target) {
unordered_map <int, int> map;
vector <int> result;
for(int i = 0; i < nums.size(); i++){
if (map.end() != map.find(target-nums[i])){
result.push_back(map[target-nums[i]]);
result.push_back(i);
}else{
map[nums[i]] = i;
}
}
return result;
}
- Explanation
- We need to output the indices of two numbers (may not be continuous), use the hash to store the index and the value (note that the key of the map is the value of the element, the value of the map is the index of that element).
- For each element, we first check if there is an element in the hash table that adds the current element up to the target value, if not, we store the info in the table.
- As finding an element in the hash table takes constant time, this implementation gives us time complexity of O(n) as we only need to go through each element once.
Missing number in array
Given an array containing n distinct numbers taken from 0, 1, 2, ..., n
, find the one that is missing from the array.
int missingNumber(vector<int>& nums) {
int sum = 0;
int n = nums.size();
sum = n*(n+1)/2;
for (auto i: nums){
sum -= i;
}
return sum;
}
- Explanation
- The array contains continuously increasing numbers, we can calculate the sum of these numbers (suppose no missing number) first, then subtracts each element in the array to get the missing number.
- Use
n*(n+1)/2
to improve efficiency
Sorting an array containing 0’s, 1’s and 2’s
Given an array A[] consisting of 0s, 1s and 2s, write a function that sorts A[]. The functions should put all 0s first, then all 1s and all 2s in last.
- Easy solution (count sort)
We count the number of 0’s, 1’s, and 2’s and then put them in the array in their correct order, time complexity is O(n) but it requires two traversals of the array.
2. Similar to 3-way partitioning for Dutch national flag problem
void sort012(int a[], int n){
int lo = 0, mid = 0;
hi = n - 1;
while(mid <= hi){ // track mid as current element
if(a[mid] == 0)
swap(&a[lo++], &a[mid++]);//ele<=mid are sorted, so mid++
else if (a[mid] == 1)
mid++;
else if (a[mid] == 2)
swap(&a[mid], &a[hi--]);
}
}
- Explanation
- Separate the value into 3 groups, i.e: less than 1, equal to 1, and greater than 1.
- Track iterate elements with index
mid
,lo
for those less than 1 andhi
for those greater than 1. - When the value is less than 1, means we found an element for
lo
, we swap the value and increase bothlo
andmid
. If the value is 1, we simply increase the index, if the value is 2, we need to swap the current value with thehi
one. - The elements with an index less than
mid
can be either 0 or 1, while the elements with an index greater thanmid
can be 0, 1, or 2. Thus the loop condition ismid≤hi
as there is a chance the element of indexmid
andhi
can be 0, which needs to be swapped, see example below (step 5).
array: 0 1 2 2 0 1
init: lo = 0, mid = 0, hi = 5
step 1: 0 1 2 2 0 1, lo = 1, mid = 1, hi = 5
step 2: 0 1 2 2 0 1, lo = 1, mid = 2, hi = 5
step 3: 0 1 1 2 0 2, lo = 1, mid = 2, hi = 4
step 4: 0 1 1 2 0 2, lo = 1, mid = 3, hi = 4
step 5: 0 1 1 0 2 2, lo = 1, mid = 3, hi = 3
step 6: 0 0 1 1 2 2, lo = 2, mid = 4, hi = 3
Product of array except self
Given an array nums
of n integers where n > 1, return an array output
such that output[i]
is equal to the product of all the elements of nums
except nums[i]
.
Input: [1,2,3,4]
Output: [24,12,8,6]
2x3x4, 1x3x4, 1x2x4, 1x2x3vector<int> productExceptSelf(vector<int>& nums) {
vector<int> res;
int product = 1;
for(int i = 0; i < nums.size(); i++){
res.push_back(product);
product *= nums[i];
}
product = 1;
for(int i = nums.size()-1; i >= 0; i--){
res[i] *= product;
product *= nums[i];
}
return res;
}
- Explanation
- First store the values contains the product of all elements on left of nums[i] excluding nums[i].
- Then calculate the values contains the product of all elements on the right of nums[i] excluding nums[i].
- For instance, in the first loop, when i is 0, we only store 1 in the result as we should calculate the product of the elements on the right of nums[0]. i.e.
res[0] = nums[1]*nums[2]…*nums[n-1]
. - It may require to check the case where the number of elements is 0 or 1.
- Where I got stuck
- I could only implement it with a brute force solution in the beginning.
- The key to improving it is to observe how the products are calculated for each element and try to solve it with O(n) time.
For more array questions, see Leetcode, G4G, and Techie Delight.