Time Complexity of a multidimentional array (when cutting to quarter each time) - java

we got a matrix size of NxN which is represented by a multidimentional array, the matrix contains integer numbers, we assume that N=2^K.
We can also say that the matrix is ordered by cutting the matrix to 4 quarters (image below), every element in the first quarter is smaller or equal to the element in the second quarter, every element in the second quarter is smaller or equal to the third quarter, and every element in the third quarter is smaller or equal to every element in the forth quarter. (and so on recursivly)
like this:
1 2
3 4
Example of sorted matrix:
We need to write a function that returns true if the num exist in the matrix.
and to make it as most efficient as possible.
I've wrote the following function:
public static boolean isExist(int[][] mat, int num)
{
int start_rows = 0;
int start_columns = 0;
// If more then 4 elements
// Loop log(base 4)n
for (int elements_size = mat.length * mat[0].length, table_size, quarter_size,
quarter1, quarter2, quarter3, quarter4;
(elements_size > 4);
elements_size /= 4)
{
table_size = (int)(Math.sqrt(elements_size));
quarter1 = mat[start_rows+(table_size/2)-1][start_columns+(table_size/2)-1];
quarter2 = mat[start_rows+(table_size/2)-1][start_columns+table_size-1];
quarter3 = mat[start_rows+table_size-1][start_columns+(table_size/2)-1];
quarter4 = mat[start_rows+table_size-1][start_columns+table_size-1];
if (num == quarter1 || num == quarter2 || num == quarter3 || num == quarter4) {
return true;
}
// Decrease elements_size
quarter_size = (int)Math.sqrt(elements_size/4);
if (quarter1 > num) {
// Dont do anything
} else if (quarter2 > num) {
start_columns += quarter_size; // Increase columns
} else if (quarter3 > num) {
start_rows += quarter_size; // Increase rows
} else if (quarter4 > num) {
start_rows += quarter_size; // Increase rows
start_columns += quarter_size; // Increase columns
} else {
return false; // bigger then quarter, fail.
}
}
return (mat[start_rows][start_columns] == num || mat[start_rows+1][start_columns] == num ||
mat[start_rows][start_columns+1] == num || mat[start_rows+1][start_columns+1] == num);
}
Is that the most efficient way to do so?
Also its time complexity is O(logn). (am I correct?)

well, that is a good approach!
if i understood you right, you want to find out if the array includes a specific int-value;
well, i would use the following methode (but you have to match this to a int [][] array):
HashSet<Integer> test= new HashSet<Integer>(Arrays.asList(intArray));
test.contains(intValue)
this approach is pretty fastest because the hashcode-mechanism has the complexity O(1) but i think through the asList()- it leads to arraylist complexity O(n)... not sure about this!!

It can be done in time complexity O(n). I am not sure if the post is still active. But below is my solution to do it in O(n).
public class NumberInMatrix {
public static void main(String args[]){
int matrix[][] = {{-4,-2,5,9},
{2,5,12,13},
{13,20,25,25},
{22,24,49,57},};
System.out.println(isExist(matrix, 1));
}
private static String isExist(int[][] matrix, int numberToBeSearched) {
int rowCounter = 0, colCounter = matrix[0].length - 1;
while(rowCounter < matrix.length && colCounter >= 0){
if(numberToBeSearched == matrix[rowCounter][colCounter]){
return "Number exist";
}else{
if(numberToBeSearched > matrix[rowCounter][colCounter]){
rowCounter++;
}else{
colCounter--;
}
}
}
return "Number does not exist";
}
}

Related

CoinChange Problem with DP in Java using 2D array

