Speed efficiency in rebuilding an array - arrays

If I have two arrays of ints e.g. [100, 50, 32, 23] and [40, 30, 32, 125] and a number 50 then the numbers in the first array that is greater than this number should be removed along with its corresponding index pair in the 2nd array.
If i did this manually for every element value and rebuilding the int array each time as I go along over 10,000 elements wouldn't this be incredibly inefficient/slow?
input 50:
new array changes:
[50, 32, 23]
[30, 32, 125]
pseudo code so far:
for each value in array one that is greater than input, remove it and rebuild both arrays, continue
Not sure how I can learn where or what direction I should go in finding a more efficient/faster way of doing this.

Here is an O(n) implementation. It goes through the arrays once to find out how many elements will be retained, creates new arrays too hold the result, then copies the integers that should lower or equal to the limit into the new arrays. I assume the two arrays are held together in an int[][] because that is the most efficient way to pass them around.
public static int[][] removeGreaterThan(int[][] arrays, int limit) {
int retained = 0;
for (int i = 0; i < arrays[0].length; i++) {
if (arrays[0][i] <= limit) retained++;
}
int[][] result = new int[][] {new int[retained], new int[retained]};
int j = 0;
for (int i = 0; i < arrays[0].length; i++) {
if (arrays[0][i] <= limit) {
result[0][j] = arrays[0][i];
result[1][j] = arrays[1][i];
j++;
}
}
return result;
}
Use it like this.
int[][] arrays = new int[][] {{100, 50, 32, 23}, {40, 30, 32, 125}};
int[][] result = removeGreaterThan(arrays, 50);
// you can check to make sure the values are correct
System.out.println(Arrays.asList(result[0]);
System.out.println(Arrays.asList(result[1]);

I would create a SortedMap of your 2 arrays and then extract the pairs with a key smaller than or equal to your input parameter:
Suppose your arrays are like this:
int[] array_1;
int[] array_2;
Convert these arrays into a map:
NavigableMap<Integer, Integer> my_map = new TreeMap();
int index;
for (index = 0; index < array_1.length; index++)
my_map.put(array_1[index], array_2[index]);
Now get all pairs with a key value not greater than the one you specify:
NavigableMap<Integer, Integer> result;
result = my_map.headMap(50, true);
Convert result into new arrays:
array_1 = new int[result.size()];
array_2 = new int[array_1.length];
Iterator<Integer> it = result.keySet().iterator();
index = 0;
Integer key;
while (it.hasNext())
{
key = it.next();
array_1[index] = key;
array_2[index] = result.get(key);
index++;
}
Of course, the final result would be sorted. Not sure if that's a problem.
So, your result would be [23, 32, 50] [125, 32, 30].
Furthermore, it supposes that the keys (the elements in the first array) are unique.

One way to improve on your pseudocode is:
for each iteration
find indexes of first array which are greater than the number.
store indexes in a list.
remove all the elements of the first array using index list. // I can tell you more here but you should give it a try.
remove all the elements of the second array.

Related

How to return an empty array Java

Hi, how are you? =)
I'm new to Java, currently, I'm learning arrays and loops, and I'm really struggling with them at the moment.
Here is my homework:
Write a public method int[] findMinMaxPrices(int[] price).
It takes an array of prices and returns a new array.
Empty, if the array is empty.
Returns only one element, if the maximum and minimum prices in the prices array are the same.
Returns only two elements if the price array contains both the minimum and maximum prices. The minimum price should go first, then the maximum.
Only for loop can be used.
I would use some help here:
How to return an empty array in this case?
I made it many times in draft, unfortunately, it doesn't work here.
How can I use a for loop here?
Can you give me some hints or advice?
Thank you in advance!)
import java.util.Arrays;
public class QuadraticEquationSolver {
public int[] findMinMaxPrices(int[] prices) { // I know it's a mess, but I'm just learning =)
Arrays.sort(prices);
int empty [] = {};
int first [] = Arrays.copyOf(prices, 1);
int a = prices[0];
int b = prices[prices.length-1];
int second [] = new int[] {a,b};
if(prices[0] == prices[prices.length-1]) {
return first;
}
else if(prices[0] < prices[prices.length-1]) {
return second;
}else{
return empty;
//return new int[0]; I tried to use this here, didn't work =(
}
}
public static void main(String[] args) {
QuadraticEquationSolver shop = new QuadraticEquationSolver();
//Should be [50, 1500]
int[] prices = new int[] {100, 1500, 300, 50};
int[] minMax = shop.findMinMaxPrices(prices);
System.out.println(Arrays.toString(minMax));
//findMaxPrices(new int[] {10, 50, 3, 1550}), returns [3, 1550]
//findMaxPrices(new int[] {}), returns []
//findMaxPrices(new int[] {50, 50}), returns [50]
}
}
You return an empty array the same way you create an empty array when you call findMaxPrices(new int[]{}), just use new int[]{}.
For your requirement you don't need to sort the array, because you can store the minimum and maximum value in a local variable and just add minimum before maximum to the array that you return.
One essential thing you are missing is checking for the array length of prices. Using prices.length you get how many values are in the array. Always check the length of an array before you try to access it using an index, otherwise you risk getting an IndexOutOfBounds exception. Using this you can immediately return when prices.length == 0 because then there are no values in the array and you need to return an empty array. If prices.length == 1 we only have one value in the array. This value must be minimum and maximum so we can return an array containing this value. In all other cases we can use a for loop to loop over all elements in the array. If we find a value that is smaller/ greater than the current minimum/ maximum we set that as new maximum. For this to work we need to initialize minimum and maximum to the biggest/ smallest possible value first. Java has the constants Integer.MAX_VALUE and Integer.MIN_VALUE for this kind of thing. Last but not least we need to check if maximum and minimum are the same. In that case we only return one element, otherwise we return both, but minimum before maximum.
public class Application {
public static void main(String[] args) {
System.out.println(Arrays.toString(findMinMaxPrices(new int[]{100, 1500, 300, 50})));
System.out.println(Arrays.toString(findMinMaxPrices(new int[]{})));
System.out.println(Arrays.toString(findMinMaxPrices(new int[]{50, 50})));
}
public static int[] findMinMaxPrices(int[] prices) {
// we can simply check the array length. If it is zero we return an empty array
if(prices.length == 0) return new int[]{};
else if(prices.length == 1) return new int[prices[0]]; // if we only have one element that one element must be the minimum and maximum value
// array length is not zero or one -> we need to find minimum and maximum
int min = Integer.MAX_VALUE; // set to maximal possible int value
int max = Integer.MIN_VALUE; // set to minimal possible int value
for (int i = 0; i < prices.length; i++) {
int currentPrice = prices[i];
if(currentPrice < min) min = currentPrice;
if(currentPrice > max) max = currentPrice;
}
// now we have minimum and a maxium value
// if they are the same only return one value
if(min == max) return new int[]{max};
// otherwise return both, but minumum first
return new int[]{min, max};
}
}
Expected output:
[50, 1500]
[]
[50]

