A non-empty array A consisting of N integers is given. The array contains an odd number of elements, and each element of the array can be paired with another element that has the same value, except for one element that is left unpaired.
For example, in array A such that:
A[0] = 9 A[1] = 3 A[2] = 9
A[3] = 3 A[4] = 9 A[5] = 7
A[6] = 9
the elements at indexes 0 and 2 have value 9,
the elements at indexes 1 and 3 have value 3,
the elements at indexes 4 and 6 have value 9,
the element at index 5 has value 7 and is unpaired.
Write a function:
class Solution { public int solution(int[] A); }
that, given an array A consisting of N integers fulfilling the above conditions, returns the value of the unpaired element.
For example, given array A such that:
A[0] = 9 A[1] = 3 A[2] = 9
A[3] = 3 A[4] = 9 A[5] = 7
A[6] = 9
the function should return 7, as explained in the example above.
Write an efficient algorithm for the following assumptions:
N is an odd integer within the range [1..1,000,000];
each element of array A is an integer within the range [1..1,000,000,000];
all but one of the values in A occur an even number of times.
MY SOLUTION
My solution fails at these scenarios, I am willing from SO community to please guide me how to think this problem so that i can overcome these failures
class Solution {
public int solution(int[] A) {
int[] result = new int[(int) Math.ceil((double)A.length/2)];
for(int x = 0 ; x < result.length ; x++ ){
result[x] = -1;
}
for(int x = 0 ; x < A.length ; x++ ){
for(int y = 0 ; y < result.length ; y++){
if(result[y] > -1 && result[y]== A[x])
{
result[y] = -2;
break;
}
if(result[y] == -1 )
{
result[y] = A[x];
break;
}
}
}
for(int x = 0 ; x < result.length ; x++ ){
if(result[x] > -1){
return result[x];
}
}
return -1;
}
}
FAILURES
medium random test n=100,003
Killed. Hard limit reached: 7.000 sec.
big random test n=999,999, multiple repetitions
Killed. Hard limit reached: 14.000 sec.
big random test n=999,999
Killed. Hard limit reached: 19.000 sec.
If it is guaranteed that the input has only one unpaired element, it is very simple to identify it by doing an XOR of all elements.
int x = A[0];
for ( int i = 1; i < A.length; i++ )
x = x ^ A[i];
The resulting value is the one which is not paired.
Example:
public static void main (String[] args) throws java.lang.Exception
{
int[] A = {9, 3, 9, 2, 4, 2, 4, 7, 3};
int x = A[0];
for ( int i = 1; i < A.length; i++ )
x = x ^ A[i];
System.out.println(x);
}
Output is 7.
Time complexity is O(n)
This works because the XOR of a number with itself is zero.
The most effective solution exploits interesting property of bitwise XOR operation:
a xor a = 0
for any value of a, so xor'ing all array items just gives unpaired value
public int solution(int[] A) {
int result = 0;
for(int x = 0 ; x < A.length ; x++ )
result ^= A[x];
return result;
}
Related
I am trying to make a program where I can input the size of a 2D array, the highest number in a 2D array, and the most amount of a certain number in the 2D array, and then fill it with random numbers in between 1 and the highest number. In my code, I specify that the max amount of times a number should repeat is 4, yet my output doesn't match that. Any suggestions?
This is my code:
class Main {
public static void main(String[] args) {
System.out.println(fill(6, 9, 4));
}
public static String fill(int size, int max, int most) {
int[][] list = new int[size][size];
int count = 0;
for (int i = 0; i < list.length; i++) {
for (int j = 0; j < list[i].length; j++) {
int x = (int)((Math.random()* max) + 1);
int y = 0;
count = 0;
for (int k = 0; k < list.length; k++) {
for (int l = 0; l < list[k].length; l++) {
if(list[k][l] == x) count++;
}
}
if(count < most) {
list[i][j] = x;
} else {
while(true) {
y = (int)((Math.random()* max) + 1);
if(y != x) break;
}
list[i][j] = y;
}
System.out.print(list[i][j] + " ");
}
System.out.println();
}
return "";
}
}
And this is my output:
9 4 6 1 9 1
7 1 4 4 3 2
6 1 4 2 7 9
5 9 4 7 2 5
3 5 3 5 7 4
3 8 8 6 2 6
Problem: There are 6 "4"s and 2 "8"s
You generate a random number.
You then check if this random number is 'invalid', in the sense that it's been used too many times.
Then, you generate a new random number, check that this isn't the same as your previous number, and then just roll with that. You are failing to check if this number, too, is 'overloaded'. So, what could have happened here is that your algorithm picked '9', counts 9s, finds 4 of them, rolls up a new random number, 9 again, so it rolls yet another number, 4, and just puts 4 in, without checking again.
Rejigger your while loops.
Or, better yet, make a utility class to offload the job of generating a random number, but not a number that's already been returned N times, to a separate class, so that you can untangle this messy code.
Your method
while(true) {
y = (int)((Math.random()* max) + 1);
if(y != x) break;
}
does not check that count of y did not already reached most
Your Issue is here:
while(true) {
y = (int)((Math.random()* max) + 1);
if(y != x) break;
}
list[i][j] = y;
This basically just rules out that x will be repeated more than most, but not y.
On a side note, I recommend using hash maps to keep track of the occurrences instead of iterating over the whole array over and over.
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
How do I get the kth combination inNCR. without iterating through all possible outcomes. e.g. say I have 3C2 for 3 positions and 2identical-items. I am aware it's [011],[101] and [110]. how do I get e.g. the 2nd term(k=1) which is [101] using a method?
constraints(R < N k >= 0 and k < P where P = NCR).
NB:[101] is the 2nd term(in ascending/lexicographical order) because 011 = 3,101 = 5 ,110 = 6
in decimal. so basically the goal is to get what number k in NCR is,
because every kth output from NCR can be represented as a number.
Yes, you are correct when you say:
because every kth output from NCR can be represented as a number.
There is a bijection from the set of integers 1 to # of combs/perms to the entire set of combs/perms. Finding the specific index of a particular comb/perm is sometimes referred to as getting the rank. According to the example that you have in your question, these are ordinary permutations. Moreover when you mention ascending order, you are referring to the lexicographical order.
It is a straightforward exercise in counting to obtain the nth ordinary permutation of a given set. We first need to obtain the total number of permutations using the well established formula:
P(n, r) = n! / (n - r)!
This next part is the key observation that allows us to quickly obtain each element of our target permutation.
If we look at all permutations of our set of n choose r, there will be n groups that are only different by a permutation of the n elements.
For example, if we look at the first two group of the permutations of [0 1 2 3] choose 3, we have:
[,0] [,1] [,2]
[0,] 0 1 2
[1,] 0 1 3
[2,] 0 2 1
[3,] 0 2 3
[4,] 0 3 1
[5,] 0 3 2
[6,] 1 0 2
[7,] 1 0 3
[8,] 1 2 0
[9,] 1 2 3
[10,] 1 3 0
[11,] 1 3 2
Note that the last permutations are simply the first 6 permutations of the set [1 0 2 3].. that is, 0 is mapped to 1, 1 is mapped to 0, and the final 2 elements are mapped to themselves.
This pattern continues as we move to the right only instead of n identical groups, we will get n - 1 similar groups for the second column, n -2 for the third, and so on.
So to determine the first element of our permutation, we need to determine the 1st group. We do that by simply dividing the number of permutations by n. For our example above of permutations of 4 choose 3, if we were looking for the 15th permutation, we have the following for the first element:
Possible indices : [0 1 2 3]
P(4, 3) = 24
24 / 4 = 6 (elements per group)
15 / 6 = 2 (integer division) 2 means the 3rd element here (base zero)
Now that we have used the 3rd element, we need to remove it from our array of possible indices. How do we get the next element?
Easy, we get our next subindex by subtracting the product of the group we just found and the elements per group from our original index.
Possible indices : [0 1 3]
Next index is 15 - 6 * 2 = 3
Now, we just repeat this until we have filled all entries:
Possible indices : [0 1 3]
Second element
6 / 3 = 2 (elements per group)
3 / 2 = 1
Next index is 3 - 3 * 1 = 0
Possible indices : [0 3]
Third element
2 / 2 = 1
0 / 1 = 0
So our 15th element is : [2 1 0]
Here is a C++ implementation that should be pretty easy to translate to Java:
double NumPermsNoRep(int n, int k) {
double result = 1;
double i, m = n - k;
for (i = n; i > m; --i)
result *= i;
return result;
}
std::vector<int> nthPermutation(int n, int r, double myIndex) {
int j = 0, n1 = n;
double temp, index1 = myIndex;
std::vector<int> res(r);
temp = NumPermsNoRep(n, r);
std::vector<int> indexVec(n);
std::iota(indexVec.begin(), indexVec.end(), 0);
for (int k = 0; k < r; ++k, --n1) {
temp /= n1;
j = (int) std::trunc(index1 / temp);
res[k] = indexVec[j];
index1 -= (temp * (double) j);
indexVec.erase(indexVec.begin() + j);
}
}
These concepts extends to other types of combinatorial problems, such as finding the nth combination, or permutation with repetition, etc.
The time complexity is O(kn), space is O(n)
public static void main(String[] args) {
//n = 4, r = 2, k = 3
int[] ret1 = getKthPermutation(4, 2, 3);
//ret1 is [1,0,0,1]
//n = 3, r = 2, k = 1
int[] ret2 = getKthPermutation(3, 2, 1);
//ret2 is [1,0,1]
}
static int[] getKthPermutation(int n, int r, int k) {
int[] array = new int[n];
setLastN(array, r, 1);
int lastIndex = n - 1;
for(int count = 0; count < k; count++) {
int indexOfLastOne = findIndexOfLast(array, lastIndex, 1);
int indexOfLastZero = findIndexOfLast(array, indexOfLastOne, 0);
array[indexOfLastOne] = 0;
array[indexOfLastZero] = 1;
//shortcut: swap the part after indexOfLastZero to keep them sorted
int h = indexOfLastZero + 1;
int e = lastIndex;
while(h < e) {
int temp = array[h];
array[h] = array[e];
array[e] = temp;
h++;
e--;
}
}
return array;
}
//starting from `from`, and traveling the array forward, find the first `value` and return its index.
static int findIndexOfLast(int[] array, int from, int value) {
for(int i = from; i > -1; i--)
if(array[i] == value) return i;
return -1;
}
//set the last n elements of an array to `value`
static void setLastN(int[] array, int n, int value){
for(int i = 0, l = array.length - 1; i < n; i++)
array[l - i] = value;
}
This is an adaption of the very typical "find the kth permation" algorithm.
I will try to explain the general idea (yours is a special case as there are only two types of elements: 0 and 1).
Lets say I have [2,1,6,4,7,5]. What is the next smallest permutation that is bigger than the current one? Why do I concern the next smallest permutation bigger than current one? Because if you start with the smallest permutation [1,2,4,5,6,7] and you repeat the action (find the smallest bigger than current) k times, you will find k+1 th smallest permutation.
Now, since the one I am looking for needs to be bigger than current one, I need to increment the current one. To keep the incrementation as small as possible, I am going to try to modify 5 (last one). Now, I cannot just change 5 to a random value, I can only swap it with some digit before it.
If I swap 5 with a bigger number before it, say 7, then I will get [2,1,6,4,5,7], which is smaller than current one. Now obviously I need to swap 5 with some smaller digit before it, but which one? If I swap 5 with 2, I get [5,1,6,4,7,2], this increment is too big. I need to swap 5 with a "lower digit" to keep the increment as small as possible. Thats leads us to find the first(lowest) digit (from right to left) that is smaller than 5. In this case I would need to swap 5 with 4 and get [2,1,6,5,7,4]. This way, I can make the impact of "swap" small. Now the prefix is decided [2,1,6,5. There is no smaller prefix. We need to deal with suffix 7,4]. Clearly, if we sort the suffix and make it 4,7], then we are done.
In our case, there are two differences:
1. we need to swap the last 1, because you cannot make the permutation bigger by swapping the a zero with any digit before it.
2. we can always sort the suffix using a shortcut as shown in the code. I will leave it to you:)
public static String lexicographicPermutation(String str, long n) {
final long[] factorials = { 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800, 39916800, 479001600 };
n--;
char[] arr = str.toCharArray();
for (int i = 0; i < arr.length - 1; i++) {
long fact = factorials[arr.length - i - 2];
long p = i + n / fact;
n %= fact;
for (int j = i + 1; j <= p; j++)
swap(arr, i, j);
}
return new String(arr);
}
private static void swap(char[] arr, int i, int j) {
char tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
You can replace STR with required string. In the given example, 1st permutation is "abcdefghijklm" (this is a string with 13 chars), 13!st permutation is reverse string "mlkjihgfedcba" and 100st permutation is "abcfklgmeihjd".
To realise this soulution just google Factorial number system. This is a key to solve this problem. This is a Project Euler: Problem 24.
Demo:
for(int i = 1; i <= 6; i++)
System.out.println(lexicographicPermutation("110", i));
1 - 110
2 - 101
3 - 110
4 - 101
5 - 011
6 - 011
for(int i = 1; i <= 6; i++)
System.out.println(lexicographicPermutation("abc", i));
1 - abc
2 - acb
3 - bac
4 - bca
5 - cab
6 - cba
I just attempted a stack based problem on HackerRank
https://www.hackerrank.com/challenges/game-of-two-stacks
Alexa has two stacks of non-negative integers, stack A and stack B where index 0 denotes the top of the stack. Alexa challenges Nick to play the following game:
In each move, Nick can remove one integer from the top of either stack A or B stack.
Nick keeps a running sum of the integers he removes from the two stacks.
Nick is disqualified from the game if, at any point, his running sum becomes greater than some integer X given at the beginning of the game.
Nick's final score is the total number of integers he has removed from the two stacks.
find the maximum possible score Nick can achieve (i.e., the maximum number of integers he can remove without being disqualified) during each game and print it on a new line.
For each of the games, print an integer on a new line denoting the maximum possible score Nick can achieve without being disqualified.
Sample Input 0
1 -> Number of games
10 -> sum should not exceed 10
4 2 4 6 1 -> Stack A
2 1 8 5 -> Stack B
Sample Output
4
Below is my code I tried the greedy approach by taking the minimum element from the top of the stack & adding it to the sum. It works fine for some of the test cases but fails for rest like for the below input
1
67
19 9 8 13 1 7 18 0 19 19 10 5 15 19 0 0 16 12 5 10 - Stack A
11 17 1 18 14 12 9 18 14 3 4 13 4 12 6 5 12 16 5 11 16 8 16 3 7 8 3 3 0 1 13 4 10 7 14 - Stack B
My code is giving 5 but the correct solution is 6 the elements popped out in series are 19,9,8,11,17,1
First three elements from stack A & then from Stack B.
**
I don't understand the algorithm It appears like DP to me can anyone
help me with the approach/algorithm?
**
public class Default {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int numOfGames = Integer.parseInt(br.readLine());
for (int i = 0; i < numOfGames; i++) {
String[] tmp = br.readLine().split(" ");
int numOfElementsStackOne = Integer.parseInt(tmp[0]);
int numOfElementsStackTwo = Integer.parseInt(tmp[1]);
int limit = Integer.parseInt(tmp[2]);
int sum = 0;
int popCount = 0;
Stack<Integer> stackOne = new Stack<Integer>();
Stack<Integer> stackTwo = new Stack<Integer>();
String[] stOne = br.readLine().split(" ");
String[] stTwo = br.readLine().split(" ");
for (int k = numOfElementsStackOne - 1; k >= 0; k--) {
stackOne.push(Integer.parseInt(stOne[k]));
}
for (int j = numOfElementsStackTwo - 1; j >= 0; j--) {
stackTwo.push(Integer.parseInt(stTwo[j]));
}
while (sum <= limit) {
int pk1 = 0;
int pk2 = 0;
if (stackOne.isEmpty()) {
sum = sum + stackTwo.pop();
popCount++;
} else if (stackTwo.isEmpty()) {
sum = sum + stackOne.pop();
popCount++;
}
else if (!stackOne.isEmpty() && !stackTwo.isEmpty()) {
pk1 = stackOne.peek();
pk2 = stackTwo.peek();
if (pk1 <= pk2) {
sum = sum + stackOne.pop();
popCount++;
} else {
sum = sum + stackTwo.pop();
popCount++;
}
} else if(stackOne.isEmpty() && stackTwo.isEmpty()){
break;
}
}
int score = (popCount>0)?(popCount-1):0;
System.out.println(score);
}
}
}
Ok I will try to explain an algorithm which basically can solve this issue with O(n), you need to try coding it yourself.
I will explain it on the simple example and you can reflect it
1 -> Number of games
10 -> sum should not exceed 10
4 2 4 6 1 -> Stack A
2 1 8 5 -> Stack B
First you will need to creat 2 arrays, the array will contain the summation of all the number up to its index of the stack, for example for stack A you will have this array
4 6 10 16 17 //index 0 ->4
Same will be done for stack B
2 3 11 16
then for each array start iterating from the end of the array until you reach a number less than or equal to the "sum you should not exceed"
now your current sum is the sum of the point you reached in both arrays, should be 10 +3 = 13 so in order to reach 10 will absolutely need to remove more entries
to remove the additional entries we will be moving the indexes on the array again, to decide which array to move it's index take the entry you are pointing at (10 for array 1 and 3 for array 2) and device it by index+1 (10/3 ~ 3) , (3/2 ~1) then move the index for the highest value and recalculate the sum
Suppose we have:
a = 1 1 1 211 2
b = 1 85
and maxSum = 217
Now, on calculating prefix sums,
a' = 1 2 3 214 216
and b' = 1 86
current sum = 86+216 > 217
so to decide which index to remove, we compare `
216/5~43.2` and `86/2=43`,
so we move pointer in a'. BUT, that doesn't solve it - `
214+86 is still > 217!!`
Had we removed 86, it would've been better! So we should always go ahead by removing the one which has larger difference with previous element!
In case both values are equal its logical to move the index on the value which has larger difference with its previous ( remember we are moving the index in reverse order).
the result will be the sum of the indexes +2.
This solution works great.... i hope it helps ...
import java.util.Scanner;
public class Solution {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int g = sc.nextInt();
for (int tc = 0; tc < g; tc++) {
int n = sc.nextInt();
int m = sc.nextInt();
int x = sc.nextInt();
int[] a = readArray(sc, n);
int[] b = readArray(sc, m);
System.out.println(solve(a, b, x));
}
sc.close();
}
static int[] readArray(Scanner sc, int size) {
int[] result = new int[size];
for (int i = 0; i < result.length; i++) {
result[i] = sc.nextInt();
}
return result;
}
static int solve(int[] a, int[] b, int x) {
int lengthB = 0;
int sum = 0;
while (lengthB < b.length && sum + b[lengthB] <= x) {
sum += b[lengthB];
lengthB++;
}
int maxScore = lengthB;
for (int lengthA = 1; lengthA <= a.length; lengthA++) {
sum += a[lengthA - 1];
while (sum > x && lengthB > 0) {
lengthB--;
sum -= b[lengthB];
}
if (sum > x) {
break;
}
maxScore = Math.max(maxScore, lengthA + lengthB);
}
return maxScore;
}
}
solution in python3
# stack implementation
class Stack:
lis = []
def __init__(self, l):
self.lis = l[::-1]
def push(self, data):
self.lis.append(data)
def peek(self):
return self.lis[-1]
def pop(self):
self.lis.pop()
def is_empty(self):
return len(self.lis) == 0
# number of test cases
tests = int(input())
for i in range(tests):
na, nb, x = map(int, input().split(' '))
a = list(map(int, input().split(' ')))
b = list(map(int, input().split(' ')))
temp = []
stk_a = Stack(a)
stk_b = Stack(b)
score = 0
count = 0
# first taking elements from stack A , till score becomes just less than desired total
for j in range(len(a)):
if score + stk_a.peek() <= x:
score += stk_a.peek()
count += 1
temp.append(stk_a.peek())
# storing the popped elements in temporary stack such that we can again remove them from score
# when we find better element in stack B
stk_a.pop()
# this is maximum number of moves using only stack A
max_now = count
# now iterating through stack B for element lets say k which on adding to total score should be less than desired
# or else we will remove each element of stack A from score till it becomes just less than desired total.
for k in range(len(b)):
score += stk_b.peek()
stk_b.pop()
count += 1
while score > x and count > 0 and len(temp) > 0:
count = count - 1
score = score - temp[-1]
temp.pop()
# if the score after adding element from stack B is greater than max_now then we have new set of moves which will also lead
# to just less than desired so we should pick maximum of both
if score <= x and count > max_now:
max_now = count
print(max_now)
I see that there exist a solution and you marked it as correct, but I have a simple solution
add all elements from stack one that satisfy condition <= x
every element you add push it on stack called elements_from_a
set counter to size of stack
try add elements from stack b if sum > x so remove last element you added you can get it from stack elements_from_a
increment bstack counter with each add , decrements from astack with each remove
compare sum of steps with count and adjust count return count
here is code sample for the solution :
def twoStacks(x, a, b):
sumx = 0
asteps = 0
bsteps = 0
elements = []
maxIndex = 0
while len(a) > 0 and sumx + a[0] <= x :
nextvalue = a.pop(0)
sumx+=nextvalue
asteps+=1
elements.append(nextvalue)
maxIndex = asteps
while len(b) > 0 and len(elements) > 0:
sumx += b.pop(0)
bsteps+=1
while sumx > x and len(elements) > 0 :
lastValue = elements.pop()
asteps-=1
sumx -= lastValue
if sumx <= x and bsteps + asteps > maxIndex :
maxIndex = bsteps + asteps
return maxIndex
I hope this is more simple solution.
void traversal(int &max, int x, std::vector<int> &a, int pos_a,
std::vector<int> &b, int pos_b) {
if (pos_a < a.size() and a[pos_a] <= x) {
max = std::max(pos_a + pos_b + 1, max);
traversal(max, x - a[pos_a], a, pos_a + 1, b, pos_b);
}
if (pos_b < b.size() and b[pos_b] <= x) {
max = std::max(pos_a + pos_b + 1, max);
traversal(max, x - b[pos_b], a, pos_a, b, pos_b + 1);
}
}
int twoStacks(int x, std::vector<int> &a, std::vector<int> &b) {
int max = 0;
traversal(max, x, a, 0, b, 0);
return max;
}
A recursion solution, easy to understand. This solution takes the 2 stacks as a directed graph and traversal it.
The Accepted Answer is Wrong. It fails for the below test case as depicted in the image.
For the test case given, if maximum sum should not exceed 10. Then correct answer is 5. But if we follow the approach by Amer Qarabsa, the answer would be 3. We can follow Geeky coder approach.
Lets say I have a number 1-5, now if I have 2, I want 4 as an output, if I had 3 then have 3 as the output, if I have 1 then 4 as the output. Here is a chart of what I want:
1-10 Chart:
Give 1 return 9
Give 2 return 8
Give 3 return 7
Give 4 return 6
Give 5 return 5
What algorithm do I use for such a thing?
I don't see that you need an algorithm as much. What you have is:
InverseNumber = (myCollection.Length - MySelection);
Thats all you need for even numbers.
With a collection of 1 - 6 for example:
Give 2; 6 - 2 = 4. Also if given 4, 6 - 4 = 2.
You will need a slightly different problem for odds:
1 - 5; with 1 given 1 is at index 0, the opposite is 5, 2 given and the inverse ( 5 - 2) is 3. But if 3 is given, there is no inverse. So you might want to also add a catch for:
if (((myCollection.Length *.5).Round) == mySelection) { //Inverse does not exist!!!}
If you are using just integers, and not arrays of numbers then just replace the myCollection.Length with the upperbound integer.
I think the following code will work for what you need:
int a[] = new a[length_needed];
int counter = length_needed;
for(int c = 0; c < length_needed; c++) {
a[c] = counter;
counter--;
}
int number_inputed;
for(int c = 0; c < length needed; c++) {
if(c == number_inputed) System.out.println(a[c]);
}
Let's say you are giving max number as input. Then you are going to have 0-n numbers. For ex., if 9 is the max number you will have 0-9.
Then you can do something like this:
public static void main(String[] a) {
int max = a[0]; // read values from cmd line args
int forWhichNum = a[1]; //for which number we need its inverse
Sop(max- forWhichNum);
}
Integer value = 2;
Integer maxValue = 6;
Integer reverseCounter = 0;
for (int i = maxValue; i > 0; i--) {
reverseCounter++;
if (i == value) {
return reverseCounter;
}
}
So, I have array like this:
a[1] = 2
a[4] = 3
a[8] = 1
which represent this sequence 1 1 4 4 4 8
And I need to find middle element, or element before (for odd and even);
In this example its 4.
How can I do this quick?
My code is very slow:
static int B(int[] array, int size) {
int c = 0;
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array[i]; j++) {
c++;
if (c == size / 2) {
return i;
}
}
}
}
Traverse original array and add all values
a[1] = 2
a[4] = 3
a[8] = 1
sum = 6
Divide sum by 2 (find mid)
mid = 6/2 = 3
Traverse original array and subtract value from sum
check if ans <= 0
if true print index
else continue to next
For an even less efficient way to do it, run one pass through and keep updating :)
Javascript (since I'm Java challenged):
var a=[]
a[1] = 2
a[4] = 3
a[8] = 1
a[9] = 2
a[10] = 3
a[11] = 1
//1 1 4 4 4 8 9 9 10 10 10 11
function middle (arr){
var stack = [],
total = 0,
tmp,
tmpChange,
middle = 0,
change = 0,
middleElement
for (i in arr){
stack.push([i, arr[i]])
total += arr[i]
tmp = Math.ceil(total/2)
change = tmp - middle
middle = tmp
while (change){
tmpChange = stack[0][1] - change
if (tmpChange >= 0) {
stack[0][1] = tmpChange
change = 0
}
else {
change -= stack[0][1]
stack.splice(0,1)
}
}
middleElement = stack[0][0]
}
return middleElement
}
console.log(middle(a))