I was solving one problem and it stated that we need to find the sum of all minimum number that needs to be added to the elements in the array so that the bitwise AND is greater than 0.
For eg: Given array is [4, 4, 3, 2]
then the output should be 3
(adding one to 1st 2nd and 4th element).
My approach : first I decided to find the position of the right most set in all elements and check for the overall minimum number to be added so that the and is greater than zero. But this is not working.Can anyone help in finding an alternative algo?
Let's solve a bit different problem first:
What minimum min number should be add to value to ensure 1 in kth position (zero based)?
We have two cases here:
if value has 1 at k position we add 0 (do nothing);
if value has 0 at k position we can add
min = 100...000000000 - (value & 11.....11111)
<- k zeroes -> <- k ones ->
Code (C#)
private static long AddToEnsureOne(long value, int position) {
if ((value & (1L << position)) != 0)
return 0;
long shift = 1L << (position);
return shift - (value & (shift - 1));
}
Demo: if we have 3 and we want 1 at 2nd position
0b011
^
we want 1 here
we should add
0b100 - (0b011 & 0b11) == 4 - 3 == 1
let's add: 3 + 1 == 4 == 0b100 which has 1 at 2nd position
Now we can scan all 32 positions (if integer is good old 32 bit integer int); C# code:
private static long MinToAdd(IEnumerable<int> items) {
long best = 0;
for (int i = 0; i < 32; ++i) {
long sum = 0;
foreach (int item in items)
sum += AddToEnsureOne(unchecked((uint)item), i); // uint - get rid of sign
if (i == 0 || sum < best)
best = sum;
}
return best;
}
One can improve the solution looping not for 32 positions but for the leftmost 1 of the maximum item. Here we have 4 as the maximum, which is 0b100, the leftmost 1 is in the 2 position; thus for (int i = 0; i <= 2; ++i) will be enough in the context
Simple test:
Console.Write(MinToAdd(new int[] { 4, 4, 3, 2}));
Outcome:
3
// A Dynamic programming based C++ program to find number of
// non-negative solutions for a given linear equation
#include<bits/stdc++.h>
using namespace std;
// Returns counr of solutions for given rhs and coefficients
// coeff[0..n-1]
int countSol(int coeff[], int n, int rhs)
{
// Create and initialize a table to store results of
// subproblems
int dp[rhs+1];
memset(dp, 0, sizeof(dp));
dp[0] = 1;
// Fill table in bottom up manner
for (int i=0; i<n; i++)
for (int j=coeff[i]; j<=rhs; j++)
dp[j] += dp[j-coeff[i]];
return dp[rhs];
}
// Driver program
int main()
{
int coeff[] = {2, 2, 5};
int rhs = 4;
int n = sizeof(coeff)/sizeof(coeff[0]);
cout << countSol(coeff, n, rhs);
return 0;
}
I am new to competitive programming, I just stumbled upon this code. I would like to know the intuition behind this particular snippet, like how does the second for loop help. Thank you.
// Fill table in bottom up manner
for (int i=0; i<n; i++)
for (int j=coeff[i]; j<=rhs; j++)
dp[j] += dp[j-coeff[i]];
This is using a bottom up approach, and
Suppose if j= 3 and j-coeff[i] = 2
so how does d[3] = d[3] + d[2] give the solution? How can a simple addition of a previous result and a current result give the total solution of linear variables?
Imagine that you have unlimited number of coins with value 2,3,5 (your coeff[]) and you want to know number of solutions to make some sum form give coin set.
At the first loop run you fill table with coins 2. Table will be filled
idx 0 1 2 3 4 5 6
num 1 0 1 0 1 0 1
because there is the only way to get even sum with such coins.
At the second loop run you fill table with coins 3 - now you'll have sums that might be composed from coins 2 and 3
idx 0 1 2 3 4 5 6
num 1 0 1 1 1 1 2
Note that cell 5 filled with 2+3 - similar to your question situation, and cell 6 now contains 2 variants: 2+2+2 and 3+3
I recently encountered this problem in an interview
There are n stairs, a person standing at the bottom wants to reach the top. The person can climb either 1 stair or 2 stairs at a time.
Print all possible ways person can reach the top.
For example, n=4 Output:
1 2 3 4
1 2 4
1 3 4
2 3 4
2 4
But I couldn't code this properly. How to code up solution for this?
To print the number of ways, you can first understand how to calculate the number of ways, and adjust it so each "count" will print instead of just count:
D(0) = 1
D(-1) = 0
D(i) = D(i-1) + D(i-2)
To adjust it to actual printing, you need to "remember" the choices you have made, and follow the same logic. Pseudo code:
printWays(curr, n, soFar):
if curr > n:
return
soFar.append(curr)
if n == curr:
print soFar
soFar.removeLast()
return
printWays(curr+1,n,soFar)
printWays(curr+2,n,soFar)
soFar.removeLast()
The idea is:
soFar is the current series of steps you did.
curr is the current step you're at.
n is the last stair you need to get to.
At each point, you either climb one stair or two. You check both options.
You can try some recursive solution where you call recursively CanClimb(n-1) and CanClimb(n-2) to visualize the possible ways.
Sample solution in C#:
public static void ClimbWays(int n, int currentIndex, int[] currectClimb)
{
if (n < 0) return;
if (n == 0)
{
for (var i = currentIndex - 1; i >= 0; i--)
{
Console.Write(currectClimb[i] + " ");
}
Console.WriteLine();
return;
}
currectClimb[currentIndex] = n;
ClimbWays(n - 1, currentIndex + 1, currectClimb);
ClimbWays(n - 2, currentIndex + 1, currectClimb);
}
Output for ClimbWays(4, 0, new int[4]);:
1 2 3 4
2 3 4
1 3 4
1 2 4
2 4
If you want to just count them you can use the well known Fibonacci sequence which can be calculated iteratively:
public static int Fibonacci(int n)
{
int a = 0;
int b = 1;
// In N steps compute Fibonacci sequence iteratively.
for (int i = 0; i < n; i++)
{
int temp = a;
a = b;
b = temp + b;
}
return a;
}
Given an array of 'n' integers, i need to find for each element of the array, the number of continuous subarrays that have that element as its max element.
Elements can repeat.
Is there a way to do it in less than O(n^2).
O(nlogn) or O(n)?
Example-
If array is {1,2,3}. Then-
For '1': 1 Such subarray {1}.
For '2': 2 Such subarrays {2},{1,2}
For '3': 3 Such subarrays {3},{2,3},{1,2,3}
I am having hard time trying to explain my solution in words. I will just add the code. It will explain itself:
#include <iostream>
#include <fstream>
using namespace std;
#define max 10000
int main(int argc, const char * argv[]) {
ifstream input("/Users/appleuser/Documents/Developer/xcode projects/SubArrayCount/SubArrayCount/input.in");
int n, arr[max], before[max]={0}, after[max]={0}, result[max];
input >> n;
for (int i=0; i<n; i++)
input >> arr[i];
for (int i=0;i<n;i++)
for (int j=i-1;j>=0&&arr[j]<arr[i];j-=before[j]+1)
before[i]+=before[j]+1;
for (int i=n-1;i>=0;i--)
for (int j=i+1;j<n&&arr[j]<arr[i];j+=after[j]+1)
after[i]+=after[j]+1;
for (int i=0;i<n;i++)
result[i]= (before[i]+1)*(after[i]+1);
for (int i=0; i<n; i++)
cout << result [i] << " ";
cout << endl;
return 0;
}
Explanation for (before[i]+1)*(after[i]+1):
for each value we need the numbers lies before and less than the value and the numbers lies after and less than the value.
| 0 1 2 3 4 5 .... count of numbers less than the value and appears before.
---------------------
0 | 1 2 3 4 5 6
1 | 2 4 6 8 10 12
2 | 3 6 9 12 15 18
3 | 4 8 12 16 20 24
4 | 5 10 15 20 25 30
5 | 6 12 18 24 30 36
. |
. |
. |
count of numbers less than the value and appears after.
Example: for a number that have 3 values less than it and appears before and have 4 values less than it and appears after. answer is V(3,4) = 20 = (3+1) * (4+1)
please, let me know the results.
Did you manage to find the source link of the problem?
You could store SubArrays sizes in another Array (arr2) to save yourself recalculating them.
arr2 must be the length of the max value in the arr1
i.e -
Take the Array {1,2,4,6,7,8}
arr2 is declared like this:
arr2 = []
for i in range(max(arr1)):
arr2.append(0)
Now, the algorithm goes like this:
Say you hit number 6.
Since 6-1=5 does not exist it has a default value of 0 corresponding to index 5 in arr2, because nothing has been added there yet. So you store 0+1=1 in position 6 of arr2. Then you hit the number 7. You check if 7-1=6 exists in arr2. It does, with a value of 1. Hence add the value of 1+1=2 to position 7 in arr2.
For each value in arr2 we simply add this to the count. We can do so simultaneously with a count variable.
This algorithm is O(n)
Here is my O(N) time java solution using Stack. Basic idea is to move from left to right keeping track of sub arrays ending at "i" and then right to left keeping track of sub arrays starting from "i":
public int[] countSubarrays(int[] arr) {
Stack<Integer> stack = new Stack<>();
int[] ans = new int[arr.length];
for(int i = 0; i < arr.length; i++) {
while(!stack.isEmpty() && arr[stack.peek()] < arr[i]) {
ans[i] += ans[stack.pop()];
}
stack.push(i);
ans[i]++;
}
stack.clear();
int[] temp = new int[arr.length];
for(int i = arr.length - 1; i >= 0; i--) {
while(!stack.isEmpty() && arr[stack.peek()] < arr[i]) {
int idx = stack.pop();
ans[i] += temp[idx];
temp[i] += temp[idx];
}
stack.push(i);
temp[i]++;
}
return ans;
}
You haven't specified in which way repeating elements are handled/what that element is (the element at the precise position in the array, or any element in the array with the same value).
Assuming the problem is for the element at a precise index this can be solved easily in linear time:
define ctSubarrays(int[] in , int at)
int minInd = at, maxInd = at;
//search for the minimum-index (lowest index with a smaller element than in[at]
for(; minInd > 0 && in[minInd - 1] < in[at] ; minInd--);
//search for the maximum-index (highest index with a smaller element than in[at]
for(; maxInd < length(at) - 1 && in[maxInd + 1] < in[at] ; maxInd++);
//now we've got the length of the largest subarray meeting all constraints
//next step: get the number of possible subarrays containing in[at]
int spaceMin = at - minInd;
int spaceMax = maxInd - at;
return spaceMin * spaceMax;
Lets look at an example.
{4, 5, 6, 3, 2}
Iterating from the begin till the end we can detect single increasing subarray: {4, 5, 6} and two single elements 3, and 2.
So we're detecting lengths of subarrays 3, 1, and 1.
First subarray {4, 5, 6} gives us 6 possible decisions, i.e. 1 + 2 + 3 = 6. It's a key.
For any length of increasing subarray N we can calculate the number of decisions as N * (N + 1)/2.
Therefore we have 3 * (3 + 1)/2 + 1 * (1 + 1)/2 + 1 * (1 + 1)/2, i.e. 6 + 1 + 1 = 8.
While we need a single iteration only, we have O(N) algorithm.
If the array is sorted,
count = 1;
for (i = 1 to n-1){
if(a[i-1] == a[i]){
count = count + 1;
}else if(a[i-1] + 1 == a[i]){
count of sub arrays for a[i-1] = count;
count = count + 1;
}else{
count of sub arrays for a[i-1] = count;
count = 1;
}
}
count of sub arrays for a[n-1] = count;
If the array is not sorted,
Assumption 3:If the array is like {3,1,2,3} then #sub arrays for 3 is 3
aMin = min(a);//O(n)
aMax = max(a);
len = (aMax - aMin + 1);
create array b of size len;
for (j = 0 to len-1){
b[j] = 0;
}
count = 1;
for (i = 1 to n-1){
if(a[i-1] == a[i]){
count = count + 1;
}else if(a[i-1] + 1 == a[i]){
if(b[a[i-1] - aMin] < count){
b[a[i-1] - aMin] = count;
}
count = count + 1;
}else{
if(b[a[i-1] - aMin] < count){
b[a[i-1] - aMin] = count;
}
count = 1;
}
}
if(b[a[n-1] - aMin] < count){
b[a[n-1] - aMin] = count;
}
for (i = 0 to n-1){
count of sub arrays for a[i] = b[a[i] - aMin];
}
This will work even if the array contains negative integers
If Assumption 3 fails according to your problem, and it is like,
Assumption 4:If the array is like {3,1,2,3} then #sub arrays for 3 is 4
{3}, {1,2,3}, {2,3}, {3}
Modify the above code by replacing
if(b[a[i-1] - aMin] < count){
b[a[i-1] - aMin] = count;
}
with this
b[a[i-1] - aMin] = b[a[i-1] - aMin] + count;
Create a value-to-index map and traverse from bottom to top - maintain an augmented tree of intervals. Each time an index is added, adjust the appropriate interval and calculate the total from the relevant segment. For example:
A = [5,1,7,2,3] => {1:1, 2:3, 3:4, 5:0, 7:2}
indexes interval total sub-arrays with maximum exactly
1 (1,1) 1 => 1
1,3 (3,3) 2 => 1
1,3,4 (3,4) 3 => 2
1,3,4,0 (0,1) 5 => 2
1,3,4,0,2 (0,4) 7 => 3 + 2*3 = 9
Insertion and deletion in augmented trees are of O(log n) time-complexity. Worst-case total time-complexity is O(n log n).
Using JavaScript Not sure the Big O notation. But here i'm looping the list. Then starting 2 loops. One counting down from i, and the other counting up from i+1.
let countArray = []
for(let i = 0; i < arr.length; i++){
let count = 0;
*This will count downwards starting at i*
for(let j = i; j >= 0; j--){
if(arr[j] > arr[i]) {break;}
count++;
}
*This will count upwards starting at i+1 so that you dont get a duplicate of the first value*
for(let j = i+1; j < arr.length; j++){
if(arr[j] >= arr[i]) {break;}
count++;
}
countArray.push(count);
}
return countArray;
I have been trying to formulate an algorithm to solve a problem. In this problem, we have a photo containing some buildings. The photo is divided into n vertical regions (called pieces) and the height of a building in each piece is given.
One building may span several consecutive pieces, but each piece can only contain one visible building, or no buildings at all. We are required to find the minimum number of buildings.
e.g.
given ,
3 ( no of pieces)
1 2 3 ( heights) ans = 3
3
1 2 1 ans = 2
6
1 2 3 1 2 3 ans = 5 ( a figure wud help show the overlap.).
Though I feel like I get it, I am unable to get a solid algorithm for it. Any ideas?
You can find the lowest number from the given array and account for all occurances of this number. This will split the array into multiple subarrays and now you need to recursively solve the problem for each of them.
In the example:
1 2 3 1 2 3 (total = 0)
Smallest number is 1:
x 2 3 x 2 3 (total = 1)
Now you have 2 subarrays.
Solve for the first one - the smallest number is 2:
x 3 (total = 2)
Finally you have a single element: total = 3
Solving the other subarray makes it 5.
Here is some code in C#:
int Solve(int[] ar, int start, int end){
//base for the recursion -> the subarray has single element
if(end-start == 1) return 1;
//base for the recursion -> the subarray is empty
if(end-start < 1) return 0;
//find min
int m = int.MaxValue;
for(int i = start; i < end; i++)
if (ar[i] < m) m = ar[i];
int total = 1;
//find the subarrays and their contribution recursively
int subStart = start;
for(int subEnd = start; subEnd < end; subEnd++){
if(ar[subEnd] == m) {
total += Solve(ar, subStart, subEnd);
subStart = subEnd + 1;
}
}
total += Solve(ar, subStart, ar.Length);
return total;
}