I am implementing an algorithm to solve the Coin Change problem, where given an array that indicates types of coins (i.e. int[] coinValues = {1,4,6};) and a value to achieve (i.e. int totalAmount=8;), an array is returned where the value at position 0 indicates the minimum number of coins needed to achieve totalAmount. The rest of the array will keep a track of how many coins are needed to achieve the total sum.
An example input of coins = {1,4,6} and total = 8 should return the array [3,2,0,1]. However, my code is returning [1,2,0,1].
Another example would be coins = {2,4,8,16,34,40,64} and total = 50 should return the array [2, 0, 0, 0, 1, 1, 0, 0]. My code is not returning that result.
The algorithm is implemented with 2 methods: CoinChange and CoinCount. CoinChange creates the coin matrix and CoinCount keeps track of the coins required to achieve the total sum.
package P5;
import java.util.Arrays;
public class CoinChange7 {
public static int[] CoinChange(int[] v, int sum) {
int[][] aux = new int[v.length + 1][sum + 1];
// Initialising first column with 0
for(int i = 1; i <= v.length; i++) {
aux[i][0] = 0;
}
// Implementing the recursive solution
for(int i = 1; i <= v.length-1; i++) {
for(int j = 1; j <= sum; j++) {
if(i == 1) {
if(v[1] > j) {
aux[i][0]=999999999; //instead of Integer.MAX_VALUE
} else {
aux[i][j]=1 + aux[1][j-v[1]];
}
} else {
if(v[i] > j) { //choose best option ,discard this coin or use it.
aux[i][j] = aux[i - 1][j];
} else
aux[i][j] = Math.min(aux[i-1][j],1 + aux[i][j-v[i]]);
}
}
}
int []z=CoinCount(sum,aux,v);
return z; // Return solution to the initial problem
}
public static int[] CoinCount(int A, int[][] aux, int[] d){
int coin = d.length-1;
int limit=A;
int [] typo=new int[d.length+1]; //We create solution array, that will count no of coins
for (int k=0;k<typo.length;k++) {
typo[k]=0;
} while (coin>0 || limit>0){
if(limit-d[coin]>=0 && coin-1>=0){
if(1+aux[coin][limit-d[coin]]<aux[coin-1][limit]){
typo[coin+1]=typo[coin+1]+1;
limit=limit-d[coin];
} else {
coin=coin-1;
}
} else if(limit-d[coin]>=0) {
typo[coin+1]=typo[coin+1]+1;
limit=limit-d[coin];
} else if(coin-1>=0) {
coin=coin-1;
}
}
typo[0]= aux[d.length-1][A];
return typo; //return the final array with solutions of each coin
}
public static void main(String[] args) {
int[] coins = {1,4,6};
int sum = 8;
int[] x=CoinChange(coins,sum);
System.out.println("At least " + Arrays.toString(x) +" from set "+ Arrays.toString(coins)
+ " coins are required to make a value of " + sum);
}
}
Clarification
I don't know if you still need the answer to this question but I will try to answer it anyway.
First, there are a few things I would like to clarify. The coin change problem does not have a unique solution. If you want both the minimum of coins used to make the change and frequencies of coins usage, I think that depends on the approach used to solve the program and the arrangement of the coins.
For example: Take the coins to be [4,6,8] and amount = 12. You'll quickly see that the minimum coins required to make this change is 2. Going by your choice of output, the following are all correct: [2,0,2,0] and [2,1,0,1].
By the way, the Coin change problem can be solved in many ways. A simple recursive DP approach in Java is here. It only returns the min coins needed to make the change at O(nlog(n)) time and O(n) space.
Another approach is by using a 2D DP matrix (same with the approach you tried using) at both O(n^2) time and space. Explanation on how to use this approach is here. Please be careful with the explanation because it is not generally correct. I noticed it's almost the same as the one you used.
Your solution
I will mention a few things about your solution that may have affected the result.
The number of rows of the DP matrix is v.length not v.length + 1.
Based on your solution, this should not affect the result because I noticed you don't seem comfortable with zero indexes.
I think it is not necessary to initialize the first column of the DB matrix since the data type you used is int, which is 0 by default. Again, this does not affect the answer, though.
The way you filled row 1 (supposed to be the first row, but you ignored row 0) is not good and may affect the result of some solutions.
The only mistake I see there is that there is no uniform value to specify amounts (i.e. j) that cannot be solved using the single coin (i.e. v[0]). Negative numbers could have been better because any positive integer is a potential valid solution for the cell. You could use -1 (if you're going by the Leetcode instruction). This way, you'll easily know cells that contain invalid values while filling the rest of the matrix.
The way you compute aux[i][j] is wrong because you are using the wrong coins. you are using v[i] instead of v[i-1] since you aux.length is one bigger than the v.length.
I did not look at the countCoint method. It looks complex for a seemingly simple problem. Please see my solution.
My Solution
public int[] change(int[] coins, int amount){
int[][] DP = new int[coins.length][amount+1];
//fill the first column with 0
//int array contains 0 by default, so this part is not necessary
/*
for (int i = 0; i < coins.length; i++) {
DP[i][0] =0;
}
*/
//fill the first row.
//At 0th row, we are trying to find the min number of ways to change j amount using only
//one coin i.e. coins[0] (that is the meaning of DP[0][j];
for (int j = 1; j <= amount; j++) {
if(coins[0] > j || j % coins[0] != 0){
DP[0][j] = -1;
}else{
DP[0][j] = j /coins[0];
}
}
//iterate the rest of the unfilled DP
for (int i = 1; i < coins.length; i++) {
for (int j = 1; j < amount+1; j++) {
if(coins[i] > j){
DP[i][j] = DP[i-1][j];
}else {
int prev = DP[i-1][j];
int cur = 1+DP[i][j-coins[i]];
if(cur == 0){
DP[i][j] = DP[i-1][j];
} else if(prev == -1) {
DP[i][j] = 1 + DP[i][j - coins[i]];
}else{
DP[i][j] = Math.min(DP[i-1][j],1+DP[i][j-coins[i]]);
}
}
}
}
return countCoin(coins,amount,DP);
}
public int[] countCoin(int[] coins, int amount, int[][] DP){
int[] result = new int[coins.length+1];//The 1 added is to hold result.
int i = coins.length -1;
int j = amount;
//while the rest will contain counter for coins used.
result[0] = DP[i][j];
if(result[0] ==0 || result[0] ==-1)return result;
while (j > 0 ){
if(i-1 >= 0 && DP[i][j] == DP[i-1][j]){
i = i-1;
}else{
j = j - coins[i];
result[i+1] += 1;
}
}
return result;
}

What is wrong with my method to see if a value is in a 2D array in O(n) time?

I'm trying to write a method that takes a 2D array(arranged so that the elements in every row are in increasing order from left to right, and the elements in every column are in increasing order from top to bottom) and an int, and sees if the int is in the 2D array. I wanted to use nested loops, but that would make it go in O(N^2) time. I'm therefore trying to make conditionals that make it so it tests if the int is smaller than the first in one of the sub arrays and bigger than the last, and if so, goes onto the next subarray. Here's what I have:
static boolean has(int number, int[][] a) {
int q = 0;
boolean c = false;
for (int i = 0; i < a[q].length-1; i++){
if ((number < a[i][q]) || (number > a[a[j].length-1][i])){
q++;
}
else if (number == a[i][q]){
c = true;
break;
}
else c = false;
}
return c;
}
could use some help. This method compiles but gives me outOfBounds Thanks!
This solution runs in O(n+m):
static boolean has(int number, int[][] a) {
int row = 0;
int col = a[0].length - 1;
while (row < a.length && col >= 0) {
int n = a[row][col];
if (n < number) {
row++;
} else if (n > number) {
col--;
} else {
return true;
}
}
return false;
}
You can solve this in O(log(n) + log(m)) first find the row that contain the integer you're looking for using binary search (since columns are sorted), then find the exact position of the integer in that row, by performing another binary search (since rows are sorted).

Implementing Euclid's Algorithm in Java

I've been trying to implement Euclid's algorithm in Java for 2 numbers or more.The problem with my code is that
a) It works fine for 2 numbers,but returns the correct value multiple times when more than 2 numbers are entered.My guess is that this is probably because of the return statements in my code.
b) I don't quite understand how it works.Though I coded it myself,I don't quite understand how the return statements are working.
import java.util.*;
public class GCDCalc {
static int big, small, remainder, gcd;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
// Remove duplicates from the arraylist containing the user input.
ArrayList<Integer> listofnum = new ArrayList();
System.out.println("GCD Calculator");
System.out.println("Enter the number of values you want to calculate the GCD of: ");
int counter = sc.nextInt();
for (int i = 0; i < counter; i++) {
System.out.println("Enter #" + (i + 1) + ": ");
int val = sc.nextInt();
listofnum.add(val);
}
// Sorting algorithm.
// This removed the need of conditional statements(we don't have to
// check if the 1st number is greater than the 2nd element
// before applying Euclid's algorithm.
// The outer loop ensures that the maximum number of swaps are occurred.
// It ensures the implementation of the swapping process as many times
// as there are numbers in the array.
for (int i = 0; i < listofnum.size(); i++) {
// The inner loop performs the swapping.
for (int j = 1; j < listofnum.size(); j++) {
if (listofnum.get(j - 1) > listofnum.get(j)) {
int dummyvar = listofnum.get(j);
int dummyvar2 = listofnum.get(j - 1);
listofnum.set(j - 1, dummyvar);
listofnum.set(j, dummyvar2);
}
}
}
// nodup contains the array containing the userinput,without any
// duplicates.
ArrayList<Integer> nodup = new ArrayList();
// Remove duplicates.
for (int i = 0; i < listofnum.size(); i++) {
if (!nodup.contains(listofnum.get(i))) {
nodup.add(listofnum.get(i));
}
}
// Since the array is sorted in ascending order,we can easily determine
// which of the indexes has the bigger and smaller values.
small = nodup.get(0);
big = nodup.get(1);
remainder = big % small;
if (nodup.size() == 2) {
recursion(big, small, remainder);
} else if (nodup.size() > 2) {
largerlist(nodup, big, small, 2);
} else // In the case,the array only consists of one value.
{
System.out.println("GCD: " + nodup.get(0));
}
}
// recursive method.
public static int recursion(int big, int small, int remainder) {
remainder = big % small;
if (remainder == 0) {
System.out.println(small);
} else {
int dummyvar = remainder;
big = small;
small = dummyvar;
recursion(big, small, remainder);
}
return small;
}
// Method to deal with more than 2 numbers.
public static void largerlist(ArrayList<Integer> list, int big, int small, int counter) {
remainder = big % small;
gcd = recursion(big, small, remainder);
if (counter == list.size()) {
} else if (counter != list.size()) {
big = gcd;
small = list.get(counter);
counter++;
largerlist(list, gcd, small, counter);
}
}
}
I apologize in advance for any formatting errors etc.
Any suggestions would be appreciated.Thanks!
I think these two assignments are the wrong way around
big = gcd;
small = list.get(counter);
and then big not used
largerlist(list, gcd, small, counter);
Also you've used static variables, which is usually a problem.
I suggest removing static/global variables and generally don't reuse variables.
Edit: Oh yes, return. You've ignored the return value of the recursion method when called from the recursion method. That shouldn't matter as you are printing out instead of returning the value, but such solutions break when, say, you want to use the function more than once.

