I have an array and my goal is to find out how many are spaced by multiples of 11. The array is NOT sorted.
Such as [27, 16, 52, 84], this would return 2
[1, 55, 66, 33] should return 3.
[99, 8, 52, 32] should return 0
Currently what I have is to basically run through for-each element in the array, check every other element with multiplying by 11. But this leaves me at a O(n²) runtime, anyway I can optimize this?
static int eval(int [] a) {
int i, j, k, counter = 0;
for (i = 0; i < a.length; i++) {
for (j = 0; j < a.length; j++) {
if (i != j) {
for (k = -9; k < 10; k++) {
if (a[i] == a[j] + k*11) {
counter++;
break;
}
}
}
}
}
//if found nothing, will return 0, if found 1 matching,
//it should be 2 numbers that share this 11-difference.
return counter : counter == 0? 0: counter + 1;
}
Thanks!
It's not entirely clear what the output is supposed to be for, say, [11, 22, 34, 45]. I'm interpreting the question as asking for the size of the largest subset of the input where all differences between elements of the subset are multiples of 11, and where size-1 subsets don't count.
All inputs with the same residue mod 11 are spaced by multiples of 11, so we only need to count how many ints in the input have each possible value of i % 11. This takes time linear in the size of the input.
static int eval(int[] a) {
int[] inputsPerResidue = new int[11];
for (int i : a) {
inputsPerResidue[i % 11]++;
}
int maxGroupSize = 0;
for (int groupSize : inputsPerResidue) {
if (groupSize > 1 && groupSize > maxGroupSize) {
maxGroupSize = groupSize;
}
}
return maxGroupSize;
}
You would need 2 loops to accomplish this. Calculate the difference between every element, and if that number is a multiple of 11, increment the counter. Return half the counter, as if you hit a multiple of 11 between two elements, you will end up hitting the same two elements again later in the loop:
static int eval(int [] a) {
int counter = 0;
for (int i = 0; i < a.length; i++) {
for (int j = 0; j < a.length; j++) {
if (i != j && Math.abs(a[i] - a[j]) % 11 == 0) {
counter++;
}
}
}
return counter / 2;
}
Related
I've earlier used nested approach which is giving me TLE.
-we can not use nested approach for this.
- time limit is 1 sec and 5000kb memory. Here is my nested approach
for (int i = 0; i < n; i++) {
if (arr[i] > 0) {
int count = 1;
for (int j = i + 1; j < n; j++)
if (arr[i] == arr[j])
count += 1;
if (count == k)
res = Math.min(res, arr[i]);
}
}
You can try using a dictionary that keeps track of the numbers as keys, and the number of times it appears as the value. This way you will only have to go through the array once.
Then, at the end you check which keys have a value of K, and choose the smallest of those.
Firstly you should get the max element and make count array of length max+1 elements i.e how much time each elements occurring eg:-
arr=[2,5,1,2,3,6,3] and k=2.
Now count each element, n is length of array, c is array counting element
int c[]=new int[max+1];
for(int i=0;i<=max; i++)
{
c[a[i]]+=1;
}
Arrays.sort(a);
//1 2 2 3 3 5 6
for(int i=0;i<n;i++)
{
if(c[a[i]]==k)
{
System.out.print(a[i]);
break;
}
}
This will give you desired output with time complexity O(nLogn)
How about just sorting the array and then walking through it to return the first value that occurs k times?
// return the smallest value that occurs k times, or null if none found
static Integer smallestK(int[] a, int k)
{
Arrays.sort(a);
for(int i=1, j=0; i<=a.length; i++)
{
if(i == a.length || a[i] != a[j])
{
if(i - j == k)
return a[j];
j = i;
}
}
return null;
}
Test:
int[] a = {6, 5, 3, 1, 4, 2, 5, 2, 2};
System.out.println(Arrays.toString(a));
for(int k=1; k<=4; k++)
{
Integer val = smallestK(a.clone(), k);
if(val != null)
System.out.format("k:%d, Result: %d%n", k, val);
else
System.out.format("k:%d, Not Found", k);
}
Output:
[6, 5, 3, 1, 4, 2, 5, 2, 2]
k:1, Result: 1
k:2, Result: 5
k:3, Result: 2
k:4, Not Found
You can try below approach as well. it has O(nlogn) complexity.
int[] arr1 = {10,2,15,20,25,4,25};//array
int k = 2;//minimum occurences
Arrays.sort(arr1);
HashMap<Integer,Integer> value = new HashMap<Integer, Integer>();
for(int i:arr1) {
value.put(i, value.getOrDefault(i, 0)+1);
}
for(int i:arr1) {
if(value.get(i)==k) {
System.out.println(i);
break;
}
}
I am trying to write a function in Java which takes two arrays and sums the index values from Array 1 where values match Array 2, e.g.
Array1 = {15, 6, 99, 12, 35}
Array2 = {1, 12, 7, 99, 35}
Matching "Array1[index]" values = 2 (99), 3 (12), 4 (35)
So, return 9 (2+3+4)
I would propose doing this using the following:
public int sumIndex(int[] array1, int[] array2) {
int total = 0;
for (int i=0; i < array1.length; i++) {
for (int j = 0; j < array2.length; j++) {
if (array1[i] == array2[j]) {
total = total + i;
}
}
}
}
But I also want to return -1 if a non-matching value is in Array2. So in the case above 1 and 7 are not in Array1 so that would reduce the total by -2 (-1 for each missing value).
If I add an 'else' statement
else {
total = total - 1;
}
or 'else if' statement
else if (array1[i] != array2[j]) {
total = total - 1;
}
I get -1 removed from total every time there is a value where array1[index] does not match array2[index] as i and j loop. I am trying to only return -1 for values in array2 which do not match values in array1.
How would I write this so that total-1 is only returned when a value from array2 is not an element of array1?
Thanks
Looking at your example, I assume that the arrays have unique elements. In such a case, you need to do the following things:
Break the inner loop as soon a match is found. This will make your code efficient.
Change the order of loops and repeat the same logic.
On the termination of the inner loop, check if the inner loop was terminated prematurely (because of break). If not, a match was not found and therefore the value of total needs to be decreased by 1.
public class Main {
public static void main(String[] args) {
System.out.println(sumIndex(new int[] { 15, 6, 99, 12, 35 }, new int[] { 1, 12, 7, 99, 35, 100, 1000 }));
}
static int sumIndex(int[] array1, int[] array2) {
int total = 0, i, j;
// Nested loops to calculate sum of indices having equal values
for (i = 0; i < array1.length; i++) {
for (j = 0; j < array2.length; j++) {
if (array1[i] == array2[j]) {
total += i;
break;
}
}
}
// Nested loops to decrease 'total' for the non-matching values of array2
for (j = 0; j < array2.length; j++) {
for (i = 0; i < array1.length; i++) {
if (array1[i] == array2[j]) {
break;
}
}
// If a match is not found, 'i' will reach a value equal to array1.length
if (i == array1.length) {
total--;
}
}
return total;
}
}
Output:
5
Just create a flag found, reset it every loop, and set it to true if array1[i] value is found in array2[j], and if it's false reduce total by 1.
public int sumIndex(int[] array1, int[] array2) {
total = 0;
for (int i=0; i < array1.length; i++) {
bool found = false;
for (int j = 0; j < array2.length; j++) {
if (array1[i] == array2[j]) {
total = total + i;
found = true;
}
}
if(!found)
total--;
}
}
You should use lists instead of arrays. If you use lists you can use:
List<Integer> arrayList1 = Arrays.asList(15, 6, 99, 12, 35);
List<Integer> arrayList2 = Arrays.asList(1, 12, 7, 99, 35);
int indexSum = 0;
for(Integer integer : arrayList2){
indexSum = indexSum + arrayList1.indexOf(integer);
}
The indexOf method returns -1 when the element integer of arrayList2 is not present in ArrayList1. If it is present that method will return the index. So if its not present -1 is added to indexSum. If it is present the index is added.
I can't solve the problem , where I need output from array A like {1,2,3,4,-1,-2,-3,-4}
from random numbers in array, then write it to another array B. So far my experimental code doesn't work as I'd
public static void main(String[] args) {
int a[] = {5,4,3,2,1,-3,-2,-30};
int length = a.length - 1;
for (int i = 0 ; i < length ; i++) {
for (int j = 0 ; j < length-i ; j++) {
if (a[j] < a[j+1]) {
int swap = a[j];
a[j] = a[j+1];
a[j+1] = swap;
}
}
}
for (int x : a) {
System.out.print(x+" ");
}
}
Output is 5 4 3 2 1 -2 -3 -30 , but I need 1,2,3,4,5,-2,-3,-30
Update:
public static void main(String[] args) {
int a[] = {5,4,3,2,1,-3,-2,-30,-1,-15,8};
int length = a.length - 1;
for (int i = 0 ; i < length ; i++) {
for (int j = 0 ; j < length-i ; j++) {
if (a[j] < a[j+1]) {
int swap = a[j];
a[j] = a[j+1];
a[j+1] = swap;
} else {
if (a[j] > a[j+1] && a[j+1] > 0) {
int swap = a[j];
a[j] = a[j+1];
a[j+1] = swap;
}
}
}
}
for (int x : a) {
System.out.print(x+" ");
}
}
I got closer to my target but 8 1 2 3 4 5 -1 -2 -3 -15 -30 , that number 8 ruins it all
Add an if-else to differentiate the positive and negative case.
if (a[j] < 0) {
if (a[j] < a[j+1]) {
int swap = a[j];
a[j] = a[j+1];
a[j+1] = swap;
}
} else {
if (a[j] > a[j+1] && a[j+1] > 0) {
int swap = a[j];
a[j] = a[j+1];
a[j+1] = swap;
}
}
If I understand you correctly you want to sort after two things. Positive numbers from low to high and negative numbers from high to low.
You could first sort from high to low and in a second run over the array skip all positives and then sort from high to low.
Does this help?
I could write some code, but I believe that's something you want to learn right now :)
Algo:
Traverse the Array and Store positives in one and Negatives in another. O(i)
Sort the positives array in ascending order. O(mLog(m))
Sort the negatives indescending order. O(nLog(n))
Create a final array of the size of the input.
Add all the positive array sorted values. Then add the negative array sorted values. O(i)
Total : O(i) + O(mLog(m)) + O(nLog(n)) + O(i) = O(mLog(m)) if m > n
I have used library functions here. But if you want you can the write the functions using the same idea.
public class PostivieAsendingNegativeDesending implements Comparator<Integer> {
public static void main(String args[]) {
int fullList[] = {5, 4, 3, 2, 1, -3, -2, -30};
ArrayList<Integer> subList = new ArrayList<>();
ArrayList<Integer> subList2 = new ArrayList<>();
for (int i = 0; i < fullList.length; i++) {
if (fullList[i] < 0) {
subList2.add((fullList[i]));
} else {
subList.add(fullList[i]);
}
}
Collections.sort(subList);
Collections.sort(subList2, new PostivieAsendingNegativeDesending());
subList.addAll(subList2);
for (int i = 0; i < subList.size(); i++) {
System.out.print(subList.get(i) + " ");
}
System.out.println("");
}
#Override
public int compare(Integer n1, Integer n2) {
return n2 - n1;
}
}
This will do the trick which uses only basic loops
public static void main(String[] args) {
int a[] = { 5, 4, 3, 2, 1, -3, -2, -30 };
int length = a.length - 1;
int pos = 0, neg = 0;
// find total count of positive and negative numbers
for (int i = 0; i <= length; i++) {
if (a[i] < 0)
neg++;
else
pos++;
}
// initialize the arrays based on 'pos' and 'neg'
int posArr[] = new int[pos];
int negArr[] = new int[neg];
// store pos and neg values in the arrays
int countPos = 0, countNeg = 0;
for (int i = 0; i <= length; i++) {
if (a[i] < 0) {
negArr[countNeg] = a[i];
countNeg++;
} else {
posArr[countPos] = a[i];
countPos++;
}
}
// sort positive numbers
for (int i = 0; i < posArr.length - 1; i++) {
for (int j = 0; j < posArr.length - 1 - i; j++) {
if (posArr[j] > posArr[j + 1]) {
int swap = posArr[j];
posArr[j] = posArr[j + 1];
posArr[j + 1] = swap;
}
}
}
// sort negative numbers
for (int i = 0; i < negArr.length - 1; i++) {
for (int j = 0; j < negArr.length - 1 - i; j++) {
if (negArr[j] < negArr[j + 1]) {
int swap = negArr[j];
negArr[j] = negArr[j + 1];
negArr[j + 1] = swap;
}
}
}
// 1. print out posArr[] and then negArr[]
// or
// 2. merge them into another array and print
}
Logic is explained below :
Find total count of positive and negative numbers.
Create and store the positive and negative values in the respective arrays.
Sort positive array in ascending order.
Sort negative array in descending order.
Print out positive array followed by the negative array OR merge them into another and print.
I suggest another approach. You should try to formulate the rules to which the exact comparison must adhere.
Your requirement seem to have the following rules:
Positive numbers always come before negative numbers.
Positive numbers are ordered in ascending order.
Negative numbers are ordered in descending order. Yes, I said descending. Since higher numbers come before lower numbers, i.e. −2 is greater than −7.
Warning: you are using a nested for loop, which means that the process time will grow exponentially if the array becomes larger. The good news is: you don't need to nest a for loop into another for loop. I suggest writing a Comparator instead:
// The contract of Comparator's only method 'compare(i, j)' is that you
// return a negative value if i < j, a positive (nonzero) value if i > j and
// 0 if they are equal.
final Comparator<Integer> c = (i, j) -> { // I'm using a lambda expression,
// see footnote
// If i is positive and j is negative, then i must come first
if (i >= 0 && j < 0) {
return -1;
}
// If i is negative and j is positive, then j must come first
else if (i < 0 && j >= 0) {
return 1;
}
// Else, we can just subtract i from j or j from i, depending of whether
// i is negative or positive
else {
return (i < 0 ? j - i : i - j);
}
}
Your code could look like this:
int[] a = { 5, 4, 3, 2, 1, -3, -2, -30 };
int[] yourSortedIntArray = Arrays.stream(a)
.boxed()
.sorted(c) // Your Comparator, could also added inline, like
// .sorted((i, j) -> { ... })
.mapToInt(i -> i)
.toArray();
Lambda expressions are a new concept from Java 8. The Java Tutorials provide some valuable information.
I made this method that compares the numbers of two arrays and then returns how many numbers are equal to each other, but no matter how many numbers are equal, the method returns the value 1 every time.
(both arrays are the same length).
public static void main(String[] args) {
int a [] = {1, 4, 6, 7, 8, 10, 13};
int b [] = {1, 2, 3, 4, 5, 6, 7};
equal(a,b);
}
public static int equal(int[] a, int[] b){
int j = 0;
for(int i = 0; i< a.length-1;i++){
if(a[i] == b[i]){
j++;
}
}
System.out.println(j);
return j;
}
Your code is finding the number that are equal at the same index.
There are several ways you can find the size of the intersection.
A simple but O(m*n) implementation would be to iterate over all elements of b for each element of a.
If the arrays are sorted, you could use separate indexes for the two arrays, advancing each when it can no longer match. This would be O(m+n). (If they're not sorted, you could sort them first, for a cost of O(m log m + n log n ).
If each array has no duplicate members, another way is to compute the size of the intersection is from the size of the set difference. An example of this is at http://ideone.com/6vLAfn. The key part is to convert each array to a set, and determine how many members are in common by removing one set from another.
int aSizeBefore = setA.size();
setA.removeAll( setB );
int aSizeAfter = setA.size();
return aSizeBefore - aSizeAfter;
You should use a nested for loop if you want to check if any single number in array a is also in array b.
e.g.
int numMatches = 0;
for (int i = 0; i < a.length; ++i)
{
for (int j = 0; j < b.length; ++j)
{
if (a[i] == b[j])
++numMatches; //Naive, as obviously if the same number appears twice in a it'll get counted twice each time it appears in b.
}
}
The current code just checks the elements at the same index match i.e
1 == 1 // Yes, increment j
4 == 2 // Nope
6 == 3 // Nope
7 == 4 // Nope
8 == 5 // Nope
10 == 6 // Nope
13 == 7 // Nope
Elements with same values might be in different indexes. You can write as following, assuming the arrays are sorted:
public static int equal(int[] a, int[] b) {
int count = 0;
for(int i = 0; i < a.length - 1; i++) {
for(int j = 0; i < b.length - 1; j++) {
if (a[j] < b[j]) {
// we came to the part where all elements in b are bigger
// than our selected element in a
break;
}
else if (a[j] == b[j]) {
count++;
}
}
}
System.out.println(count);
return count;
}
If you can't guarantee that the arrays are sorted, you can remove the if-block and remove the else-if's else from the loop.
If you want to know how many numbers are present in both arrays and there is a guarantee that they are ordered, you should try the following:
public static int equal(int[] a, int[] b) {
int j, result = 0;
int lastFound = 0;
for (int i = 0; i < a.length - 1; i++) {
for (j = lastFound; j < b.length; j++) {
if (a[i] == b[j]) {
result++;
lastFound = j;
break;
} else {
if (a[i] < b[j]) break;
}
}
}
return result;
}
Using the variable lastFound will speed your loops, but it is only helpful if the arrays are ordered, as your example indicates.
I have an exercise in which I have to sort an array in the following way:
the numbers that divide 4 with no remainder will be the first in the array (e.g 4,8,12,16).
the numbers that divide 4 with remainder of 1 will be the second in the array (1,5,9).
the numbers that divide 4 with remainder of 2 will be the third in the array (2,6,10).
the numbers that divide 4 with remainder of 3 will be last in the array.
For example, the following array:
int []a={1,7,3,2,4,1,8,14}
will be:
4 8 1 1 2 14 3 7
the order within the groups does not matter.
I have found a solution which works on O(n) time complexity and O(1) space complexity.
However, it is ugly and moves on the array 3 times. I would want a more elegant solution.
This is my code:
int ptr=a.length-1; int temp=0, i=0;
while (i<ptr){
//move 3 remained to the end
if (a[i] % 4==3){
temp=a[ptr];
a[ptr]=a[i];
a[i]=temp;
ptr--;
}
else
i++;
}
i=0;
while (i<ptr){
if (a[i]%4==2)
{
temp=a[ptr];
a[ptr]=a[i];
a[i]=temp;
ptr--;
}
else
i++;
}
i=0;
while (i<ptr){
if (a[i]%4==1)
{
temp=a[ptr];
a[ptr]=a[i];
a[i]=temp;
ptr--;
}
else
i++;
}
Important to know:
I don't want time complexity worse than O(n), and space complexity worse than O(1).
Since O(3 * N) is O(N), you only need to loop through the array three times:
Move the elements e % 4 == 0 to the front, swapping elements along the way;
Move the elements e % 4 == 1 to the front, swapping elements along the way;
Move the elements e % 4 == 2 to the front, swapping elements along the way;
The elements that e % 4 == 3 will be at the end after this.
Example:
public static void main(String args[]) {
int[] a = { 1, 7, 3, 2, 4, 1, 8, 14 , 9};
int current = 0;
for (int i = 0; i < 3; i++) {
for (int j = current; j < a.length; j++) {
if (a[j] % 4 == i) {
int b = a[j];
a[j] = a[current];
a[current] = b;
current++;
}
}
}
System.out.println(Arrays.toString(a));
}
Just use a comparator and make use for the very efficient internal sort algorithm.
Arrays.sort(a, new Comparator() {
public int compare(int a, int b) {
if(a%4 == b%4) {
if(a < b) return -1;
if(a > b) return 1;
return 0;
} else {
if(a%4 < b%4) return -1;
if(a%4 > b%4) return 1;
return 0;
}
}
});
You can use up more memory. This is not correct, but I will still put it.
int modulusLength = 4;
List<Integer> array[] = new List<Integer>[modulusLength];
for(int i = 0; i < modulusLength; i++)
array[i] = new ArrayList<Integer>;
for(int i = 0 ; i < a.length; i++)
array[a[i]%modulusLength].put(a[i]);
int counter = 0;
for(int i = 0 ; i < array.length; i++)
for(int j = 0; j < array[i].size; j++)
{
a[counter] = array[i].get(j);
counter++;
}
Horrible and scary, but was fun to write. And it works :)