Minimizing time complexity when looping over two arrays - c

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;
}

Related

Speed efficiency in rebuilding an array

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.

How to know if an array is "almost" sorted?

I have to decide, given an array of numbers, if either heap sort or merge sort will be faster at sorting it, without actually running them. In order to do that I am trying to find good indicators that might harm performance in both cases such as the length of the array, for example.
I have found that merge sort is exceptionally good at sorting almost sorted arrays. In that sense, I am trying to find a good way to estimate how "almost" sorted an array is but I am not sure how to do that.
I have thought about using the means of the result of subtracting each consecutive element in the array but I am not sure if that is the best approach to this problem. For example:
public class AlmostSortedCalculator {
private static final int[] UNSORTED_ARRAY = {7, 1, 3, 9, 4, 8, 5};
private static final int[] SORTED_ARRAY = {1, 3, 4, 5, 7, 8, 9};
private static final int[] UNSORTED_ARRAY_ = {200, 20, 634, 9957, 1, 890, 555};
private static final int[] SORTED_ARRAY_ = {1, 20, 200, 555, 634, 890, 9957};
public static void main(String[] args) {
new AlmostSortedCalculator();
}
public AlmostSortedCalculator() {
calculate(SORTED_ARRAY);
calculate(UNSORTED_ARRAY);
calculate(SORTED_ARRAY_);
calculate(UNSORTED_ARRAY_);
}
private void calculate(int[] array) {
int result = 0;
for (int i = array.length - 1; i != 0; i--) {
if (i != 0) {
result += array[i] - array[i - 1];
}
}
System.out.println("The result is: " + result / array.length);
}
}
The result is: 1
The result is: 0
The result is: 1422
The result is: 50
The result of the means seems to be higher when the array is sorted but I am not sure how reliable that indicator is. I am sure there is a better approach for this, but I cannot think of any. Any suggestions?
First of all, I'd only look at the sign of the subtraction results:
/* returns the sign of the expression a - b */
int sign_of_subtraction_result(int a, int b) {
if ( a < b ) return -1;
if ( a > b ) return +1;
return 0;
}
You may also call this function compare().
Note that usual library sorting functions only use this information and require such compare()-fuctions.

Finding the number of Polysyllables in java

Say I have a String array, I already counted the number of syllables in the array. How would I go about finding the number of Polysyllables in the array? I know I would have to count the number of words with syllables > 1, but I don't know how to go about doing that.
You need to keep track of the number of syllables in another data structure. You could use a simple int[] to do this, and it could be returned by the function that counts syllables, that you have already created.
String[] myStrings = {"One", "Syllable", "Dog", "Laptop"};
int[] mySyllables = countSyllables(myStrings);
//In the above case, mySyllables = {1, 3, 1, 2};
So once you have counted the number of syllables, and saved the values, you can iterate your mySyllables array, and whenever you encounter a value greater than 1, you know how many polysyllables you have.
int numPoly = 0;
for(int i=0;i<mySyllables.length;i++) {
if(mySyllables[i] > 1) numPoly++;
}
In the given sample case, the end result is numPoly == 2, being "Syllables" and "Laptop"

How do I use 2-D arrays to determine whether or not something is a Magic Square? (requires much help, please)