What should be the optimal way of solving Recurrence relation for really Huge number greater than Integer maximum value

I want to find the Nth number of the Recurrence Equation
T(n)=T(n-1)+3T(n-2)+3T(n-3)+(n-4),T(1)=T(4)=1,T(2)=T(3)=3
so if suppose you entered 2,5,9 as input, output should be T(2)=3,T(5)=20,T(9)=695
what I did is create an array of size equal to maximum of all input value and storing solution of T(i) at index i.Then look up into the array for specific index. eg array[3] for T(3),array[5] for T(5),etc
The code worked fine till maximum number is not greater than maximum integer value system can hold i.e
Integer.MAXValue.
Because the index of array can only be integer then
if number is n=1855656959555656 what should be the best way to find the solution of
T(1855656959555656)?
as clearly I cant create an array of size=1855656959555656..
I have even tried BigInteger from java.Math but with no success.
I have to find some other approach.please suggest some ideas..
Thanks
you do not need to store every T(i), you only need to store 3 values T(i-1), T(i-2), T(i-3). While looping over i, check if the current i should be part of your output, if so put it out immediately or save it to an "output"-array.
edit: this part is quite inefficient. You check in every iteation EVERY needed output.
for (int k = 0; k < arr.length; ++k) {
if (count == arr[k])
T[k] = temp[i];
else if (arr[k] == 1)
T[k] = 1;
else if (arr[k] == 2)
T[k] = 3;
else if (arr[k] == 3)
T[k] = 3;
else if (arr[k] == 4)
T[k] = 1;
}
so your code runs in time (max*arr.length) you can reduce it to only (max). Use a HashMap with key=neededPosition (=count) value=position in arr
Init the map like this:
Map<Long, Integer> map = new HashMap<Long, Integer>();
for (int i = 0; i < arr.length; i++) {
map.put(arr[i], i);
}
if (map.containsKey(count)) {
T[map.get(count)] = temp[i]
}
check the values 1-4 just once after the whole thing!
Not possible. The array size can be a maximum of Integer.MAX_VALUE (minus something usually 5 or 8, depending on the JVM capabilities). Why?. The index for an Array should be an integer thats a limitation.
It can't be done. So you need to solve the problem by introducing a sharding mechanism. The simplest way would be to just have arrays of arrays with a fixed length.
Edit: You really do not need this much storage for your problem at hand (as pointed out in another answer; this code fragment avoids arrays altogether to avoid bounds checks / indirection):
public void t(long n) {
if (n < 5) {
return (n == 2 || n == 3) ? 3 : 1;
}
long i = 5; // Initialize variables for n == 5;
long tn_1 = 1; // T(n-1) = T(4) = 1;
long tn_2 = 3; // T(n-2) = T(3) = 3;
long tn_3 = 1; // T(n-3) = T(2) = 1;
long tn_4 = 3; // T(n-4) = T(1) = 3;
while (true) {
long tn = tn_1 + 3*tn_2 + 3*tn_3 + tn_4;
if (i++ == n) {
return tn;
}
tn_4 = tn_3;
tn_3 = tn_2;
tn_2 = tn_1;
tn_1 = tn;
}
}
To answer the question in the title anyway:
If your array is sparse, use a map (TreeMap or HashMap) of Long or BigInteger:
Map<Long,Long> t = new TreeMap<Long,Long>()
The memory consumption of sparse arrays depends on the number of elements actually stored, so you may want to delete values from the map that are no longer needed.
If your array is not sparse, use a 2-level array (memory consumption will depend on the pre-allocated size only):
public class LongArray {
static final long BLOCK_SIZE = 0x40000000;
long[][] storage;
public LongArray(long size) {
long blockCount = (size + BLOCK_SIZE - 1) / BLOCK_SIZE;
storage = new long[][(int) blockCount];
for (long i = 0; i < blockCount; i++) {
if (i == blockCount - 1) {
storage[i] = new long[(int) size - BLOCK_SIZE * (blockCount - 1)];
} else {
storage[i] = new long[(int) BLOCK_SIZE];
}
}
}
public long get(long index) {
return storage[(int) (index / BLOCK_SIZE)][(int) (index % BLOCK_SIZE)];
}
public void put(long index, long value) {
storage[(int) (index / BLOCK_SIZE)][(int) (index % BLOCK_SIZE)] = value;
}
}
In both cases, use t.get(index) and t.put(index, value) instead of t[index] to access your array (if t is the name of the array).
You can do one thing. Check if the value of n is equal to 1855656959555656 in the beginning or if its multiple. Suppose, the value of n is twice of 1855656959555656. Then you can create two arrays and link them together virtually. This should solve your problem but it will involve a lot of overhead.
Use recursive call:
int T(int n){
if (n==1 || n==4){
return 1;
} else if (n==2 || n==3){
return 3;
} else {
return T(n-1)+3*T(n-2)+3T*(n-3)+T(n-4);
}
}
Edit: Time consumming. Won't work with large numbers

