I have been trying to solve the below task:
You are given N counters, initially set to 0, and you have two possible operations on them:
increase(X) − counter X is increased by 1,
max_counter − all counters are set to the maximum value of any counter.
A non-empty zero-indexed array A of M integers is given. This array represents consecutive operations:
if A[K] = X, such that 1 ≤ X ≤ N, then operation K is increase(X),
if A[K] = N + 1 then operation K is max_counter.
For example, given integer N = 5 and array A such that:
A[0] = 3
A[1] = 4
A[2] = 4
A[3] = 6
A[4] = 1
A[5] = 4
A[6] = 4
the values of the counters after each consecutive operation will be:
(0, 0, 1, 0, 0)
(0, 0, 1, 1, 0)
(0, 0, 1, 2, 0)
(2, 2, 2, 2, 2)
(3, 2, 2, 2, 2)
(3, 2, 2, 3, 2)
(3, 2, 2, 4, 2)
The goal is to calculate the value of every counter after all operations.
struct Results {
int * C;
int L;
};
Write a function:
struct Results solution(int N, int A[], int M);
that, given an integer N and a non-empty zero-indexed array A consisting of M integers, returns a sequence of integers representing the values of the counters.
The sequence should be returned as:
a structure Results (in C), or
a vector of integers (in C++), or
a record Results (in Pascal), or
an array of integers (in any other programming language).
For example, given:
A[0] = 3
A[1] = 4
A[2] = 4
A[3] = 6
A[4] = 1
A[5] = 4
A[6] = 4
the function should return [3, 2, 2, 4, 2], as explained above.
Assume that:
N and M are integers within the range [1..100,000];
each element of array A is an integer within the range [1..N + 1].
Complexity:
expected worst-case time complexity is O(N+M);
expected worst-case space complexity is O(N), beyond input storage (not counting the storage required for input arguments).
Elements of input arrays can be modified.
Here is my solution:
import java.util.Arrays;
class Solution {
public int[] solution(int N, int[] A) {
final int condition = N + 1;
int currentMax = 0;
int countersArray[] = new int[N];
for (int iii = 0; iii < A.length; iii++) {
int currentValue = A[iii];
if (currentValue == condition) {
Arrays.fill(countersArray, currentMax);
} else {
int position = currentValue - 1;
int localValue = countersArray[position] + 1;
countersArray[position] = localValue;
if (localValue > currentMax) {
currentMax = localValue;
}
}
}
return countersArray;
}
}
Here is the code valuation:
https://codility.com/demo/results/demo6AKE5C-EJQ/
Can you give me a hint what is wrong with this solution?
The problem comes with this piece of code:
for (int iii = 0; iii < A.length; iii++) {
...
if (currentValue == condition) {
Arrays.fill(countersArray, currentMax);
}
...
}
Imagine that every element of the array A was initialized with the value N+1. Since the function call Arrays.fill(countersArray, currentMax) has a time complexity of O(N) then overall your algorithm will have a time complexity O(M * N). A way to fix this, I think, instead of explicitly updating the whole array A when the max_counter operation is called you may keep the value of last update as a variable. When first operation (incrementation) is called you just see if the value you try to increment is larger than the last_update. If it is you just update the value with 1 otherwise you initialize it to last_update + 1. When the second operation is called you just update last_update to current_max. And finally, when you are finished and try to return the final values you again compare each value to last_update. If it is greater you just keep the value otherwise you return last_update
class Solution {
public int[] solution(int N, int[] A) {
final int condition = N + 1;
int currentMax = 0;
int lastUpdate = 0;
int countersArray[] = new int[N];
for (int iii = 0; iii < A.length; iii++) {
int currentValue = A[iii];
if (currentValue == condition) {
lastUpdate = currentMax
} else {
int position = currentValue - 1;
if (countersArray[position] < lastUpdate)
countersArray[position] = lastUpdate + 1;
else
countersArray[position]++;
if (countersArray[position] > currentMax) {
currentMax = countersArray[position];
}
}
}
for (int iii = 0; iii < N; iii++) {
if (countersArray[iii] < lastUpdate)
countersArray[iii] = lastUpdate;
}
return countersArray;
}
}
The problem is that when you get lots of max_counter operations you get lots of calls to Arrays.fill which makes your solution slow.
You should keep a currentMax and a currentMin:
When you get a max_counter you just set currentMin = currentMax.
If you get another value, let's call it i:
If the value at position i - 1 is smaller or equal to currentMin you set it to currentMin + 1.
Otherwise you increment it.
At the end just go through the counters array again and set everything less than currentMin to currentMin.
Another solution that I have developed and might be worth considering: http://codility.com/demo/results/demoM658NU-DYR/
This is the 100% solution of this question.
// you can also use imports, for example:
// import java.math.*;
class Solution {
public int[] solution(int N, int[] A) {
int counter[] = new int[N];
int n = A.length;
int max=-1,current_min=0;
for(int i=0;i<n;i++){
if(A[i]>=1 && A[i]<= N){
if(counter[A[i] - 1] < current_min) counter[A[i] - 1] = current_min;
counter[A[i] - 1] = counter[A[i] - 1] + 1;
if(counter[A[i] - 1] > max) max = counter[A[i] - 1];
}
else if(A[i] == N+1){
current_min = max;
}
}
for(int i=0;i<N;i++){
if(counter[i] < current_min) counter[i] = current_min;
}
return counter;
}
}
I'm adding another Java 100 solution with some test cases it they're helpful.
// https://codility.com/demo/results/demoD8J6M5-K3T/ 77
// https://codility.com/demo/results/demoSEJHZS-ZPR/ 100
public class MaxCounters {
// Some testcases
// (1,[1,2,3]) = [1]
// (1,[1]) = [1]
// (1,[5]) = [0]
// (1,[1,1,1,2,3]) = 3
// (2,[1,1,1,2,3,1]) = [4,3]
// (5, [3, 4, 4, 5, 1, 4, 4]) = (1, 0, 1, 4, 1)
public int[] solution(int N, int[] A) {
int length = A.length, maxOfCounter = 0, lastUpdate = 0;
int applyMax = N + 1;
int result[] = new int[N];
for (int i = 0; i < length; ++i ) {
if(A[i] == applyMax){
lastUpdate = maxOfCounter;
} else if (A[i] <= N) {
int position = A[i]-1;
result[position] = result[position] > lastUpdate
? result[position] + 1 : lastUpdate + 1;
// updating the max for future use
if(maxOfCounter <= result[position]) {
maxOfCounter = result[position];
}
}
}
// updating all the values that are less than the lastUpdate to the max value
for (int i = 0; i < N; ++i) {
if(result[i] < lastUpdate) {
result[i] = lastUpdate;
}
}
return result;
}
}
My java solution with a detailed explanation 100% Correctness, 100% Performance :
Time Complexity O(N+M)
public static int[] solution(int N, int[] A) {
int[] counters = new int[N];
//The Max value between all counters at a given time
int max = 0;
//The base Max that all counter should have after the "max counter" operation happens
int baseMax = 0;
for (int i = 0; i < A.length; i++) {
//max counter Operation ==> updating the baseMax
if (A[i] > N) {
// Set The Base Max that all counters should have
baseMax = max;
}
//Verify if the value is bigger than the last baseMax because at any time a "max counter" operation can happen and the counter should have the max value
if (A[i] <= N && counters[A[i] - 1] < baseMax) {
counters[A[i] - 1] = baseMax;
}
//increase(X) Operation => increase the counter value
if (A[i] <= N) {
counters[A[i] - 1] = counters[A[i] - 1] + 1;
//Update the max
max = Math.max(counters[A[i] - 1], max);
}
}
//Set The remaining values to the baseMax as not all counters are guaranteed to be affected by an increase(X) operation in "counters[A[i] - 1] = baseMax;"
for (int j = 0; j < N; j++) {
if (counters[j] < baseMax)
counters[j] = baseMax;
}
return counters;
}
Here is my C++ solution which got 100 on codility. The concept is same as explained above.
int maxx=0;
int lastvalue=0;
void set(vector<int>& A, int N,int X)
{
for ( int i=0;i<N;i++)
if(A[i]<lastvalue)
A[i]=lastvalue;
}
vector<int> solution(int N, vector<int> &A) {
// write your code in C++11
vector<int> B(N,0);
for(unsigned int i=0;i<A.size();i++)
{
if(A[i]==N+1)
lastvalue=maxx;
else
{ if(B[A[i]-1]<lastvalue)
B[A[i]-1]=lastvalue+1;
else
B[A[i]-1]++;
if(B[A[i]-1]>maxx)
maxx=B[A[i]-1];
}
}
set(B,N,maxx);
return B;
}
vector<int> solution(int N, vector<int> &A)
{
std::vector<int> counters(N);
auto max = 0;
auto current = 0;
for (auto& counter : A)
{
if (counter >= 1 && counter <= N)
{
if (counters[counter-1] < max)
counters[counter - 1] = max;
counters[counter - 1] += 1;
if (counters[counter - 1] > current)
current = counters[counter - 1];
}
else if (counter > N)
max = current;
}
for (auto&& counter : counters)
if (counter < max)
counter = max;
return counters;
}
Arrays.fill() invocation inside array interation makes the program O(N^2)
Here is a possible solution which has O(M+N) runtime.
The idea is -
For the second operation, keep track of max value that is achieved through increment, this is our base value till the current iteration, no values can't be less than this.
For the first operation, resetting the value to base value if needed before the increment.
public static int[] solution(int N, int[] A) {
int counters[] = new int[N];
int base = 0;
int cMax = 0;
for (int a : A) {
if (a > counters.length) {
base = cMax;
} else {
if (counters[a - 1] < base) {
counters[a - 1] = base;
}
counters[a - 1]++;
cMax = Math.max(cMax, counters[a - 1]);
}
}
for (int i = 0; i < counters.length; i++) {
if (counters[i] < base) {
counters[i] = base;
}
}
return counters;
}
vector<int> solution(int N, vector<int> &A)
{
std::vector<int> counter(N, 0);
int max = 0;
int floor = 0;
for(std::vector<int>::iterator i = A.begin();i != A.end(); i++)
{
int index = *i-1;
if(*i<=N && *i >= 1)
{
if(counter[index] < floor)
counter[index] = floor;
counter[index] += 1;
max = std::max(counter[index], max);
}
else
{
floor = std::max(max, floor);
}
}
for(std::vector<int>::iterator i = counter.begin();i != counter.end(); i++)
{
if(*i < floor)
*i = floor;
}
return counter;
}
Hera is my AC Java solution. The idea is the same as #Inwvr explained:
public int[] solution(int N, int[] A) {
int[] count = new int[N];
int max = 0;
int lastUpdate = 0;
for(int i = 0; i < A.length; i++){
if(A[i] <= N){
if(count[A[i]-1] < lastUpdate){
count[A[i]-1] = lastUpdate+1;
}
else{
count[A[i]-1]++;
}
max = Math.max(max, count[A[i]-1]);
}
else{
lastUpdate = max;
}
}
for(int i = 0; i < N; i++){
if(count[i] < lastUpdate)
count[i] = lastUpdate;
}
return count;
}
I just got 100 in PHP with some help from the above
function solution($N, $A) {
$B = array(0);
$max = 0;
foreach($A as $key => $a) {
$a -= 1;
if($a == $N) {
$max = max($B);
} else {
if(!isset($B[$a])) {
$B[$a] = 0;
}
if($B[$a] < $max) {
$B[$a] = $max + 1;
} else {
$B[$a] ++;
}
}
}
for($i=0; $i<$N; $i++) {
if(!isset($B[$i]) || $B[$i] < $max) {
$B[$i] = $max;
}
}
return $B;
}
This is another C++ solution to the problem.
The rationale is always the same.
Avoid to set to max counter all the counter upon instruction two, as this would bring the complexity to O(N*M).
Wait until we get another operation code on a single counter.
At this point the algorithm remembers whether it had met a max_counter and set the counter value consequently.
Here the code:
vector<int> MaxCounters(int N, vector<int> &A)
{
vector<int> n(N, 0);
int globalMax = 0;
int localMax = 0;
for( vector<int>::const_iterator it = A.begin(); it != A.end(); ++it)
{
if ( *it >= 1 && *it <= N)
{
// this is an increase op.
int value = *it - 1;
n[value] = std::max(n[value], localMax ) + 1;
globalMax = std::max(n[value], globalMax);
}
else
{
// set max counter op.
localMax = globalMax;
}
}
for( vector<int>::iterator it = n.begin(); it != n.end(); ++it)
*it = std::max( *it, localMax );
return n;
}
100%, O(m+n)
public int[] solution(int N, int[] A) {
int[] counters = new int[N];
int maxAIs = 0;
int minAShouldBe = 0;
for(int x : A) {
if(x >= 1 && x <= N) {
if(counters[x-1] < minAShouldBe) {
counters[x-1] = minAShouldBe;
}
counters[x-1]++;
if(counters[x-1] > maxAIs) {
maxAIs = counters[x-1];
}
} else if(x == N+1) {
minAShouldBe = maxAIs;
}
}
for(int i = 0; i < N; i++) {
if(counters[i] < minAShouldBe) {
counters[i] = minAShouldBe;
}
}
return counters;
}
here is my code, but its 88% cause it takes 3.80 sec for 10000 elements instead of 2.20
class Solution {
boolean maxCalled;
public int[] solution(int N, int[] A) {
int max =0;
int [] counters = new int [N];
int temp=0;
int currentVal = 0;
for(int i=0;i<A.length;i++){
currentVal = A[i];
if(currentVal <=N){
temp = increas(counters,currentVal);
if(temp > max){
max = temp;
}
}else{
if(!maxCalled)
maxCounter(counters,max);
}
}
return counters;
}
int increas (int [] A, int x){
maxCalled = false;
return ++A[x-1];
//return t;
}
void maxCounter (int [] A, int x){
maxCalled = true;
for (int i = 0; i < A.length; i++) {
A[i] = x;
}
}
}
Following my solution in JAVA (100/100).
public boolean isToSum(int value, int N) {
return value >= 1 && value <= N;
}
public int[] solution(int N, int[] A) {
int[] res = new int[N];
int max =0;
int minValue = 0;
for (int i=0; i < A.length; i++){
int value = A[i];
int pos = value -1;
if ( isToSum(value, N)) {
if( res[pos] < minValue) {
res[pos] = minValue;
}
res[pos] += 1;
if (max < res[pos]) {
max = res[pos];
}
} else {
minValue = max;
}
}
for (int i=0; i < res.length; i++){
if ( res[i] < minValue ){
res[i] = minValue;
}
}
return res;
}
my solution is :
public class Solution {
public int[] solution(int N, int[] A) {
int[] counters = new int[N];
int[] countersLastMaxIndexes = new int[N];
int maxValue = 0;
int fixedMaxValue = 0;
int maxIndex = 0;
for (int i = 0; i < A.length; i++) {
if (A[i] <= N) {
if (countersLastMaxIndexes[A[i] - 1] != maxIndex) {
counters[A[i] - 1] = fixedMaxValue;
countersLastMaxIndexes[A[i] - 1] = maxIndex;
}
counters[A[i] - 1]++;
if (counters[A[i] - 1] > maxValue) {
maxValue = counters[A[i] - 1];
}
} else {
maxIndex = i;
fixedMaxValue = maxValue;
}
}
for (int i = 0; i < countersLastMaxIndexes.length; i++) {
if (countersLastMaxIndexes[i] != maxIndex) {
counters[i] = fixedMaxValue;
countersLastMaxIndexes[i] = maxIndex;
}
}
return counters;
}
}
In my Java solution I updated values in solution[] only when needed. And finally updated solution[] with a right values.
public int[] solution(int N, int[] A) {
int[] solution = new int[N];
int maxCounter = 0;
int maxCountersSum = 0;
for(int a: A) {
if(a >= 1 && a <= N) {
if(solution[a - 1] < maxCountersSum)
solution[a - 1] = maxCountersSum;
solution[a - 1]++;
if(solution[a - 1] > maxCounter)
maxCounter = solution[a - 1];
}
if(a == N + 1) {
maxCountersSum = maxCounter;
}
}
for(int i = 0; i < N; i++) {
if(solution[i] < maxCountersSum)
solution[i] = maxCountersSum;
}
return solution;
}
Here's my python solution:
def solution(N, A):
# write your code in Python 3.6
RESP = [0] * N
MAX_OPERATION = N + 1
current_max = 0
current_min = 0
for operation in A:
if operation != MAX_OPERATION:
if RESP[operation-1] <= current_min:
RESP[operation-1] = current_min + 1
else:
RESP[operation-1] += 1
if RESP[operation-1] > current_max:
current_max = RESP[operation-1]
else:
if current_min == current_max:
current_min += 1
else:
current_min = current_max
for i, val in enumerate(RESP):
if val < current_min:
RESP[i] = current_min
return RESP
def sample_method(A,N=5):
initial_array = [0,0,0,0,0]
for i in A:
if(i>=1):
if(i<=N):
initial_array[i-1]+=1
else:
for a in range(len(initial_array)):
initial_array[a]+=1
print i
print initial_array
Here's my solution using python 3.6. The result is 100% correctness but 40% performance (most of them were because of timeout). Still cannot figure out how to optimize this code but hopefully someone can find it useful.
def solution(N, A):
count = [0]*(N+1)
for i in range(0,len(A)):
if A[i] >=1 and A[i] <= N:
count[A[i]] += 1
elif A[i] == (N+1):
count = [max(count)] * len(count)
count.pop(0)
return count
Typescript:
function counters(numCounters: number, operations: number[]) {
const counters = Array(numCounters)
let max = 0
let currentMin = 0
for (const operation of operations) {
if (operation === numCounters + 1) {
currentMin = max
} else {
if (!counters[operation - 1] || counters[operation - 1] < currentMin) {
counters[operation - 1] = currentMin
}
counters[operation - 1] = counters[operation - 1] + 1
if (counters[operation - 1] > max) {
max += 1
}
}
}
for (let i = 0; i < numCounters; i++) {
if (!counters[i] || counters[i] < currentMin) {
counters[i] = currentMin
}
}
return counters
}
console.log(solution=${counters(5, [3, 4, 4, 6, 1, 4, 4])})
100 points JavaScript solution, includes performance improvement to ignore repeated max_counter iterations:
function solution(N, A) {
let max = 0;
let counters = Array(N).fill(max);
let maxCounter = 0;
for (let op of A) {
if (op <= N && op >= 1) {
maxCounter = 0;
if (++counters[op - 1] > max) {
max = counters[op - 1];
}
} else if(op === N + 1 && maxCounter === 0) {
maxCounter = 1;
for (let i = 0; i < counters.length; i++) {
counters[i] = max;
}
}
}
return counters;
}
solution in JAVA (100/100)
class Solution {
public int[] solution(int N, int[] A) {
// write your code in Java SE 8
int[] result = new int[N];
int base = 0;
int max = 0;
int needToChange=A.length;;
for (int k = 0; k < A.length; k++) {
int X = A[k];
if (X >= 1 && X <= N) {
if (result[X - 1] < base) {
result[X - 1] = base;
}
result[X - 1]++;
if (max < result[X - 1]) {
max = result[X - 1];
}
}
if (X == N + 1) {
base = max;
needToChange= X-1;
}
}
for (int i = 0; i < needToChange; i++) {
if (result[i] < base) {
result[i] = base;
}
}
return result;
}
}
My Java solution. It gives 100% but is very long (in comparison). I have used HashMap for storing counters.
Detected time complexity: O(N + M)
import java.util.*;
class Solution {
final private Map<Integer, Integer> counters = new HashMap<>();
private int maxCounterValue = 0;
private int maxCounterValueRealized = 0;
public int[] solution(int N, int[] A) {
if (N < 1) return new int[0];
for (int a : A) {
if (a <= N) {
Integer current = counters.putIfAbsent(a, maxCounterValueRealized + 1);
if (current == null) {
updateMaxCounterValue(maxCounterValueRealized + 1);
} else {
++current;
counters.replace(a, current);
updateMaxCounterValue(current);
}
} else {
maxCounterValueRealized = maxCounterValue;
counters.clear();
}
}
return getCountersArray(N);
}
private void updateMaxCounterValue(int currentCounterValue) {
if (currentCounterValue > maxCounterValue)
maxCounterValue = currentCounterValue;
}
private int[] getCountersArray(int N) {
int[] countersArray = new int[N];
for (int j = 0; j < N; j++) {
Integer current = counters.get(j + 1);
if (current == null) {
countersArray[j] = maxCounterValueRealized;
} else {
countersArray[j] = current;
}
}
return countersArray;
}
}
Here is solution in python with 100 %
Codility Max counter 100%
def solution(N, A):
"""
Solution at 100% - https://app.codility.com/demo/results/trainingUQ95SB-4GA/
Idea is first take the counter array of given size N
take item from main A one by one + 1 and put in counter array , use item as index
keep track of last max operation
at the end replace counter items with max of local or counter item it self
:param N:
:param A:
:return:
"""
global_max = 0
local_max = 0
# counter array
counter = [0] * N
for i, item in enumerate(A):
# take item from original array one by one - 1 - minus due to using item as index
item_as_counter_index = item - 1
# print(item_as_counter_index)
# print(counter)
# print(local_max)
# current element less or equal value in array and greater than 1
# if A[K] = X, such that 1 ≤ X ≤ N, then operation K is increase(X),
if N >= item >= 1:
# max of local_max counter at item_as_counter_index
# increase counter array value and put in counter array
counter[item_as_counter_index] = max(local_max, counter[item_as_counter_index]) + 1
# track the status of global_max counter so far
# this is operation K
global_max = max(global_max, counter[item_as_counter_index])
# if A[K] = N + 1 then operation K is max counter.
elif item == N + 1:
# now operation k is as local max
# here we need to replace all items in array with this global max
# we can do using for loop for array length but that will cost bigo n2 complexity
# example - for i, item in A: counter[i] = global_max
local_max = global_max
# print("global_max each step")
# print(global_max)
# print("local max so far....")
# print(local_max)
# print("counter - ")
# print(counter)
# now counter array - replace all elements which are less than the local max found so far
# all counters are set to the maximum value of any counter
for i, item in enumerate(counter):
counter[i] = max(item, local_max)
return counter
result = solution(1, [3, 4, 4, 6, 1, 4, 4])
print("Sol " + str(result))
enter link description here
Got 100% result with O ( N + M )
class Solution {
public int[] solution(int N, int[] A) {
// write your code in Java SE 8
int max = 0;
int[] counter = new int[N];
int upgrade = 0;
for ( int i = 0; i < A.length; i++ )
{
if ( A[i] <= N )
{
if ( upgrade > 0 && upgrade > counter[A[i] - 1 ] )
{
counter[A[i] - 1] = upgrade;
}
counter[A[i] - 1 ]++;
if ( counter[A[i] - 1 ] > max )
{
max = counter[A[i] - 1 ];
}
}
else
{
upgrade = max;
}
}
for ( int i = 0; i < N; i++ )
{
if ( counter[i] < upgrade)
{
counter[i] = upgrade;
}
}
return counter;
}
}
Java 100%/100%, no imports
public int[] solution(int N, int[] A) {
int[] counters = new int[N];
int currentMax = 0;
int sumOfMaxCounters = 0;
boolean justDoneMaxCounter = false;
for (int i = 0; i < A.length ; i++) {
if (A[i] <= N) {
justDoneMaxCounter = false;
counters[A[i]-1]++;
currentMax = currentMax < counters[A[i]-1] ? counters[A[i]-1] : currentMax;
}else if (!justDoneMaxCounter){
sumOfMaxCounters += currentMax;
currentMax = 0;
counters = new int[N];
justDoneMaxCounter = true;
}
}
for (int j = 0; j < counters.length; j++) {
counters[j] = counters[j] + sumOfMaxCounters;
}
return counters;
}
python solution: 100% 100%
def solution(N, A):
c = [0] * N
max_element = 0
base = 0
for item in A:
if item >= 1 and N >= item:
c[item-1] = max(c[item-1], base) + 1
max_element = max(c[item - 1], max_element)
elif item == N + 1:
base = max_element
for i in range(N):
c[i] = max (c[i], base)
return c
pass
Using applyMax to record max operations
Time complexity:
O(N + M)
class Solution {
public int[] solution(int N, int[] A) {
// write your code in Java SE 8
int max = 0, applyMax = 0;;
int[] result = new int[N];
for (int i = 0; i < A.length; ++i) {
int a = A[i];
if (a == N + 1) {
applyMax = max;
}
if (1 <= a && a <= N) {
result[A[i] - 1] = Math.max(applyMax, result[A[i] - 1]);
max = Math.max(max, ++result[A[i] - 1]);
}
}
for (int i = 0; i < N; ++i) {
if (result[i] < applyMax) {
result[i] = applyMax;
}
}
return result;
}
}
Related
I have an array with several numbers:
int[] tab = {1,2,3,4};
I have to create two methods the first is the sum() method and the second is numberOdd().
It's Ok for this step !
int length = tab.length;
length = numberOdd(tab,length);
int sum_odd = sum(tab, length);
System.out.println(" 1) - Calculate the sum of the odds numbers : => " + sum_odd);
public static int sum(int[] tab, int length){
int total = 0;
for(int i=0;i<length;i++){
total += tab[i];
}
return total;
}
public static int numberOdd(int[] tab, int length){
int n = 0;
for(int i=0;i<length;i++){
if(tab[i] % 2 != 0){
tab[n++] = tab[i];
}
}
return n;
}
Now, I have to add the even numbers with the numberEven() method and I get the value "0".
I don't understand why I retrieve the value => 0 ???????
Here is my code:
int[] tab = {1,2,3,4};
int length = tab.length;
length = numberOdd(tab,length);
int sum_odd = sum(tab, length);
length = numberEven(tab,length);
int sum_even = sum(tab, length);
System.out.println(" 1) - Calculate the sum of the odds numbers : => " + sum_odd);
System.out.println(" 2) - Calculate the sum of the evens numbers : => " + sum_even);
}
public static int numberEven(int[] tab, int length){
int n = 0;
for(int i=0;i<length;i++){
if(tab[i] % 2 == 0){
tab[n++] = tab[i];
}
}
return n;
}
For information: I share the code here => https://repl.it/repls/CriminalAdolescentKilobyte
Thank you for your help.
You need to add tab[i] to n
Having length as a parameter to numberEven does not cause any harm but you don't need it.
Given below is the working example:
public class Main {
public static void main(String[] args) {
int[] tab = { 1, 2, 3, 4 };
System.out.println(numberEven(tab));
}
public static int numberEven(int[] tab) {
int n = 0;
for (int i = 0; i < tab.length; i++) {
if (tab[i] % 2 == 0) {
n += tab[i];
}
}
return n;
}
}
Output:
6
you have changed the array in your numberOdd() method.
try replacing tab[n++] = tab[i]; with n++;
public static int sumEven(int[] tab){
int sumEven = 0;
for(int i=0;i<tab.length;i++){
if(tab[i] % 2 == 0){
sumEven = sumEven + tab[i];
}
}
return sumEven;
}
This should work.
I have the following problem:
You are given N counters, initially set to 0, and you have two possible operations on them:
increase(X) − counter X is increased by 1,
max counter − all counters are set to the maximum value of any counter.
A non-empty zero-indexed array A of M integers is given. This array represents consecutive operations:
if A[K] = X, such that 1 ≤ X ≤ N, then operation K is increase(X),
if A[K] = N + 1 then operation K is max counter.
For example, given integer N = 5 and array A such that:
A[0] = 3
A[1] = 4
A[2] = 4
A[3] = 6
A[4] = 1
A[5] = 4
A[6] = 4
the values of the counters after each consecutive operation will be:
(0, 0, 1, 0, 0)
(0, 0, 1, 1, 0)
(0, 0, 1, 2, 0)
(2, 2, 2, 2, 2)
(3, 2, 2, 2, 2)
(3, 2, 2, 3, 2)
(3, 2, 2, 4, 2)
The goal is to calculate the value of every counter after all operations.
Write a function:
class Solution { public int[] solution(int N, int[] A); }
that, given an integer N and a non-empty zero-indexed array A consisting of M integers, returns a sequence of integers representing the values of the counters.
For example, given:
A[0] = 3
A[1] = 4
A[2] = 4
A[3] = 6
A[4] = 1
A[5] = 4
A[6] = 4
the function should return [3, 2, 2, 4, 2], as explained above.
Assume that:
N and M are integers within the range [1..100,000];
each element of array A is an integer within the range [1..N + 1].
Complexity:
expected worst-case time complexity is O(N+M);
expected worst-case space complexity is O(N), beyond input storage (not counting the storage required for input arguments).
Elements of input arrays can be modified.
I have answered this problem using the following code, but only got 80% as opposed to 100% performance, despite having O(N+M) time complexity:
public class Solution {
public int[] solution(int N, int[] A) {
int highestCounter = N;
int minimumValue = 0;
int lastMinimumValue = 0;
int [] answer = new int[N];
for (int i = 0; i < A.length; i++) {
int currentCounter = A[i];
int answerEquivalent = currentCounter -1;
if(currentCounter >0 && currentCounter<=highestCounter){
answer[answerEquivalent] = answer[answerEquivalent]+1;
if(answer[answerEquivalent] > minimumValue){
minimumValue = answer[answerEquivalent];
}
}
if (currentCounter == highestCounter +1 && lastMinimumValue!=minimumValue){
lastMinimumValue = minimumValue;
Arrays.fill(answer, minimumValue);
}
}
return answer;
}
}
Where is my performance here suffering? The code gives the right answer, but does not perform up-to-spec despite having the right time complexity.
Instead of calling Arrays.fill(answer, minimumValue); whenever you encounter a "max counter" operation, which takes O(N), you should keep track of the last max value that was assigned due to "max counter" operation, and update the entire array just one time, after all the operations are processed. This would take O(N+M).
I changed the variables names from min to max to make it less confusing.
public class Solution {
public int[] solution(int N, int[] A) {
int highestCounter = N;
int maxValue = 0;
int lastMaxValue = 0;
int [] answer = new int[N];
for (int i = 0; i < A.length; i++) {
int currentCounter = A[i];
int answerEquivalent = currentCounter -1;
if(currentCounter >0 && currentCounter<=highestCounter){
if (answer[answerEquivalent] < lastMaxValue)
answer[answerEquivalent] = lastMaxValue +1;
else
answer[answerEquivalent] = answer[answerEquivalent]+1;
if(answer[answerEquivalent] > maxValue){
maxValue = answer[answerEquivalent];
}
}
if (currentCounter == highestCounter +1){
lastMaxValue = maxValue;
}
}
// update all the counters smaller than lastMaxValue
for (int i = 0; i < answer.length; i++) {
if (answer[i] < lastMaxValue)
answer[i] = lastMaxValue;
}
return answer;
}
}
The following operation is O(n) time:
Arrays.fill(answer, minimumValue);
Now, if you are given a test case where the max counter operation is repeated often (say n/3 of the total operations) - you got yourself an O(n*m) algorithm (worst case analysis), and NOT O(n+m).
You can optimize it to be done in O(n+m) time, by using an algorithm that initializes an array in O(1) every time this operation happens.
This will reduce worst case time complexity from O(n*m) to O(n+m)1
(1)Theoretically, using the same idea, it can even be done in O(m) - regardless of the size of the number of counters, but the first allocation of the arrays takes O(n) time in java
This is a bit like #Eran's solution but encapsulates the functionality in an object. Essentially - keep track of a max value and an atLeast value and let the object's functionality do the rest.
private static class MaxCounter {
// Current set of values.
final int[] a;
// Keeps track of the current max value.
int currentMax = 0;
// Min value. If a[i] < atLeast the a[i] should appear as atLeast.
int atLeast = 0;
public MaxCounter(int n) {
this.a = new int[n];
}
// Perform the defined op.
public void op(int k) {
// Values are one-based.
k -= 1;
if (k < a.length) {
// Increment.
inc(k);
} else {
// Set max
max(k);
}
}
// Increment.
private void inc(int k) {
// Get new value.
int v = get(k) + 1;
// Keep track of current max.
if (v > currentMax) {
currentMax = v;
}
// Set new value.
a[k] = v;
}
private int get(int k) {
// Returns eithe a[k] or atLeast.
int v = a[k];
return v < atLeast ? atLeast : v;
}
private void max(int k) {
// Record new max.
atLeast = currentMax;
}
public int[] solution() {
// Give them the solution.
int[] solution = new int[a.length];
for (int i = 0; i < a.length; i++) {
solution[i] = get(i);
}
return solution;
}
#Override
public String toString() {
StringBuilder s = new StringBuilder("[");
for (int i = 0; i < a.length; i++) {
s.append(get(i));
if (i < a.length - 1) {
s.append(",");
}
}
return s.append("]").toString();
}
}
public void test() {
System.out.println("Hello");
int[] p = new int[]{3, 4, 4, 6, 1, 4, 4};
MaxCounter mc = new MaxCounter(5);
for (int i = 0; i < p.length; i++) {
mc.op(p[i]);
System.out.println(mc);
}
int[] mine = mc.solution();
System.out.println("Solution = " + Arrays.toString(mine));
}
My solution: 100\100
class Solution
{
public int maxCounterValue;
public int[] Counters;
public void Increase(int position)
{
position = position - 1;
Counters[position]++;
if (Counters[position] > maxCounterValue)
maxCounterValue = Counters[position];
}
public void SetMaxCounter()
{
for (int i = 0; i < Counters.Length; i++)
{
Counters[i] = maxCounterValue;
}
}
public int[] solution(int N, int[] A)
{
if (N < 1 || N > 100000) return null;
if (A.Length < 1) return null;
int nlusOne = N + 1;
Counters = new int[N];
int x;
for (int i = 0; i < A.Length; i++)
{
x = A[i];
if (x > 0 && x <= N)
{
Increase(x);
}
if (x == nlusOne && maxCounterValue > 0) // this used for all maxCounter values in array. Reduces addition loops
SetMaxCounter();
if (x > nlusOne)
return null;
}
return Counters;
}
}
( #molbdnilo : +1 !) As this is just an algorithm test, there's no sense getting too wordy about variables. "answerEquivalent" for a zero-based array index adjustment? Gimme a break ! Just answer[A[i] - 1] will do.
Test says to assume A values always lie between 1 and N+1. So checking for this is not needed.
fillArray(.) is an O(N) process which is within an O(M) process. This makes the whole code into an O(M*N) process when the max complexity desired is O(M+N).
The only way to achieve this is to only carry forward the current max value of the counters. This allows you to always save the correct max counter value when A[i] is N+1. The latter value is a sort of baseline value for all increments afterwards. After all A values are actioned, those counters which were never incremented via array entries can then be brought up to the all-counters baseline via a second for loop of complexity O(N).
Look at Eran's solution.
This is how we can eliminate O(N*M) complexity.
In this solutions, instead of populating result array for every A[K]=N+1, I tried to keep what is min value of all elements, and update result array once all operation has been completed.
If there is increase operation then updating that position :
if (counter[x - 1] < minVal) {
counter[x - 1] = minVal + 1;
} else {
counter[x - 1]++;
}
And keep track of minVal for each element of result array.
Here is complete solution:
public int[] solution(int N, int[] A) {
int minVal = -1;
int maxCount = -1;
int[] counter = new int[N];
for (int i = 0; i < A.length; i++) {
int x = A[i];
if (x > 0 && x <= N) {
if (counter[x - 1] < minVal) {
counter[x - 1] = minVal + 1;
} else {
counter[x - 1]++;
}
if (maxCount < counter[x - 1]) {
maxCount = counter[x - 1];
}
}
if (x == N + 1 && maxCount > 0) {
minVal = maxCount;
}
}
for (int i = 0; i < counter.length; i++) {
if (counter[i] < minVal) {
counter[i] = minVal;
}
}
return counter;
}
This is my swift 3 solution (100/100)
public func solution(_ N : Int, _ A : inout [Int]) -> [Int] {
var counters = Array(repeating: 0, count: N)
var _max = 0
var _min = 0
for i in A {
if counters.count >= i {
let temp = max(counters[i-1] + 1, _min + 1)
_max = max(temp, _max)
counters[i-1] = temp
} else {
_min = _max
}
}
return counters.map { max($0, _min) }
}
How to sort array
int[] A = {0,1,1,0,1,0,1,1,0}
You can actually sort this array by traversing the array only once.
Here is the snippet of my code:
int arr[] = {1,1,1,1,0, 0,1,0,1,1,1};
int arrb[] = new int[arr.length];
int zeroInsertIndex = 0;
int oneInsertIndex =arrb.length-1;
for(int i=0; i<arr.length; i++){
if(arr[i] == 1)
arrb[oneInsertIndex--] = 1;
else if (arr[i] == 0)
arrb[zeroInsertIndex++] = 0;
}
for(int i=0;i<arrb.length;i++)
System.out.print(arrb[i] + " ");
Although Arrays.sort is an obvious, simple, O(n log n) solution, there is an O(n) solution for this special case:
Count the number of zeros, zeroCount.
Fill the first zeroCount elements with 0, the remaining elements with 1.
This takes just two passes over the array.
More generally, any array with only a small number of distinct values can be sorted by counting how many times each value appears, then filling in the array accordingly.
use any sorting algorithm to do it. For beginner use bubble sort (easy to understand)
Refer Wiki
public static void bubble_srt( int a[], int n ){
int i, j,t=0;
for(i = 0; i < n; i++){
for(j = 1; j < (n-i); j++){
if(a[j-1] > a[j]){
t = a[j-1];
a[j-1]=a[j];
a[j]=t;
}
}
}
}
EDITED
As #Pradeep Said: You may definitely use Array.sort()
Your array contains only zeros and one so sum all the elements in the array and then reset the array with those many '1's in the end and rest '0's in the beginning. Time complexity is also O(n) with constant space. So it seems the best and easy one.
public static void main(String[] args) {
int[] A = { 0, 1, 1, 0, 1, 0, 1, 1, 0 };
int sum = 0;
for (int i = 0; i < A.length; i++)
sum = sum + A[i];
Arrays.fill(A, A.length - sum, A.length, 1);
Arrays.fill(A, 0, A.length - sum, 0);
System.out.println(Arrays.toString(A));
}
Try this I implemented the above algorithm.
Output:
[0, 0, 0, 0, 1, 1, 1, 1, 1]
You can use Arrays.sort method from Arrays class:
int[] A = {0,1,1,0,1,0,1,1,0};
Arrays.sort(A);
System.out.println(A);
Actually standard off-the-shelf sorting algorithms will typically work on O(n*log(n)). You could just run through the array once adding all the values (i.e. the number of 1). Let's say you put this in count1. Then go once more over the array setting the first count1 positions to 1, and the rest to 0. It takes 2n steps.
Of course, as other posters said: this kind of optimizations is what you do once you've detected a bottleneck, not right off the bat when you start.
Arrays.sort(A,Collections.reverseOrder());
USE
Arrays.sort(A);
method to sort your array.
You can try like this also
public static void main(String[] args) {
int inputArray[] = { 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0 };
formatInputArray(inputArray);
}
private static void formatInputArray(int[] inputArray) {
int count = 0;
for (int i = 0; i < inputArray.length; i++) {
if (inputArray[i] == 0) {
count++;
}
}
// System.out.println(count);
for (int i = 0; i < inputArray.length; i++) {
if (i < count) {
inputArray[i] = 0;
}
else {
inputArray[i] = 1;
}
}
for (int i = 0; i < inputArray.length; i++) {
System.out.print(inputArray[i] + " , ");
}
}
Sort Array which contains only 0,1 and 2
import java.util.*;
public class HelloWorld {
static void sort012(int []a, int length) {
int start = 0;
int mid = 0;
int end = length - 1;
int temp;
while(mid<=end) {
switch(a[mid]) {
case 0:
temp = a[start];
a[start] = a[mid];
a[mid] = temp;
start++;
mid++;
break;
case 1:
mid++;
break;
case 2:
temp = a[end];
a[end] = a[mid];
a[mid] = temp;
end--;
break;
}
}
}
public static void main(String []args){
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int a[] = new int[n];
for (int i =0;i<n; i++)
a[i] = sc.nextInt();
HelloWorld.sort012(a, n);
// Print the sorted Array
for (int i =0;i<n; i++)
System.out.println(a[i]);
}
}
var binaryArr = [1,1,1,0,1,0,1,0,1,1,1,1,1,1,1,1,0,0,1,0,1,0,0,0,0];
//i - starting index
//j - ending index
function binarySort(arr){
var i=0,j=arr.length-1;
for(;i!=j;){
if(arr[i] == 1){
if(arr[j] == 0){
arr[i] = 0;
arr[j] = 1;
j--;
i++;
} else {
j--;
}
}else{
i++;
}
}
}
binarySort(binaryArr);
Team
Please consider the below program in Swift in o(n) time complexity and constant extra space.
import UIKit
var inputArray = [1,0,1,0,0,0,0,1,1,1,1,1,1]
var leftIndex: Int = 0
var rightIndex: Int = inputArray.count-1
while leftIndex < rightIndex{
while inputArray[leftIndex] == 0 && leftIndex < rightIndex{
leftIndex = leftIndex+1
}
while inputArray[rightIndex] == 1 && rightIndex > leftIndex {
rightIndex = rightIndex-1
}
if leftIndex < rightIndex{
inputArray[leftIndex] = 0
inputArray[rightIndex] = 1
leftIndex = leftIndex+1
rightIndex = rightIndex-1
}
}
print(inputArray)
Sort 0 and 1 array using below code:
public static int[] sortArray(int[] array){
int first = 0;
int last = array.length-1;
while(first<last){
if(array[first]==0){
first++;
}else if(array[last] == 0){
int temp = array[last];
array[last] = array[first];
array[first] = temp;
first++;
}else{
last--;
}
}
return array;
}
public static void sort(int a[]) {
int sum=0;
int b[]= new int [a.length];
for(int i=0;i<a.length;i++) {
sum=sum+a[i];
}
System.out.println(sum);
int j=b.length-1;
while(sum>0) {
b[j]=1;
sum--;
j--;
}
System.out.println(Arrays.toString(b));
}
public class Test {
public static void main(String[] args) {
int[] arr = {0, 1, 0, 1, 0, 0, 1, 1, 1, 0};
int start = 0;
for (int i = 0; i < arr.length; i++) {
if (arr[i] == 0) {
arr[start] = 0;
if (i != start) { // should not override same value with 1
arr[i] = 1;
}
start++;
}
}
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
}
}
//complexity is O(n)
If its just 0's and 1's, it can be done using two pointers.
c# code snippet :
int i = 0; int j = input.Length - 1;
while (i < j)
{
if (input[i] == 0 && input[j] == 0)
i++;
else if(input[i] == 1 && input[j] == 1)
j--;
else if (input[i] > input[j])
{
input[i++] = 0;
input[j--] = 1;
}
else
{
i++; j--;
}
}
int[] a = {0,1,1,0,1,0,1,1,0}
Here, we are iterating with i where i starts from 1. so we can compare previous index value with the current value of i. Used swapping technique to sort the array.
Note: Sort/2 pointer technique we can also use.
public int[] sort(int[] a){
int temp=0;
for(int i=1;i<a.length;i++){
if( a[i-1] > a[i]){
temp = a[i-1];
a[i-1] = a[i];
a[i] = temp;
}
}
return a[i];
}
Time complexity : O(n)
The following code will sort your array. Please notice that it does so in place - so it modifies the object in memory instead of returning a new one.
In Python
arr=[0,1,0,0,1,1,1,0,1,1,0]
arr.sort()
print(arr)
In Java
public class test{
public static void main(String[] args){
int[] arr= {0,1,0,0,1,1,1,0,1,1,0};
Arrays.sort(arr);
System.out.println(Arrays.toString(arr));
}}
public static void main(String[] args) {
int arr[]= {0,-1,2,-3,5,9,-5,10};
int max_ending_here=0;
int max_so_far=0;
int start =0;
int end=0;
for(int i=0;i< arr.length;i++)
{
max_ending_here=max_ending_here+arr[i];
if(max_ending_here<0)
{
max_ending_here=0;
}
if(max_so_far<max_ending_here){
max_so_far=max_ending_here;
}
}
System.out.println(max_so_far);
}
}
this program generates the max sum of sub array ..in this case its 19,using {5,9,-5,10}..
now i have to find the start and end index of this sub array ..how do i do that ??
This is a C program to solve this problem. I think logic is same for all languages so I posted this answer.
void findMaxSubArrayIndex(){
int n,*a;
int start=0,end=0,curr_max=0,prev_max=0,start_o=0,i;
scanf("%d",&n);
a = (int*)malloc(sizeof(int)*n);
for(i=0; i<n; i++) scanf("%d",a+i);
prev_max = a[0];
for(i=0; i<n; i++){
curr_max += a[i];
if(curr_max < 0){
start = i+1;
curr_max = 0;
}
else if(curr_max > prev_max){
end = i;
start_o = start;
prev_max = curr_max;
}
}
printf("%d %d \n",start_o,end);
}
Fixing Carl Saldanha solution:
int max_ending_here = 0;
int max_so_far = 0;
int _start = 0;
int start = 0;
int end = -1;
for(int i=0; i<array.length; i++) {
max_ending_here = max_ending_here + array[i];
if (max_ending_here < 0) {
max_ending_here = 0;
_start = i+1;
}
if (max_ending_here > max_so_far) {
max_so_far = max_ending_here;
start = _start;
end = i;
}
}
Here is algorithm for maxsubarray:
public class MaxSubArray {
public static void main(String[] args) {
int[] intArr={3, -1, -1, -1, -1, -1, 2, 0, 0, 0 };
//int[] intArr = {-1, 3, -5, 4, 6, -1, 2, -7, 13, -3};
//int[] intArr={-6,-2,-3,-4,-1,-5,-5};
findMaxSubArray(intArr);
}
public static void findMaxSubArray(int[] inputArray){
int maxStartIndex=0;
int maxEndIndex=0;
int maxSum = Integer.MIN_VALUE;
int cumulativeSum= 0;
int maxStartIndexUntilNow=0;
for (int currentIndex = 0; currentIndex < inputArray.length; currentIndex++) {
int eachArrayItem = inputArray[currentIndex];
cumulativeSum+=eachArrayItem;
if(cumulativeSum>maxSum){
maxSum = cumulativeSum;
maxStartIndex=maxStartIndexUntilNow;
maxEndIndex = currentIndex;
}
if (cumulativeSum<0){
maxStartIndexUntilNow=currentIndex+1;
cumulativeSum=0;
}
}
System.out.println("Max sum : "+maxSum);
System.out.println("Max start index : "+maxStartIndex);
System.out.println("Max end index : "+maxEndIndex);
}
}
Here is a solution in python - Kadane's algorithm extended to print the start/end indexes
def max_subarray(array):
max_so_far = max_ending_here = array[0]
start_index = 0
end_index = 0
for i in range(1, len(array) -1):
temp_start_index = temp_end_index = None
if array[i] > (max_ending_here + array[i]):
temp_start_index = temp_end_index = i
max_ending_here = array[i]
else:
temp_end_index = i
max_ending_here = max_ending_here + array[i]
if max_so_far < max_ending_here:
max_so_far = max_ending_here
if temp_start_index != None:
start_index = temp_start_index
end_index = i
print max_so_far, start_index, end_index
if __name__ == "__main__":
array = [-2, 1, -3, 4, -1, 2, 1, 8, -5, 4]
max_subarray(array)
In python solving 3 problem i.e., sum, array elements and index.
def max_sum_subarray(arr):
current_sum = arr[0]
max_sum = arr[0]
curr_array = [arr[0]]
final_array=[]
s = 0
start = 0
e = 0
end = 0
for i in range(1,len(arr)):
element = arr[i]
if current_sum+element > element:
curr_array.append(element)
current_sum = current_sum+element
e += 1
else:
curr_array = [element]
current_sum = element
s = i
if current_sum > max_sum:
final_array = curr_array[:]
start = s
end = e
max_sum = current_sum
print("Original given array is : ", arr)
print("The array elements that are included in the sum are : ",final_array)
print("The starting and ending index are {} and {} respectively.".format(start, end))
print("The maximum sum is : ", max_sum)
# Driver code
arr = [-12, 15, -13, 14, -1, 2, 1, -5, 4]
max_sum_subarray(arr)
By Om Prasad Nayak
Like This
public static void main(String[] args) {
int arr[]= {0,-1,2,-3,5,9,-5,10};
int max_ending_here=0;
int max_so_far=0;
int start =0;
int end=0;
for(int i=0;i< arr.length;i++){
max_ending_here=max_ending_here+arr[i];
if(max_ending_here<0)
{
start=i+1; //Every time it goes negative start from next index
max_ending_here=0;
}
else
end =i; //As long as its positive keep updating the end
if(max_so_far<max_ending_here){
max_so_far=max_ending_here;
}
}
System.out.println(max_so_far);
}
Okay so there was a problem in the above solution as pointed to Steve P. This is another solution which should work for all
public static int[] compareSub(int arr[]){
int start=-1;
int end=-1;
int max=0;
if(arr.length>0){
//Get that many array elements and compare all of them.
//Then compare their max to the overall max
start=0;end=0;max=arr[0];
for(int arrSize=1;arrSize<arr.length;arrSize++){
for(int i=0;i<arr.length-arrSize+1;i++){
int potentialMax=sumOfSub(arr,i,i+arrSize);
if(potentialMax>max){
max=potentialMax;
start=i;
end=i+arrSize-1;
}
}
}
}
return new int[]{start,end,max};
}
public static int sumOfSub(int arr[],int start,int end){
int sum=0;
for(int i=start;i<end;i++)
sum+=arr[i];
return sum;
}
The question is somewhat unclear but I'm guessing a "sub-array" is half the arr object.
A lame way to do this like this
public int sum(int[] arr){
int total = 0;
for(int index : arr){
total += index;
}
return total;
}
public void foo(){
int arr[] = {0,-1,2,-3,5,9,-5,10};
int subArr1[] = new int[(arr.length/2)];
int subArr2[] = new int[(arr.length/2)];
for(int i = 0; i < arr.length/2; i++){
// Lazy hack, might want to double check this...
subArr1[i] = arr[i];
subArr2[i] = arr[((arr.length -1) -i)];
}
int sumArr1 = sum(subArr1);
int sumArr2 = sum(subArr2);
}
I image this might not work if the arr contains an odd number of elements.
If you want access to a higher level of support convert the primvate arrays to a List object
List<Integer> list = Arrays.asList(arr);
This way you have access to a collection object functionality.
Also if you have the time, take a look at the higher order functional called reduce. You will need a library that supports functional programming. Guava or lambdaJ might have a reduce method. I know that apache-commons lacks one, unless you want to hack to together it.
The only thing I have to add (to several solutions posted here) is to cover the case that all the integers are negative, in which case the max sub array will be just the max element. Pretty easy to do that.. just have to track max element and index of the index of the max element as you iterate through it. If the max element is negative, return it's index instead.
There is also the case of overflow to possibly handle. I've seen algorithm tests that take than into account.. IE, suppose MAXINT was one of the elements and you tried to add to it. I believe some of the Codility (coding interview screeners) tests take that into account.
public static void maxSubArray(int []arr){
int sum=0,j=0;
int temp[] = new int[arr.length];
for(int i=0;i<arr.length;i++,j++){
sum = sum + arr[i];
if(sum <= 0){
sum =0;
temp[j] = -1;
}else{
temp[j] = i;
}
}
rollback(temp,arr);
}
public static void rollback(int [] temp , int[] arr){
int s =0,start=0 ;
int maxTillNow = 0,count =0;
String str1 = "",str2="";
System.out.println("============");
// find the continuos index
for(int i=0;i<temp.length;i++){
if(temp[i] != -1){
s += arr[temp[i]];
if(s > maxTillNow){
if(count == 0){
str1 = "" + start;
}
count++;
maxTillNow = s;
str2 = " " + temp[i];
}
}else{
s=0;
count =0;
if(i != temp.length-1)
start = temp[i+1];
}
}
System.out.println("Max sum will be ==== >> " + maxTillNow);
System.out.print("start from ---> "+str1 + " end to --- >> " +str2);
}
public void MaxSubArray(int[] arr)
{
int MaxSoFar = 0;
int CurrentMax = 0;
int ActualStart=0,TempStart=0,End = 0;
for(int i =0 ; i<arr.Length;i++)
{
CurrentMax += arr[i];
if(CurrentMax<0)
{
CurrentMax = 0;
TempStart = i + 1;
}
if(MaxSoFar<CurrentMax)
{
MaxSoFar = CurrentMax;
ActualStart = TempStart;
End = i;
}
}
Console.WriteLine(ActualStart.ToString()+End.ToString());
}
An O(n) solution in C would be :-
void maxsumindex(int arr[], int len)
{
int maxsum = INT_MIN, cur_sum = 0, start=0, end=0, max = INT_MIN, maxp = -1, flag = 0;
for(int i=0;i<len;i++)
{
if(max < arr[i]){
max = arr[i];
maxp = i;
}
cur_sum += arr[i];
if(cur_sum < 0)
{
cur_sum = 0;
start = i+1;
}
else flag = 1;
if(maxsum < cur_sum)
{
maxsum = cur_sum;
end = i;
}
}
//This is the case when all elements are negative
if(flag == 0)
{
printf("Max sum subarray = {%d}\n",arr[maxp]);
return;
}
printf("Max sum subarray = {");
for(int i=start;i<=end;i++)
printf("%d ",arr[i]);
printf("}\n");
}
Here is a solution in Go using Kadane's Algorithm
func maxSubArr(A []int) (int, int, int) {
start, currStart, end, maxSum := 0, 0, 0, A[0]
maxAtI := A[0]
for i := 1; i < len(A); i++ {
if maxAtI > 0 {
maxAtI += A[i]
} else {
maxAtI = A[i]
currStart = i
}
if maxAtI > maxSum {
maxSum = maxAtI
start = currStart
end = i
}
}
return start, end, maxSum
}
Here is a C++ solution.
void maxSubArraySum(int *a, int size) {
int local_max = a[0];
int global_max = a[0];
int sum_so_far = a[0];
int start = 0, end = 0;
int tmp_start = 0;
for (int i = 1; i < size; i++) {
sum_so_far = a[i] + local_max;
if (sum_so_far > a[i]) {
local_max = sum_so_far;
} else {
tmp_start = i;
local_max = a[i];
}
if (global_max < local_max) {
global_max = local_max;
start = tmp_start;
end = i;
}
}
cout<<"Start Index: "<<start<<endl;
cout<<"End Index: "<<end<<endl;
cout<<"Maximum Sum: "<<global_max<<endl;
}
int main() {
int arr[] = {4, -3, -2, 2, 3, 1, -2, -3, 4,2, -6, -3, -1, 3, 1, 2};
maxSubArraySum(arr, sizeof(arr)/sizeof(arr[0]));
return 0;
}
pair<int,int> maxSumPair(vector<int> arr) {
int n = arr.size();`
int currSum = arr[0], maxSoFar = arr[0];
int start = 0, end ,prev = currSum;
unordered_map<int,pair<int,int>> mp;
for(int i = 1 ; i < n ; i++) {
prev = currSum;
if(currSum == arr[i]) {
end = i-1;
mp.insert({currSum,{start,end}});
start = i;
}
if(maxSoFar < currSum) {
maxSoFar = currSum;
end = i;
mp.insert({currSum,{start,end}});
}
}
int maxSum = INT_MIN;
for(auto it: mp) {
if(it.first > maxSum) {
maxSum = it.first;
}
}
return mp[maxSum];
}
int maxSubarraySum(int arr[], int n){
int max_so_far = -1 * Integer.MAX_VALUE;
int max_curr = 0;
int start = 0;
int end = 0;
for(int i=0; i < arr.length; i++){
max_curr = max_curr + arr[i];
if(max_so_far < max_curr){
max_so_far = max_curr;
}
if( max_curr < 0){
max_curr = 0;
start = i+1;
}
else
end = i;
}
start = end < start ? end : start;
System.out.println( start + "..." + end);
return max_so_far;
}
Maximum sub array in golang implementation
package main
import (
"fmt"
)
func main() {
in := []int{-2, -12, 23, -10, 11, -6, -1}
a, b := max(in)
fmt.Println(a)
fmt.Println(b)
}
func max(in []int) ([]int, int) {
var p, r, sum, sf, psf int
if len(in) == 0 {
return in, 0
}
sum = in[0]
for i, n := range in {
sf += n
if sf > sum {
sum = sf
p = psf
r = i
}
if sf <= 0 {
psf = i + 1
sf = 0
}
}
return in[p : r+1], sum
}
I think this will help to get the start and end index
// Time Complexity = O(N)
// Space Complexity = O(1)
public static int maxSum2(int[] nums){
int globalSum = Integer.MIN_VALUE;
int currentSum = 0;
int start=0;
int end=0;
for(int i=0; i<nums.length;i++){
currentSum += nums[i];
if (currentSum>globalSum){
globalSum = currentSum;
end = i;
}
if (currentSum<0){
currentSum=0;
start = i+1;
}
}
System.out.println(start + " " + end);
return globalSum;
}
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I just had a codility problem give me a hard time and I'm still trying to figure out how the space and time complexity constraints could have been met.
The problem is as follows:
A dominant member in the array is one that occupies over half the positions in the array, for example:
{3, 67, 23, 67, 67}
67 is a dominant member because it appears in the array in 3/5 (>50%) positions.
Now, you are expected to provide a method that takes in an array and returns an index of the dominant member if one exists and -1 if there is none.
Easy, right? Well, I could have solved the problem handily if it were not for the following constraints:
Expected time complexity is O(n)
Expected space complexity is O(1)
I can see how you could solve this for O(n) time with O(n) space complexities as well as O(n^2) time with O(1) space complexities, but not one that meets both O(n) time and O(1) space.
I would really appreciate seeing a solution to this problem. Don't worry, the deadline has passed a few hours ago (I only had 30 minutes), so I'm not trying to cheat. Thanks.
Googled "computing dominant member of array", it was the first result. See the algorithm described on page 3.
element x;
int count ← 0;
For(i = 0 to n − 1) {
if(count == 0) { x ← A[i]; count++; }
else if (A[i] == x) count++;
else count−−;
}
Check if x is dominant element by scanning array A
Basically observe that if you find two different elements in the array, you can remove them both without changing the dominant element on the remainder. This code just keeps tossing out pairs of different elements, keeping track of the number of times it has seen the single remaining unpaired element.
Find the median with BFPRT, aka median of medians (O(N) time, O(1) space). Then scan through the array -- if one number dominates, the median will be equal to that number. Walk through the array and count the number of instances of that number. If it's over half the array, it's the dominator. Otherwise, there is no dominator.
Adding a Java 100/100 O(N) time with O(1) space:
https://codility.com/demo/results/demoPNG8BT-KEH/
class Solution {
public int solution(int[] A) {
int indexOfCandidate = -1;
int stackCounter = 0, candidate=-1, value=-1, i =0;
for(int element: A ) {
if (stackCounter == 0) {
value = element;
++stackCounter;
indexOfCandidate = i;
} else {
if (value == element) {
++stackCounter;
} else {
--stackCounter;
}
}
++i;
}
if (stackCounter > 0 ) {
candidate = value;
} else {
return -1;
}
int countRepetitions = 0;
for (int element: A) {
if( element == candidate) {
++countRepetitions;
}
if(countRepetitions > (A.length / 2)) {
return indexOfCandidate;
}
}
return -1;
}
}
If you want to see the Java source code it's here, I added some test cases as comments as the beginning of the file.
Java solution with score 100%
public int solution(int[] array) {
int candidate=0;
int counter = 0;
// Find candidate for leader
for(int i=0; i<array.length; i++){
if(counter == 0) candidate = i;
if(array[i] == array[candidate]){
counter++;
}else {
counter--;
}
}
// Count candidate occurrences in array
counter = 0;
for(int i=0; i<array.length; i++){
if(array[i] == array[candidate]) counter++;
}
// Check that candidate occurs more than array.lenght/2
return counter>array.length/2 ? candidate : -1;
}
In python, we are lucky some smart people have bothered to implement efficient helpers using C and shipped it in the standard library. The collections.Counter is useful here.
>>> data = [3, 67, 23, 67, 67]
>>> from collections import Counter
>>> counter = Counter(data) # counter accepts any sequence/iterable
>>> counter # dict like object, where values are the occurrence
Counter({67: 3, 3: 1, 23: 1})
>>> common = counter.most_common()[0]
>>> common
(67, 3)
>>> common[0] if common[1] > len(data) / 2.0 + 1 else -1
67
>>>
If you prefer a function here is one ...
>>> def dominator(seq):
counter = Counter(seq)
common = counter.most_common()[0]
return common[0] if common[1] > len(seq) / 2.0 + 1 else -1
...
>>> dominator([1, 3, 6, 7, 6, 8, 6])
-1
>>> dominator([1, 3, 6, 7, 6, 8, 6, 6])
6
This question looks hard if a small trick does not come to the mind :). I found this trick in this document of codility : https://codility.com/media/train/6-Leader.pdf.
The linear solution is explained at the bottom of this document.
I implemented the following java program which gave me a score of 100 on the same lines.
public int solution(int[] A) {
Stack<Integer> stack = new Stack<Integer>();
for (int i =0; i < A.length; i++)
{
if (stack.empty())
stack.push(new Integer(A[i]));
else
{
int topElem = stack.peek().intValue();
if (topElem == A[i])
{
stack.push(new Integer(A[i]));
}
else
{
stack.pop();
}
}
}
if (stack.empty())
return -1;
int elem = stack.peek().intValue();
int count = 0;
int index = 0;
for (int i = 0; i < A.length; i++)
{
if (elem == A[i])
{
count++;
index = i;
}
}
if (count > ((double)A.length/2.0))
return index;
else
return -1;
}
Here's my C solution which scores 100%
int solution(int A[], int N) {
int candidate;
int count = 0;
int i;
// 1. Find most likely candidate for the leader
for(i = 0; i < N; i++){
// change candidate when count reaches 0
if(count == 0) candidate = i;
// count occurrences of candidate
if(A[i] == A[candidate]) count++;
else count--;
}
// 2. Verify that candidate occurs more than N/2 times
count = 0;
for(i = 0; i < N; i++) if(A[i] == A[candidate]) count++;
if (count <= N/2) return -1;
return candidate; // return index of leader
}
100%
import java.util.HashMap;
import java.util.Map;
class Solution {
public static int solution(int[] A) {
final int N = A.length;
Map<Integer, Integer> mapOfOccur = new HashMap((N/2)+1);
for(int i=0; i<N; i++){
Integer count = mapOfOccur.get(A[i]);
if(count == null){
count = 1;
mapOfOccur.put(A[i],count);
}else{
mapOfOccur.replace(A[i], count, ++count);
}
if(count > N/2)
return i;
}
return -1;
}
}
Does it have to be a particularly good algorithm? ;-)
static int dominant(final int... set) {
final int[] freqs = new int[Integer.MAX_VALUE];
for (int n : set) {
++freqs[n];
}
int dom_freq = Integer.MIN_VALUE;
int dom_idx = -1;
int dom_n = -1;
for (int i = set.length - 1; i >= 0; --i) {
final int n = set[i];
if (dom_n != n) {
final int freq = freqs[n];
if (freq > dom_freq) {
dom_freq = freq;
dom_n = n;
dom_idx = i;
} else if (freq == dom_freq) {
dom_idx = -1;
}
}
}
return dom_idx;
}
(this was primarily meant to poke fun at the requirements)
Consider this 100/100 solution in Ruby:
# Algorithm, as described in https://codility.com/media/train/6-Leader.pdf:
#
# * Iterate once to find a candidate for dominator.
# * Count number of candidate occurences for the final conclusion.
def solution(ar)
n_occu = 0
candidate = index = nil
ar.each_with_index do |elem, i|
if n_occu < 1
# Here comes a new dominator candidate.
candidate = elem
index = i
n_occu += 1
else
if candidate == elem
n_occu += 1
else
n_occu -= 1
end
end # if n_occu < 1
end
# Method result. -1 if no dominator.
# Count number of occurences to check if candidate is really a dominator.
if n_occu > 0 and ar.count {|_| _ == candidate} > ar.size/2
index
else
-1
end
end
#--------------------------------------- Tests
def test
sets = []
sets << ["4666688", [1, 2, 3, 4], [4, 6, 6, 6, 6, 8, 8]]
sets << ["333311", [0, 1, 2, 3], [3, 3, 3, 3, 1, 1]]
sets << ["313131", [-1], [3, 1, 3, 1, 3, 1]]
sets << ["113333", [2, 3, 4, 5], [1, 1, 3, 3, 3, 3]]
sets.each do |name, one_of_expected, ar|
out = solution(ar)
raise "FAILURE at test #{name.inspect}: #{out.inspect} not in #{expected.inspect}" if not one_of_expected.include? out
end
puts "SUCCESS: All tests passed"
end
Here is an easy to read, 100% score version in Objective-c
if (A.count > 100000)
return -1;
NSInteger occur = 0;
NSNumber *candidate = nil;
for (NSNumber *element in A){
if (!candidate){
candidate = element;
occur = 1;
continue;
}
if ([candidate isEqualToNumber:element]){
occur++;
}else{
if (occur == 1){
candidate = element;
continue;
}else{
occur--;
}
}
}
if (candidate){
occur = 0;
for (NSNumber *element in A){
if ([candidate isEqualToNumber:element])
occur++;
}
if (occur > A.count / 2)
return [A indexOfObject:candidate];
}
return -1;
100% score JavaScript solution. Technically it's O(nlogn) but still passed.
function solution(A) {
if (A.length == 0)
return -1;
var S = A.slice(0).sort(function(a, b) {
return a - b;
});
var domThresh = A.length/2;
var c = S[Math.floor(domThresh)];
var domCount = 0;
for (var i = 0; i < A.length; i++) {
if (A[i] == c)
domCount++;
if (domCount > domThresh)
return i;
}
return -1;
}
This is the solution in VB.NET with 100% performance.
Dim result As Integer = 0
Dim i, ladderVal, LadderCount, size, valCount As Integer
ladderVal = 0
LadderCount = 0
size = A.Length
If size > 0 Then
For i = 1 To size - 1
If LadderCount = 0 Then
LadderCount += 1
ladderVal = A(i)
Else
If A(i) = ladderVal Then
LadderCount += 1
Else
LadderCount -= 1
End If
End If
Next
valCount = 0
For i = 0 To size - 1
If A(i) = ladderVal Then
valCount += 1
End If
Next
If valCount <= size / 2 Then
result = 0
Else
LadderCount = 0
For i = 0 To size - 1
If A(i) = ladderVal Then
valCount -= 1
LadderCount += 1
End If
If LadderCount > (LadderCount + 1) / 2 And (valCount > (size - (i + 1)) / 2) Then
result += 1
End If
Next
End If
End If
Return result
See the correctness and performance of the code
Below solution resolves in complexity O(N).
public int solution(int A[]){
int dominatorValue=-1;
if(A != null && A.length>0){
Hashtable<Integer, Integer> count=new Hashtable<>();
dominatorValue=A[0];
int big=0;
for (int i = 0; i < A.length; i++) {
int value=0;
try{
value=count.get(A[i]);
value++;
}catch(Exception e){
}
count.put(A[i], value);
if(value>big){
big=value;
dominatorValue=A[i];
}
}
}
return dominatorValue;
}
100% in PHP https://codility.com/demo/results/trainingVRQGQ9-NJP/
function solution($A){
if (empty($A)) return -1;
$copy = array_count_values($A); // 3 => 7, value => number of repetition
$max_repetition = max($copy); // at least 1 because the array is not empty
$dominator = array_search($max_repetition, $copy);
if ($max_repetition > count($A) / 2) return array_search($dominator, $A); else return -1;
}
i test my code its work fine in arrays lengths between 2 to 9
public static int sol (int []a)
{
int count = 0 ;
int candidateIndex = -1;
for (int i = 0; i <a.length ; i++)
{
int nextIndex = 0;
int nextOfNextIndex = 0;
if(i<a.length-2)
{
nextIndex = i+1;
nextOfNextIndex = i+2;
}
if(count==0)
{
candidateIndex = i;
}
if(a[candidateIndex]== a[nextIndex])
{
count++;
}
if (a[candidateIndex]==a[nextOfNextIndex])
{
count++;
}
}
count -- ;
return count>a.length/2?candidateIndex:-1;
}
Adding a Java 100/100 O(N) time with O(1) space:
// you can also use imports, for example:
import java.util.Stack;
// you can write to stdout for debugging purposes, e.g.
// System.out.println("this is a debug message");
class Solution {
public int solution(int[] A) {
// write your code in Java SE 8
int count = 0;
Stack<Integer> integerStack = new Stack<Integer>();
for (int i = 0; i < A.length; i++) {
if (integerStack.isEmpty()) {
integerStack.push(A[i]);
} else if (integerStack.size() > 0) {
if (integerStack.peek() == A[i])
integerStack.push(A[i]);
else
integerStack.pop();
}
}
if (!integerStack.isEmpty()) {
for (int i = 0; i < integerStack.size(); i++) {
for (int j = 0; j < A.length; j++) {
if (integerStack.get(i) == A[j])
count++;
if (count > A.length / 2)
return j;
}
count = 0;
}
}
return -1;
}
}
Here is test result from codility.
I think this question has already been resolved somewhere. The "official" solution should be :
public int dominator(int[] A) {
int N = A.length;
for(int i = 0; i< N/2+1; i++)
{
int count=1;
for(int j = i+1; j < N; j++)
{
if (A[i]==A[j]) {count++; if (count > (N/2)) return i;}
}
}
return -1;
}
How about sorting the array first? You then compare middle and first and last elements of the sorted array to find the dominant element.
public Integer findDominator(int[] arr) {
int[] arrCopy = arr.clone();
Arrays.sort(arrCopy);
int length = arrCopy.length;
int middleIndx = (length - 1) /2;
int middleIdxRight;
int middleIdxLeft = middleIndx;
if (length % 2 == 0) {
middleIdxRight = middleIndx+1;
} else {
middleIdxRight = middleIndx;
}
if (arrCopy[0] == arrCopy[middleIdxRight]) {
return arrCopy[0];
}
if (arrCopy[middleIdxLeft] == arrCopy[length -1]) {
return arrCopy[middleIdxLeft];
}
return null;
}
C#
int dominant = 0;
int repeat = 0;
int? repeatedNr = null;
int maxLenght = A.Length;
int halfLenght = A.Length / 2;
int[] repeations = new int[A.Length];
for (int i = 0; i < A.Length; i++)
{
repeatedNr = A[i];
for (int j = 0; j < A.Length; j++)
{
if (repeatedNr == A[j])
{
repeations[i]++;
}
}
}
repeatedNr = null;
for (int i = 0; i < repeations.Length; i++)
{
if (repeations[i] > repeat)
{
repeat = repeations[i];
repeatedNr = A[i];
}
}
if (repeat > halfLenght)
dominant = int.Parse(repeatedNr.ToString());
class Program
{
static void Main(string[] args)
{
int []A= new int[] {3,6,2,6};
int[] B = new int[A.Length];
Program obj = new Program();
obj.ABC(A,B);
}
public int ABC(int []A, int []B)
{
int i,j;
int n= A.Length;
for (j=0; j<n ;j++)
{
int count = 1;
for (i = 0; i < n; i++)
{
if ((A[j]== A[i] && i!=j))
{
count++;
}
}
int finalCount = count;
B[j] = finalCount;// to store the no of times a number is repeated
}
// int finalCount = count / 2;
int finalCount1 = B.Max();// see which number occurred max times
if (finalCount1 > (n / 2))
{ Console.WriteLine(finalCount1); Console.ReadLine(); }
else
{ Console.WriteLine("no number found"); Console.ReadLine(); }
return -1;
}
}
In Ruby you can do something like
def dominant(a)
hash = {}
0.upto(a.length) do |index|
element = a[index]
hash[element] = (hash[element] ? hash[element] + 1 : 1)
end
res = hash.find{|k,v| v > a.length / 2}.first rescue nil
res ||= -1
return res
end
#Keith Randall solution is not working for {1,1,2,2,3,2,2}
his solution was:
element x;
int count ← 0;
For(i = 0 to n − 1) {
if(count == 0) { x ← A[i]; count++; }
else if (A[i] == x) count++;
else count−−;
}
Check if x is dominant element by scanning array A
I converted it into java as below:
int x = 0;
int count = 0;
for(int i = 0; i < (arr.length - 1); i++) {
if(count == 0) {
x = arr[i];
count++;
}
else if (arr[i] == x)
count++;
else count--;
}
return x;
Out put : 3
Expected: 2
This is my answer in Java: I store a count in seperate array which counts duplicates of each of the entries of the input array and then keeps a pointer to the array position that has the most duplicates. This is the dominator.
private static void dom(int[] a) {
int position = 0;
int max = 0;
int score = 0;
int counter = 0;
int[]result = new int[a.length];
for(int i = 0; i < a.length; i++){
score = 0;
for(int c = 0; c < a.length;c++){
if(a[i] == a[c] && c != i ){
score = score + 1;
result[i] = score;
if(result[i] > position){
position = i;
}
}
}
}
//This is just to facilitate the print function and MAX = the number of times that dominator number was found in the list.
for(int x = 0 ; x < result.length-1; x++){
if(result[x] > max){
max = result[x] + 1;
}
}
System.out.println(" The following number is the dominator " + a[position] + " it appears a total of " + max);
}