Minimizing time complexity when looping over two arrays

For a intro computer science class we have to write a function that finds the intersection of two arrays, which each unique element only being shown once and without allocating more space than we need.
For example:
array A = {1, 2, 3, 3, 3, 5}
array B = {2, 2, 2, 3, 5, 6}
intersection of A and B = {2, 3, 5}
How can I accomplish this without looping over the both arrays twice? As it stands I have:
//find how large of an array I'll need
for array A
for array A
if A[i] is already somewhere earlier in array A
stop
else
loop through array B
if A[i] is in array B, increment a counter
declare a new array of size counter
//add unique elements to the array
for array A
for array A
if A[i] is already somewhere earlier in array A
stop
else
loop through array B
if A[i] is in array B, add it to the new array
It seems like this would be really inefficient I have two nearly identical nested for loops. If I was using python I could just append unique elements to list, but is there a way I could do something similar in C? I could just declare an array of the maximum size I could need, but I'm trying to minimize the space complexity.
If your are aware of sets you can use that. The time-complexity will be O(n)
You can know more about set and how to implement one in C here.
Then you can do something like this (written in Java):
public int[] intersection(int[] nums1, int[] nums2) {
Set<Integer> set1 = getSet(nums1);
Set<Integer> set2 = getSet(nums2);
Set<Integer> ans = new HashSet<>();
for(Integer i: set1) {
if(set2.contains(i)) {
ans.add(i);
}
}
int[] ret = new int[ans.size()];
int count = 0;
for(Integer i: ans) {
ret[count] = i;
count++;
}
return ret;
}
public Set<Integer> getSet(int[] arr) {
Set<Integer> set = new HashSet<>();
for(int a: arr) { set.add(a); }
return set;
}

Creating a Method to find Max Difference in an Array