Efficient method to find the second largest even int in an array

The assignment is to create a method that finds the second largest even int in an array of ints. I am restricted from using any methods from any libraries.
Here is my code that works for all cases:
public static int getSecondLargestEven(int[] ary) {
int i;
aryLength = ary.length;
int largestEven = -1;
int secondLargestEven = -1;
for (i = 0; i < aryLength; i++) {
if (ary[i] % 2 == 0) {
if (ary[i] > largestEven) {
if (largestEven != -1)
secondLargestEven = largestEven;
largestEven = ary[i];
} else {
if (ary[i] != largestEven) {
if (secondLargestEven == -1 || ary[i] >= secondLargestEven) {
secondLargestEven = ary[i];
}
}
}
}
}
Prior to calling the methodI require the array to have more than one even else no method call.
So, when secondLargestEven == -1, I know there is a duplicate.
Is there a more efficient (less use of operators, less loops used, less memory allocation) way to accomplish the objective? How can I improve the logic of my code? How can I improve my code overall?
I don't like that I have to assign the magic number -1 to secondLargestEven and largestEven because they are technically named to hold EVENS. Would it be efficient to use a loop to assign a valid even integer in the array to both secondLargestEven and largestEven and THEN proceed to search? Thanks in advance.
You can make the code cleaner by not explicitly checking for the case when the largest and second variables are equal to -1.
Just set these variables to Integer.MIN_VALUE before the loop - this is the same as assuming that there were two additional values in your array that come before all the others, and they both have the value Integer.MIN_VALUE.
public static int secondLargestEven(int[] x) {
int largest = Integer.MIN_VALUE;
int second = Integer.MIN_VALUE;
for (int i = 0; i < x.length; i++) {
if (x[i] % 2 == 0) {
if (x[i] > largest) {
second = largest;
largest = x[i];
} else if (x[i] > second) {
second = x[i];
}
}
}
return second;
}
Edit -- I thought I'd throw in that you can remove one level of nesting by using a continue statement inside the loop to skip the cases where you have an odd integer, although some people would consider this more difficult to understand than the code above.
It's a tradeoff - you use explicit control flow inside the loop (bad) but you remove a nesting level (good).
public static int secondLargestEven(int[] x) {
int largest = Integer.MIN_VALUE;
int second = Integer.MIN_VALUE;
for (int i = 0; i < x.length; i++) {
if (x[i] % 2 != 0)
continue;
if (x[i] > largest) {
second = largest;
largest = x[i];
} else if (x[i] > second)
second = x[i];
}
}
return second;
}
Just a fun thought... in Haskell, this function can be written in one line
import Data.List (sort)
secondLargestEven = (!! 1) . reverse . sort . filter even
or, if you want to be more efficient
import Data.List (sortBy)
import Data.Ord (comparing)
secondLargestEven = (!! 1) . sortBy (comparing negate) . filter even
This is just-for-fun implementation:
public static int secondLargestEven(int[] array) {
Set<Integer> evenSet = new TreeSet<>(Collections.reverseOrder());
for (int n : array) if (n % 2 == 0) evenSet.add(n);
return new ArrayList<>(evenSet).get(1);
}
This method is extremely inefficient (I cant look at it) but returns second largest even number :)
Method works only if array has second largest even number.

Categories