I am trying to find the largest differences between indexes of two equal elements, in an zero-index array of integers.
My for loop currently looks like this, with a "nested for loops" structure
which means its time complexity is O(N^2).
Is it possible of reducing its time complexity to O(N * log(N)) or lower?
public static Integer solution(Integer[] arr) {
Integer l = arr.length;
int result = 0;
for (int i = 0; i < l; i++) {
for (int j = 0; j < l; j++) {
if (arr[i] == arr[j]) {
result = Math.max(result, Math.abs(i - j));
}
}
}
return result;
}
I assume you are trying to find the highest difference of two indexes of equal numbers in an array. You don't need to run through the entire array 2 times. The inner loop can simply end at i which will greatly reduce complexity.
public static int solution(int[] arr) {
int l = arr.length;
int result = 0;
for (int i = 0; i < l; i++) {
for (int j = 0; j < i; j++) {
if (arr[i] == arr[j]) {
result = Math.max(result, Math.abs(i - j));
}
}
}
return result;
}
The complexity should just about be O(N * log(N)).
Related
I need to print all prime numbers from 1 to 1,000,000 and print all even numbers from 4 to 10,000 and two prime numbers that sum to it.
I have a sieve method that changes all non-prime numbers in an array to a 0 (the problem specifically asks for this to be done), and I need to use a goldbach method that passes this array and displays all even numbers from 4 to 10,000 and two primes that sum up to that number.
The point of the goldbach portion of the problem is to print the numbers efficiently, and I am pretty sure my solution uses a polynomial time search when the correct solution is to be done with a linear time search. Any clue on how I might optimize this?
import java.lang.Math;
public class sieveAndGoldbach {
public static void sieve(int[] a) {
int n = a.length;
a[0] = 0;
for (int i = 1; i <= Math.sqrt(n); i++) {
if (a[i] != 0) {
for (int j = a[i]*a[i]; j <= n; j+=a[i]) {
a[j-1] = 0;
}
}
}
}
public static void goldbach(int[] a) {
int max = 10000;
for (int i = 4; i <= max; i += 2) {
int count = 0;
for (int j = 0; j < i/2; j++) {
if (a[j] != 0) {
int difference = i-a[j];
for (int k = 0; k < max; k++) {
if (a[k] == difference && count == 0) {
System.out.println(i + " = " + a[j] + " + " + (difference));
count++;
}
}
}
}
}
}
public static void main(String[] args) {
//initialize and fill array from 1 to n
int n = 1000000; //initially one million GOLDBACH METHOD WILL NOT WORK FOR n < 10,000
int[] a = new int[n];
for (int i = 0; i < n; i++) {
a[i] = i + 1;
}
//Call sieve method on array a, then print all primes, not the zeros
sieve(a);
for (int i = 0; i < n; i++) {
if (a[i] != 0) {
System.out.print(a[i]);
System.out.print(" ");
}
}
System.out.print("\n");
//Call goldbach method on array a
goldbach(a);
}
}
You currently seem to be iterating through the array of primes for each prime looking for one that sums to your target. That's not necessary; you just need to check whether the difference is a prime:
int[] primes;
int target;
for (int i = 2; i < target / 2; i++) {
if (primes[i] != 0 && primes[target - i] != 0)
...
}
Beyond that I can't see a lot of obvious optimisation but there may well be some numerical analysis that allows you to target likely primes first.
I am attempting to write a recursive method that COUNTS the number of combinations of k size in an integer array.
I can easily do this for a known value k (e.g. 3) as so:
int[] arr = {1,2,3,4};
int count = 0;
for(int i = 0; i < arr.length; i++) {
for(int j = i+1; j < arr.length; j++) {
for(int k = j+1; k < arr.length; k++) {
count++;
}
}
}
However, I would like to be able to do this without a known k. I have found methods online that print the combinations using recursion, such as this one:
https://www.techiedelight.com/find-distinct-combinations-of-given-length/, but none that count them.
Simple case of modifying the method linked.
public static int recur(int[] A, int i, int k)
{
int count = 0;
if (k == 0) {
count++;
}
for (int j = i; j < A.length; j++) {
count = count + recur(A, j + 1, k - 1);
}
return count;
}
The problem is to count how many times my bubble sort algorithm switches the places of numbers. I tried to use a variable which increments by one each time, but I think there may be an error with scopes or something similar. Instead of returning a number such as 6 (which means numbers were swapped 6 times), it returns 0, which is what I initialized my variable as. How would I get my program to work?
public static int sort(int arr[]) {
int length = arr.length;
int temp;
int count = 0;
for (int i = 0; i < (length); i++) {
for (int j = 1; j < (length); j++) {
if (arr[j - 1] > arr[j]) {
temp = arr[j-1];
arr[j-1] = arr[j];
arr[j] = temp;
count++;
}
}
}
return count;
}
Looks like your algorithm is not optimized because of your for loop condition and initialization. As a result you are comparing an element with itself which is redundant.
Proper approach should be like below:
int yourCounter = 0;
for (int i = 0; i < length; i++)
for (int j = 1; j < length-i; j++)
if (arr[j - 1] > arr[j]) {
//swap code
//yourCounter++;
}
your counter should give you proper result then.
I was reading up on sorting algorithms, I finished selection and bubble sort and thought I should try to implement what I understood.It took me while to understand what I wrote intending to be selection sort(code snippet-1) wasn't implementing key features of selection sort at all(which is finding min of unsorted array and building sorted array one element at a time). So I wrote one more for selection sort(code snippet-3). But now, I'm curious about Snippet-1. Can someone tell me if it is bubble sort or not?
Code Snippet-1
public void sort(int[] arr) {
// code snippet-1
int n = arr.length;
for (int i = 0; i < n; i++) {
for(int j = i + 1; j < n; j++) {
if(arr[i] > arr[j]){
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
}
Code Snippet-2
public void sort(int[] arr) {
// code snippet-2
int n = arr.length;
for (int i = 0; i < n-1; i++) {
for (int j = 0; j < n-1; j++) {
if(arr[j] > arr[j+1]){
int temp=arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
}
Code Snippet-3
public void sort(int[] arr) {
// Code snippet-3
int n = arr.length;
for (int i = 0; i < n; i++) {
int min = i;
for(int j = i + 1; j < n; j++){
if(arr[j] < arr[min]) {
min = j;
}
}
int temp = arr[i];
arr[i] = arr[min];
arr[min] = temp;
}
}
Also, on a not so related account, can someone explain how the outer for loop condition (i.e i<n and i<n-1) doesn't affect the result in these cases? I only changed snippet-2's condition to j<n-1 as it gave me Arrayoutofbound error because of arr[j+1] term. Yes, I saw the entire thing in debug mode and animations too but still not completely clear how to choose a condition. I know I'm missing something here.
You have different approaches to bubble sort and the Arrayoutofbound exception is because of the comparison of n+1 element which is not there in the array.
In code snippet 2, you could also avoid one more loop by doing:
for (int i = 0; i <= n-2; i++)
public static void complexityexample(int n) {
int count = 0;
int k = 1;
for (int i = 0; i < n; i++) {
for (int j = 0; j < k; j++) {
count++;
}
k *= 2;
for (int t = 0; t < n; t++) {
count++;
}
System.out.println(count);
}
}
Can anyone write me the answer?
for example , I know that nuber of operations in the for loop is 2N+2,
and number of operations in count++; is N
but what for the other parts.
Time complexity is O(2n). The bottle neck is :
for(int j = 0; j < k; j++){
count++;
}
Since k increases exponentially every iteration of i.
In the i'th iteration, k = 2i-1. This means iterating all values from j to k is O(k) = O(2i).
Now, sum it all up for all iterations:
20 + 21 + 22 + ... + 2n-1 = 2n - 1
Where last equality comes from sum of geometric series
Note that the next inner loop:
for (int t = 0; t < n; t++) {
is not influencing the time complexity (in terms of asymptotic notation), since it adds O(n) time for each iteration of i, and this gets quickly suppressed by the exponential behavior of the first inner loop.
If you want to count the value of count at the end, it is the summation of the first inner loop, which as said is (2n)-1, and the second inner loop, which is sum{n | for each i} = n2.
(2^n)+(n*n)
as them main loop is
for (int i = 0; i < n; i++) {
2^n from :
for (int j = 0; j < k; j++) {
count++;
}
and n*n from:
for (int t = 0; t < n; t++) {
count++;
}
1st row ) 1 operation.
2st row ) 2 operations.
3rd row ) 1+n+1+n = 2N+2.
4 ) 2N+2
5)N
7) N
9)2N+2
10)N
13)1
Is this right.
And after all math calculations the final result is : 14N^2 + 22N + 11 - operations.
A precise methodology using Sigma notation would be:
Empirically verified:
When n = 10, number of overall iterations is 1123.
When n = 25, number of overall iterations is 33555056.
When n = 50, it took for ever to execute (I had to change variables type from int to long).
Indeed, this non polynomial algorithm is expensive.