Before I ask my question, I want to make myself clear that I am not expecting someone to do my lab for me. I am seeking genuine help to understand my lab, I am using StackOverflow because it is consistent and helpful. YES I have searched for answers to my question elsewhere. I am trying my best to format a detailed "good" question.
Okay this is a MagicSquare prgogram. Unlike others I have viewed online, the program we are writing is to determine whether or not a two-dimensional array is a Magic Square. After it determines whether or not it is, it will print the result. I am struggling in my class when it comes to writing a program. So if you could please help me out, I would appreciate it. (More specifics are commented within my code)
public class MagicSquare {
public static void main(String [] args){
int [] [] square3 = {{ 1, 6, 4}, {8, 2, 9} {5, 7, 3}}; // this is for the 3x3 matrix
MagicSquare case1 = new MagicSquare( square3 );
String table = case1.toString();
System.out.println(table);
// Do I stop here for the first array?
int [] [] square4 = {{16, 3, 2, 13}, {5, 10, 11, 8}, {9, 6, 7, 12}, {4, 15, 14, 1}}
//do something here for the rest of the second 2d array
The above is pre-written code, I understand that it is setting up what will be printed. Is the case1 necessary for doing this or could you use a loop instead?
if(case1.isAmagicSq( ))
System.out.println("...is a magic square..." );
else
System.out.println("...is not a magic square... " );
//repeat for the 4x4 square
}
This simply states whether or not it is a magic square.
}/* write the constructor nd two instance methods here */
//1. Write a constructor to create a deep copy of the 2-D array
//formal parameter. There should be a private instance field for
//holding the deep copy of the input array
private int arrayCopy(int [] [] square3, square4){
int [] = new int[square3.length];
for(int i = 0; i < square3.length; i++)
result[i] = square3[i];
return result;
int [] = new int[square4.length];
for( int i = 0; i < square4.length; i++)
result[i] = square4[i];
return result;
}
Am I on the right track for writing a deep copy of the array? Would I use the variables above?
//2. Write the toString method to return a String with a table
//containing the magic square
//3. Determine if the 2d array is or is not a magic square
//by using an instance method
public static int count Elements( int [][] array){
int result;
for(int i = 0; i < array.length; i++) result+=array[i].length;
return result;
}
public static int[] rowI(int data[][], int i){
if(i<data.length)
return data[i];
else
return null;
}
For the last one I have started to write something that (should) count across each row to see if they add up to what a MagicSquare is supposed to be. Obviously I'm not finished, but I didn't want to continue if I'm completely incorrect...
You do not need a deep copy of any sort to validate a magic square. You should just pass the square to some method, and that will add up the numbers for each row and column. Passing the object is done by reference, and since you are not modifying it, you shouldn't have to worry about any copy function. This is the most critical part of the exercise, I would work on that first.
Everything you need to do should be in that method you defined:
public boolean isAmagicSq(){
// do your checks here
}

Creating an average array

part of an assignment that I'm working on is having me pass an array through a method that calculates the averages of the elements in the last array 5 numbers at a time.
For example, say Array1 consists of {1, 2, 3, 4, 5, 6}
The method would calculate the average of {1, 2, 3, 4, 5} and then {2, 3, 4, 5, 6}
The method would then take those averages and put them into a new array and pass that array back into the main.
I'm just not sure where to start. The most I can think of logically is that I'm going to need to use nested loops.
And yes, this is my first year in programming.
Welcome to Stack Overflow, Tony! Here at Stack Overflow, we really encourage users to provide some proof of effort or research, keep this in mind in future posts :)Let's think about this problem logically. We want to start by getting the average of the array from array[0] to array[n-2] (You use n-2, because index n-1 is actually holding the value '6').
For the second part. start at array[1] and go to array[n-1] Once we know this, we can take the average and return it.There is no need for nested loops here, remember this concept while programming and many tears will be saved: Keep it simple
Here is a similar question that was posted: How to minpulate arrays and find the average
Here is a solution that I came up with. When you are in the design stage of your program, you want to think about how you can make your code reusable. There may be a time when you'll have a complex program and many parts will need to perform the same operation with different data. This is known as code re-usability and mastering it will make your life easier.
public static void main(String[] args) {
int [] arr = new int [] {1, 2, 3, 4, 5, 6}; //Stores the numbers we need to average
//We get the Lower-Average by starting at index 0, going to index n-2
System.out.println ("Lower-Average: " + average(0, arr.length - 2, arr));
//We get the Upper-Average by starting at index 1, going to index n-1
System.out.println ("Upper-Average: " + average(1, arr.length - 1, arr));
}
/*
* This method accepts a start index, end index, and an array to operate on
* The average is calculated iteratively and returned based on number of elements provided
*/
public static double average (int startIndex, int endIndex, int [] array) {
double avg = 0; //Stores the average
int counter; //Used to hold number of elements iterated through
for (counter = startIndex; counter <= endIndex; counter++) {
avg += array[counter]; //Summation for the average
}
return avg = avg / counter; //Calculate the average and return it to caller
}
Output:
Lower-Average: 3.0
Upper-Average: 3.3333333333333335

Resources