Related
I'm stuck in solving an interview question. The goal is to find a specific element from an array with unknown length (cannot use .length) and return the number of steps, but for an array with a length of n, the elements are guaranteed to be from 0 to n-1, no duplicates. For example, if the array's length is 5, the elements are {0, 1, 2, 3, 4} but the order may be different. Additional requirements are no loops, no static/global variables, and no helper functions, and the only parameters passing in are the array int[] arr and the target value int x, no extra parameters allowed, the array remains the same after all the operations have done.
//So you can only write in the body of the following method, no outside variables nor methods could be used.
private int findElement (int[] arr, int x) {
}
What I have gotten so far is, since the elements are guaranteed to be 0 to n-1, I can use the target number as an index and go back to the array to see if the number arr[x] equals the number x I want. If not, I take that number arr[x] and make it my new index, repeating until I find the target value.
int[] arr = {4, 1, 0, 2, 3}
int target = 3;
arr[3] = 2; //take target as the initial index
arr[2] = 0;
arr[0] = 4;
arr[4] = 3; //we got the number we want
//steps total is 3 since the question says the first time doesn't count.
Question: I tried to solve this by recursion, but since I am always comparing the following values with the initial parameter value, in the above case I always wanted to find 3. So how to store that information without static variables or extra parameters is my bigges problem. Is there any other way I can store the initial parameter value and pass it through the whole process?
private int findElement(int [] arr, int x) {
int actualN = arr[x];
if (actualN == **???**) { //can't be x cuz x is changing but I always want 3
return 0;
} else {
return findElement(arr, arr[x]) + 1;
}
}
Preferably using Java
Any hints or help would be greatly appreciated.
Probably this should work:
private int findElement(int [] arr, int x) {
int currValue = arr[x], returnValue;
if(arr[x]>0)
arr[x] = 0;//setting the actual element of the array to 0
else
arr[x]--;// decrementing the search index so it goes from 0-> -1 -> -2 -> -3...
if(Math.abs(arr[-arr[x]]) == x)//We check if the number is at our search index...
returnValue = 0;
else
returnValue = findElement(arr, x)+1;
arr[x] = currValue;//We take the value of the index from when the function was called and then reassign it to the same index after our work with it is done.
return returnValue;
}
Since the array only has to be the same after execution and it doesn't matter it's state during execution, this may work.
Note: I haven't done elaborate test on this so please do test the code sometimes before submitting
You were almost there
// t is the target number, o is teh array offset
static int find(int [] arr, int t, int o) {
if (arr[o] == t)
return o;
return find(arr, t, o + 1);
}
and
static void Main(string[] args) {
int[] arr = { 4, 1, 0, 2, 3 };
int target = 3;
int x = find(arr, 3, 0);
}
if only 2 args allowed - I missed that
in c
static int* find(int* arr, int t) {
if (*arr == t)
return arr;
return find(arr + 1, t);
}
int main() {
int arr[] = {4, 1, 0, 2, 3};
int target = 2;
int x = find(arr, target) - arr;
}
in c#
static unsafe int* find(int * arr, int t) {
if (*arr == t)
return arr;
return find(arr + 1,t);
}
static void Main(string[] args) {
int[] arr = { 4, 1, 0, 2, 3 };
int target = 3;
unsafe {
fixed (int * p = &arr[0]) {
int x = (int)(find(p, target) - p);
}
}
}
I have assumed arr can be modified, provide it is unchanged after the answer has been obtained.
Since it is only "preferable" that the answer be in Java (and I don't know Java), I'll offer a solution in Ruby. With its pseudo-code appearance and added comments readers unfamiliar with Ruby should be able to follow the calculations.
Specifically, I append an element to the given array which equals the index of the current element of the array to be examined (initially zero). If that element equals the target value we return up the recursion chain, initially returning zero, then adding one at each subsequent point of the chain. Before returning the desired count in doit, the last element of the array is removed to restore the array to its initial value.
If the value of the array indexed by the last element of the array (the current index) does not equal the target value the last element of the array is incremented by one and the method is called recursively.
def doit(arr,target)
arr << 0 # append the index 0 to arr
n = recurse(arr, target)
arr.pop # remove the last element of arr
n
end
def recurse(arr, target)
return 0 if arr[arr[-1]] == target
arr[-1] += 1 # increment last value of arr by 1
1 + recurse(arr, target)
end
arr = [4, 1, 0, 2, 3]
doit(arr, 4) #=> 0
doit(arr, 1) #=> 1
doit(arr, 0) #=> 2
doit(arr, 2) #=> 3
doit(arr, 3) #=> 4
By given an array of integers, each element represents a building. For example: int buildings[] = {1, 4, 3, 2, 3, 1}.
If I drew the buildings horizontally with a brush, how many brush strike I would use?
I should write a function that returns the number of these brush strokes. For example 5.
I can do it easily on run time O(n^2), by using 2 loops.
The external loop running on the levels of each building (according to the highest building).
The inner loop is running on the array from 0 to n, and compares the difference of the height (0 or 1) between two near elements.
How can I do this in the O(n) time and O(n) space?
A brush stroke starts whenever the height increases going from left to right, and ends when it decreases. You only need to look at when it increases, because if you just count the starting points of each stroke you will have the stroke count. Instead of looping over the height levels in an inner loop, just subtract one height level from the previous to get the difference.
In pseudo-code:
int BrushCount(int[] buildings)
{
int brushCount = 0;
int prevHeight = 0;
for(int i = 0; i < buildings.length; i++)
{
if(buildings[i] > prevHeight)
brushCount = brushCount + (buildings[i] - prevHeight);
prevHeight = buildings[i];
}
return brushCount;
}
Runs in O(n).
A little code golf :) (Based on samgak's excellent explanation.)
const f = A => A.reduce((a,b,i,A) => a + Math.max(0, b - A[i-1]));
console.log(f([1, 4, 3, 2, 3, 1]))
console.log(f([4, 1, 2, 1, 2, 2]))
Counting from the end of the array use the last element as the initial value of the result, and compare the previous one with the current one.
If they are the same value then, the result increase one;
if the previous one is smaller than the current one, do nothing;
if the previous one is bigger than the current one then, result = result +previous-current
int i=sizeof buildings;
int t=buildings[i];
while(i>0){
if(buildings[i-1]-buildings[i]>0) t+=(buildings[i-1]-buildings[i]);
else if(buildings[i-1]-buildings[i]==0) ++t;
--i;
}
return t;
public static int brushCount(int[] buildings)
{
int count=0;
for(int i=0; i<=buildings.length-1; i++){
if((i+1)<(buildings.length)){
if(buildings[i]>buildings[i+1]){
count += buildings[i]-buildings[i+1];
}
}else{
count += buildings[i];
}
}
return count;
}
You can easily see that we need a stack like approach to keep heights in increasing order and add the difference between top element and current element when our current value is less than top value.
Since we don't values before the top, we can just keep a variable for the top element.
#include <bits/stdc++.h>
using namespace std;
using ll = int64_t;
int solve(vector<int> v) {
int brushes = 0, lastMax = 0;
for (auto val: v) {
if (val > lastMax) {
brushes += lastMax - val;
}
lastMax = val;
}
brushes += lastMax;
return brushes;
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
vector<int> v1 {1, 4, 3, 2, 3, 1}, v2 {4, 1, 2, 1, 2, 2};
cout << solve(v1) << ' ' << solve(v2) << endl; // 5 6
}
Kotlin version of #samgak's answer:
fun brush(nums: IntArray): Int {
var c = 0
var ph = 0
nums.forEach {
if (it > ph) c += (it - ph)
ph = it
}
return c
}
Shortly java answer:
int BrushCount(int[] buildings) {
int s=0,p=0;
for(int x:buildings) s-=(x>p?p:x)-(p=x);
return s;
}
I am trying to add elements in an Array in Typescrypt with the push method, but it does not seem to work. the array remains empty. This is my code:
list: Array<int> = Array(10)
for(let x = 0; x <= 10; x++) {
list.push(x)
}
someone got the same problem?
in your case you can do :
list: Array<number> = [];
for(let x = 0; x <= 10; x++) {
list.push(x)
}
or
list: Array<number> = Array(10)
for(let x = 0; x <= 10; x++) {
list[x];
}
Explanation on your error :
Array(10) already creates an array with 10 "empty" elements.
if you use push on it, you will actually get your elements pushed, but in the 11th to the 20th position.
The 1st to the 10th ranks stay empty (and will return undefined if you try to get their value them)
So a few things to note:
There's no int type in TypeScript, since JavaScript has only one number type, the corresponding TypeScript type is called number.
You shouldn't use Array(n) (or the array constructor in general) to create an array, there's a lot of information about why that is (primarily, it creates what's called a sparse array, with a length property but no elements), but you should generally use [] to create a new array. All arrays in JavaScript are dynamic anyway, so the 10 you pass has no meaning.
You should never define variables without declaring them with const, let or var.
Combining the points above, here's how your code should look like for this case
const list: number[] /* or Array<number> */ = []
for(let x = 0; x <= 10; x++) {
list.push(x)
}
int type is not available in typescript use number instead of int
let list: Array<number> = Array(10);
for (let x = 0; x <= 10; x++) {
list.push(x)
}
above code is pushing the value to array but this will return
[undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
to fix this please change code to
let list: Array<number> = Array();
for (let x = 0; x <= 10; x++) {
list[x] = x;
}
this will return [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
I'm looking for an algorithm that given a list like:
[1, 1, 2, 1, 1, 5, 1, 1, 1, 1, 2, 1]
can find and return all subsequences of a given value. For example, if given the value 1, the function would return [[1, 1], [1, 1], [1, 1, 1, 1], [1]].
I believe this is similar to problems such as summing up all subsequences of an array or finding all the subsequences of a given string but algorithms was never my strong suit. The answer can be psuedo-code or language agnostic. And if you wouldn't mind, could you explain the complexity of the solution?
I can explain what I need this for if that helps. Comment if you want that.
We can do this in O(n) time complexity by scanning the array twice. Pseudocode:
//use an array list so we can access element at an index in O(1) time
outputArrays = new ArrayList<int[]> //list of arrays
//loop to declare arrays of outputs - this scans each element once
int currLen = 0;
for (item in inputArray) {
if (item = itemToLookFor) {
currLen++;
}else if (currLen > 0) {
currLen = 0;
outputArrays.add(new int[currLen]);
}
}
//loop to actually populate the output - this scans each element once
currLen = 0;
currIndex = 0;
for (item in inputArray) {
if (item = itemToLookFor) {
outputArrays.getElement(currIndex)[currLen] = item;
currLen++;
}else if (currLen > 0) {
currLen = 0;
currIndex++;
}
}
Let me know if there is anything i can clarify.
Let a be initial array, res - resulting array of sequences, curSeq - a current sequence, given_value - a given value.
res = []
curSeq = []
for i = 1..length(a)
if a[i] != given_value
if curSeq has at least one item
append curSeq to res
end if
curSeq = []
else
append given_value to curSeq
end if
end for
if curSeq has at least one item
append curSeq to res
end if
As you can see the time complexity is O(n) where n is the length of initial array.
Here is the O(n) solution.
Here arr is input array of sequence and sequence is array for sub-sequence. You can save sequence another array for your answer.
arr = [1, 1, 2, 1, 1, 5, 1, 1, 1, 1, 2, 1]; // here is your
selectNumber = 1 //take input for selected input
sequence = [];
for (i: 0 to arr.length) {
if (arr[i] == selectNumber) {
sequence.push(selectNumber);
} else {
if(sequence.length > 0) {
print sequence;
sequence = [] // empty sequence array as it is already printed or saved
}
}
}
if (sequence > 0) {
print sequence; // last sequence if exist
}
I had previously posted a question, Given an array, find out the next smaller element for each element
now, i was trying to know , if there is any way to find out "given an array, for each element, find out the total number of elements lesser than it, which appear to the right of it"
for example, the array [4 2 1 5 3] should yield [3 1 0 1 0]??
[EDIT]
I have worked out a solution, please have a look at it, and let me know if there is any mistake.
1 Make a balanced BST inserting elements traversing the array from right to left
2 The BST is made in such a way that each element holds the size of the tree rooted at that element
3 Now while you search for the right position to insert any element, take account of the total size of the subtree rooted at left sibling + 1(for parent) if you move right
Now since, the count is being calculated at the time of insertion of an element, and that we are moving from right to left, we get the exact count of elements lesser than the given element appearing after it.
It can be solved in O(n log n).
If in a BST you store the number of elements of the subtree rooted at that node when you search the node (reaching that from the root) you can count number of elements larger/smaller than that in the path:
int count_larger(node *T, int key, int current_larger){
if (*T == nil)
return -1;
if (T->key == key)
return current_larger + (T->right_child->size);
if (T->key > key)
return count_larger(T->left_child, key, current_larger + (T->right_child->size) + 1);
return count_larger(T->right_child, key, current_larger)
}
** for example if this is our tree and we're searching for key 3, count_larger will be called for:
-> (node 2, 3, 0)
--> (node 4, 3, 0)
---> (node 3, 3, 2)
and the final answer would be 2 as expected.
Suppose the Array is 6,-1,5,10,12,4,1,3,7,50
Steps
1.We start building a BST from right end of the array.Since we are concerned with all the elements to right for any element.
2.Suppose we have formed the partial solution tree upto the 10.
3.Now when inserting 5 we do a tree traversal and insert to the right of 4.
Notice that each time we traverse to the right of any node we increment by 1 and add the no. of elements in left subtree of that node.
eg:
for 50 it is 0
for 7 it is 0
for 12 it is 1 right traversel + leftsubtree size of 7 = 1+3 =4
for 10 same as above.
for 4 it is 1+1 =2
While building bst we can easily maintain the left subtree size for each node by simply maintaining a variable corresponding to it and incrementing it by 1 each time a node traverses to the left by it.
Hence the Solution Average case O(nlogn).
We can use other optimizations such as predetermining whether array is sorted in decreasing order
find groups of element in decreasing order treat them as single.
I think is it possible to do it in O(nlog(n))with a modified version of quicksort. Basically each time you add an element to less, you check if this element rank in the original array was superior to the rank of the current pivot. It may look like
oldrank -> original positions
count -> what you want
function quicksort('array')
if length('array') ≤ 1
return 'array' // an array of zero or one elements is already sorted
select and remove a pivot value 'pivot' from 'array'
create empty lists 'less' and 'greater'
for each 'x' in 'array'
if 'x' ≤ 'pivot'
append 'x' to 'less'
if oldrank(x) > = oldrank(pivot) increment count(pivot)
else
append 'x' to 'greater'
if oldrank(x) < oldrank(pivot) increment count(x) //This was missing
return concatenate(quicksort('less'), 'pivot', quicksort('greater')) // two recursive calls
EDIT:
Actually it can be done using any comparison based sorting algorithm . Every time you compare two elements such that the relative ordering between the two will change, you increment the counter of the bigger element.
Original pseudo-code in wikipedia.
You can also use binary Index tree
int tree[1000005];
void update(int idx,int val)
{
while(idx<=1000000)
{
tree[idx]+=val;
idx+=(idx & -idx);
}
}
int sum(int idx)
{
int sm=0;
while(idx>0)
{
sm+=tree[idx];
idx-=(idx & -idx);
}
return sm;
}
int main()
{
int a[]={4,2,1,5,3};
int s=0,sz=6;
int b[10];
b[sz-1]=0;
for(int i=sz-2;i>=0;i--)
{
if(a[i]!=0)
{
update(a[i],1);
b[i]=sum(a[i]-1)+s;
}
else s++;
}
for(int i=0;i<sz-1;i++)
{
cout<<b[i]<<" ";
}
return 0;
}
//some array called newarray
for(int x=0; x <=array.length;x++)
{
for(int y=x;y<array.length;y++)
{
if(array[y] < array[x])
{
newarray[x] = newarray[x]+1;
}
}
}
something like this,where array is your input array and newarray your output array
make sure to initialize everything correctly(0 for the newarrays values)
Another approach without using the tree.
Construct another sorted array . For example for input array {12, 1, 2, 3, 0, 11, 4} it will be {0, 1, 2, 3, 4, 11, 12}
Now compare position of each element from input array with sorted array.For example 12 in first array is at 0 index while sorted array it’s as 6
Once comparison is done, remove element from both array
Other than using BST, we can also solve this problem optimally by doing some modification in merge sort algorithm (in O(n*logn) time).
If you observe this problem more carefully, you can say that in the problem we need to count the number of inversions required for each element to make the array sorted in ascending order, right?
So this problem can be solved using Divide and Conquer paradigm. Here you need to maintain an auxiliary array for storing the count of inversions required (i.e. elements smaller than it on the right side of it).
Below is a python program:
def mergeList(arr, pos, res, start, mid, end):
temp = [0]*len(arr)
for i in range(start, end+1):
temp[i] = pos[i]
cur = start
leftcur = start
rightcur = mid + 1
while leftcur <= mid and rightcur <= end:
if arr[temp[leftcur]] <= arr[temp[rightcur]]:
pos[cur] = temp[leftcur]
res[pos[cur]] += rightcur - mid - 1
leftcur += 1
cur += 1
else:
pos[cur] = temp[rightcur]
cur += 1
rightcur += 1
while leftcur <= mid:
pos[cur] = temp[leftcur]
res[pos[cur]] += end - mid
cur += 1
leftcur += 1
while rightcur <= end:
pos[cur] = temp[rightcur]
cur += 1
rightcur += 1
def mergeSort(arr, pos, res, start, end):
if start < end:
mid = (start + end)/2
mergeSort(arr, pos, res, start, mid)
mergeSort(arr, pos, res, mid+1, end)
mergeList(arr, pos, res, start, mid, end)
def printResult(arr, res):
print
for i in range(0, len(arr)):
print arr[i], '->', res[i]
if __name__ == '__main__':
inp = input('enter elements separated by ,\n')
inp = list(inp)
res = [0]*len(inp)
pos = [ind for ind, v in enumerate(inp)]
mergeSort(inp, pos, res, 0, len(inp)-1)
printResult(inp, res)
Time : O(n*logn)
Space: O(n)
You can also use an array instead of a binary search tree.
def count_next_smaller_elements(xs):
# prepare list "ys" containing item's numeric order
ys = sorted((x,i) for i,x in enumerate(xs))
zs = [0] * len(ys)
for i in range(1, len(ys)):
zs[ys[i][1]] = zs[ys[i-1][1]]
if ys[i][0] != ys[i-1][0]: zs[ys[i][1]] += 1
# use list "ts" as binary search tree, every element keeps count of
# number of children with value less than the current element's value
ts = [0] * (zs[ys[-1][1]]+1)
us = [0] * len(xs)
for i in range(len(xs)-1,-1,-1):
x = zs[i]+1
while True:
us[i] += ts[x-1]
x -= (x & (-x))
if x <= 0: break
x = zs[i]+1
while True:
x += (x & (-x))
if x > len(ts): break
ts[x-1] += 1
return us
print count_next_smaller_elements([40, 20, 10, 50, 20, 40, 30])
# outputs: [4, 1, 0, 2, 0, 1, 0]
Instead of BST, you can use stl map.
Start inserting from right.
After inserting an element, find its iterator:
auto i = m.find(element);
Then subtract it from m.end(). That gives you the number of elements in map which are greater than current element.
map<int, bool> m;
for (int i = array.size() - 1; i >= 0; --i) {
m[array[i]] = true;
auto iter = m.find(array[i])
greaterThan[i] = m.end() - iter;
}
Hope it helped.
Modified Merge sort: (Already tested code)
Takes O(nlogn) time.
public class MergeSort {
static HashMap<Integer, Integer> valueToLowerCount = new HashMap<Integer, Integer>();
public static void main(String[] args) {
int [] arr = new int[] {50, 33, 37, 26, 58, 36, 59};
int [] lowerValuesOnRight = new int[] {4, 1, 2, 0, 1, 0, 0};
HashMap<Integer, Integer> expectedLowerCounts = new HashMap<Integer, Integer>();
idx = 0;
for (int x: arr) {
expectedLowerCounts.put(x, lowerValuesOnRight[idx++]);
}
for (int x : arr) valueToLowerCount.put(x, 0);
mergeSort(arr, 0, arr.length-1);
//Testing
Assert.assertEquals("Count lower values on right side", expectedLowerCounts, valueToLowerCount);
}
public static void mergeSort(int []arr, int l, int r) {
if (r <= l) return;
int mid = (l+r)/2;
mergeSort(arr, l, mid);
mergeSort(arr, mid+1, r);
mergeDecreasingOrder(arr, l, mid, r);
}
public static void mergeDecreasingOrder(int []arr, int l, int lr, int r) {
int []leftArr = Arrays.copyOfRange(arr, l, lr+1);
int []rightArr = Arrays.copyOfRange(arr, lr+1, r+1);
int indexArr = l;
int i = 0, j = 0;
while (i < leftArr.length && j < rightArr.length) {
if (leftArr[i] > rightArr[j]) {
valueToLowerCount.put(leftArr[i], valueToLowerCount.get(leftArr[i]) + rightArr.length - j);
arr[indexArr++] = leftArr[i++];
}else {
arr[indexArr++] = rightArr[j++];
}
}
while (i < leftArr.length) {
arr[indexArr++] = leftArr[i++];
}
while (j < rightArr.length) {
arr[indexArr++] = rightArr[j++];
}
}
}
To find the total number of values on right-side which are greater than an array element, simply change single line of code:
if (leftArr[i] > rightArr[j])
to
if (leftArr[i] < rightArr[j])