I have to create a function that will look at an array of 5 numbers and find the difference between adjacent numbers and from them differences then return the largest difference.
Honestly I'm not sure where to start I know using loops will be my best bet but I'm unsure.
Arrays
int [] numbers = {12, 8, 34, 10, 59};
int [] numbers2 = {-50, 100, 20, -40};
So for the first one the maximum difference would be 49 (10 to 59)
Second one the maximum difference would be 150 (-50 to 100)
Remember it has to be between numbers next to each other.
Thanks in advance!
Well, the question seems trivial, if you know how to loop through an array.
For example (in C#)
int[] numbers = {12,8,34,10,59};
int maxDiff = Int32.MinValue;
for(int i = 0;i<numbers.Length-2;i++)
{
var diff = Math.Abs(numbers[i+1]-numbers[i]);
if( diff> maxDiff)
{
maxDiff = diff;
}
}
Are you missing to tell us something important, like the array size, that is challenging you?

Scala partial sum with current and all past elements in the list

We have a list of integers like: [1,4,5,6,6,7,9].
The idea is to generate a list with the same length and sums up till the current element like: [1,5,10,16,22,29,38].
In the Java world it would look like:
int sum = 0;
int[] table = {1,4,5,6,6,7,9}
int[] res = new int[table.length]
for(int i=0; i<table.length; i++) {
sum += table[i]
res[i] = sum
}
I know there exist more elegant and efficient solutions. My question is how to do something like this in Scala in more fuctional way?
Thx!
You are looking for the scan combinator.
List(1,4,5,6,6,7,9).scanLeft(0)(_ + _)
res1: List[Int] = List(0, 1, 5, 10, 16, 22, 29, 38)
Remove the leading element with tail if you want I am not aware of a version of scan that does not take an initial value. The complexity is O(n) for this guy and you could implement it yourself with folding the list via an accumulator and a list (that contains past accumulators). The latter you take as a result.
#uberwatch's answer is the right one, but for the sake of completeness, here's the more "generic" functional solution using foldLeft:
val xs = Vector(1,4,5,6,6,7,9)
val (sumList, sum) =
xs.foldLeft((Vector.empty[Int], 0)) {
case ((list, total), x) =>
val newTotal = x + total
(list :+ newTotal, newTotal)
}
// sumList: Vector(1, 5, 10, 16, 22, 29, 38)
// sum: Int = 38

Move items to the front of an array

I have items in the centre of an array and I want to move them to the front of this array. For example:
array[8] = {10, 38, 38, 0, 8, 39, 10, 22}
and I have an index array
index[6] = {0, 3, 4, 6, 7, 1}
and I want to move these 6 items to the front of the array
result[8] = {10, 0, 8, 10, 22, 38, 38, 39}
Actually the order doesn't matter, just make sure the item whose index is in the index array should always before the item whose index is not in the index array.
Can anyone give me a fast algorithm? Actually this is one step in an KNN problem, the data array could be very large. The algorithm should run as fast as possible and the extra space needed should be as small as possible. It is better if you can give me CUDA implementation.
Update: Compare to the data array, the size of the index array is very small. In my case, it is only about 200.
Update: Please note that the size of the data array could be very very very large! It goes to 1M, 10M even higher(The data array is loaded to GPU memory which is quite limited). Any algorithm needs a temp array which has the same size with data array is not acceptable.
Sort the index array in increasing order, this step will make sure that we will not make any unnecessary swap.
Starting from 0 to n - 1 (n is the length of array index), swap the ith element in the array with index[i]th element.
Pseudo Code
sort(index);
for(int i = 0; i < index.length; i++){
swap(array, i , index[i]);
}
If you don't want to sort index, we can always find the smallest element in the index array which is not at the beginning of the array. (as the size of index is small)
Use an boolean used to mark which position in the array index is already put at the correct position.
Pseudocode:
bool []used = //
for(int i = 0; i < index.length; i++){
int nxt = -1;
for(int j = 0; j < index.length; j++){
if(!used[j]){
if(nxt == -1 || index[j] < index[nxt]){
nxt = j;
}
}
}
used[nxt] = true;
swap(array, i, nxt);
}
const int ARRAY_SIZE = sizeof(array) / sizeof(array[0]);
const int INDEX_SIZE = sizeof(index) / sizeof(index[0]);
bool used[ARRAY_SIZE] = {};
for (int i = 0; i < INDEX_SIZE; ++i)
{
int id = index[i];
result[i] = array[id];
used[id] = 1;
}
for (int i = 0, id = INDEX_SIZE; i < ARRAY_SIZE; ++i)
{
if (!used[i])
{
result[id] = array[i];
++id;
}
}
Approach 1
You can modify insertion sort to solve your problem which will eventually give you O(n^2) time complexity.
But if you want to keep run time in order of N then you can use following approach.
Approach 2
Here we can use index array as auxiliary space as follows :
step 1
store all actual values instead of indexes in index table(array) and replace the value array with negative/non accepting value.
Value Array
[ -1, -1, 38, -1, -1, 39, -1, -1 ]
Index Array
[ 10, 0, 8, 10, 22, 38 ]
complexity in this operation is O(n)
step 2
shift all the remaining at last which will take O(n) time complexity.
Value Array ###
[ -1, -1, -1, -1, -1, -1, 38, 39 ]
Index Array
[ 10, 0, 8, 10, 22, 38 ]
step 3
not put the element from index array to value array.
Value Array
[ 10, 0, 8, 10, 22, 38, 38, 39 ]
Index Array
[ 10, 0, 8, 10, 22, 38 ]
time complexity for this operation is O(n)
Total run time complexity for this approach : O(n)
Improvement
Here in this approach you are not able to preserve your index array. While you can preserve it using O(index array size) space complexity OR with the condition that value array does not contain any non negative values then while keeping -1/non accepting value in it you can use storing index with -ve and in third step you can recover your index array as it is.

Resources