Find smallest possible array for given condition - java

I have an array say int[] x = {1,0,0,2,0,2}. Sum of pow(2,x[i]) of each element is 13.
I want to find Smallest Possible Array which fulfills same condition (sum of square of each element should be 13).
Please help me out.

public void solution() {
double equation = 0;
int[] a = new int[] { 2, 1, 0, 5, 2, 3 };
try {
for (int i = 0; i < a.length; i++) {
equation = equation + Math.pow(2, a[i]);
}
System.out.println(equation);
int equation1 = (int) equation;
int binaryArray[] = new int[30];
int i = 0;
while (equation1 > 0) {
binaryArray[i++] = equation1 % 2;
equation1 = equation1 / 2;
}
int sum = 0;
List<Integer> list = new ArrayList<Integer>();
do {
for (int j = i - 1; j >= 0; j--) {
if (binaryArray[j] == 0) {
i--;
continue;
}
sum = sum + (binaryArray[j] * (int) Math.pow(2, i));
i--;
list.add(i);
}
} while (i > 0);
// shortest list
System.out.println(list);
// length of shortest list
System.out.println(list.size());
} finally {
}
}

Related

Trying to wrap my head around 3 nested if statments

Say I have an array of 5 strings and that related to that array is 3 arrays of integers all of the same size. e.g.`
String a[] = new String[5]
int x[] = new int[5]
int y[] = new int[5]
int z[] = new int[5]
so that a[0],x[0],y[0],z[0] are all related to the same thing.
I want to find out which index(es) in x[] hold the highest number. If more than one those has the same highest number then which of those has the highest number in y[] and if there is more than one with the same highest number which one would have the highest in z[](Its safe to assume that none would have the same max value in z[]
I've tried to explain as best I can..
This is the best if got it only checks the first 2 conditions
for(int i=0;i<a.length;i++)
{
if(x[i]>=maximum){
if(x[i]==maximum)
{
if(y[i]>=maximum)
{
maximum=x[i];
winner=a[i];
maximum=y[i];
}
}
else
{
maximum=x[i];
winner=teams[i];
maximum=y[i];
}
}
So this is my new code
static int compareValues(){
for (int i=0; i<a.length; i++){
int max =0;
int diff = x[i] - x[max];
if (diff == 0){
diff = y[i] - y[max];
}
if (diff == 0){
diff = z[i] - z[max];
}
if (diff > 0){
max = i
}
}
return max;
}
If the String[n] is related to the int[n]s for each n then really you should compose them properly, make them Comparable and sort them.
class Thing implements Comparable<Thing> {
final String a;
final int x;
final int y;
final int z;
public Thing(String a, int x, int y, int z) {
this.a = a;
this.x = x;
this.y = y;
this.z = z;
}
#Override
public int compareTo(Thing o) {
int diff = o.x - x;
if (diff == 0) {
diff = o.y - y;
}
if (diff == 0) {
diff = o.z - z;
}
return diff;
}
#Override
public String toString() {
return "{" + a + "," + x + "," + y + "," + z + "}";
}
}
public static int max(Thing[] things) {
// NB - This should really call compareTo.
int max = 0;
for (int i = 1; i < things.length; i++) {
int diff = things[i].x - things[max].x;
if (diff == 0) {
diff = things[i].y - things[max].y;
}
if (diff == 0) {
diff = things[i].z - things[max].z;
}
if (diff > 0) {
// Higher
max = i;
}
}
return max;
}
public void test() {
Thing[] things = new Thing[6];
things[0] = new Thing("Hello", 1, 2, 3);
things[1] = new Thing("There", 1, 2, 4);
things[2] = new Thing("Everyone", 0, 2, 3);
things[3] = new Thing("How", 9, 0, 3);
things[4] = new Thing("Are", 8, 9, 3);
things[5] = new Thing("You", 7, 2, 3);
System.out.println("Before: " + Arrays.toString(things));
System.out.println("Max: " + things[max(things)]);
Arrays.sort(things);
System.out.println("Sorted: " + Arrays.toString(things));
}
This solution might be easier to understand:
static String compareValues() {
// find the maximum in x
int xMax = Integer.MIN_VALUE;
for (int i = 0; i < 5; i++) {
if (x[i] > xMax) {
xMax = x[i];
}
}
// find the maximum in y, but limited to the positions where x is maximal according to the calculation above
int yMax = Integer.MIN_VALUE;
for (int i = 0; i < 5; i++) {
if (x[i] == xMax && y[i] > yMax) {
yMax = y[i];
}
}
// find the maximum in z, but limited to the positions where y is maximal according to the calculation above
int zMax = Integer.MIN_VALUE;
int iMax = 0;
for (int i = 0; i < 5; i++) {
if (y[i] == yMax && z[i] > zMax) {
zMax = z[i];
iMax = i; // record the maximum position
}
}
return a[iMax];
}
I did not test the code, but I think that it should work.

Adding binary numbers in Java

I have a function which takes two binary numbers as an array of integers, adds the numbers, then returns the sum as a new array of integers.
public static int[] addBin(int a[], int b[]){
int[] sum = {0, 0, 0, 0, 0, 0, 0, 0};
int carryover = 0;
int randombanana = 0;
int x = 7;
for(x = 7; x > 0; x--){
randombanana = a[x] + a[x] + carryover;
if(randombanana == 1){
sum[x] = 1;
carryover = 0;
}
else if(randombanana == 2){
sum[x] = 0;
carryover = 1;
}
else if(randombanana == 3){
sum[x] = 1;
carryover = 1;
}
else if(randombanana == 0){
sum[x] = 0;
carryover = 0;
}
else{
System.out.println("Either I [censored] up, or you [censored] up. I'm a genius so I'm going to assume you [censored] up");
}
}
if(carryover == 1){
sum[x] = 1;
}
return sum;
}
The code works fine on single digit numbers, including numbers that require carrying a digit, but on double or triple digit numbers it works when a number is added to itself, but not when different multiple digit numbers are added.
Should be
randombanana = a[x] + b[x] + carryover;
Your for loop isn't handling the 0th bit
for(x = 7; x >= 0; x--){
Assuming the two numbers are of the same length the numbers could be added as follows:
public static int[] addNumbers(int[] firstNum, int[] secondNum) {
int[] result = new int[firstNum.length + 1];
int digitSum, carry = 0, i;
for (i = firstNum.length - 1; i >= 0; i--) {
digitSum = firstNum[i] + secondNum[i] + carry;
result[i + 1] = digitSum % 2;
carry = digitSum / 2;
}
result[0] = carry;
return result;
}
Here is a short and crisp solution.
public static int [] addBinaryNumbers(int a[],int b[])
{
int n =Integer.max(a.length, b.length);
int c[]=new int[n+1];
int carry =0;
for(int i=0;i<n;i++)
{
c[n-i]=(a[i]+b[i]+carry)%2;
carry= (a[i]+b[i]+carry) /2;
}
c[n]=carry;
return c;
}

Tape-Equilibrium Codility Training program

I submitted a solution to Tape Equilibrium problem in Codility. [Codility training][1]
The problem is described as follows:
A non-empty zero-indexed array A consisting of N integers is given. Array A represents numbers on a tape.
Any integer P, such that 0 < P < N, splits this tape into two non-empty parts: A[0], A[1], ..., A[P − 1] and A[P], A[P + 1], ..., A[N − 1].
The difference between the two parts is the value of: |(A[0] + A[1] + ... + A[P − 1]) − (A[P] + A[P + 1] + ... + A[N − 1])|
In other words, it is the absolute difference between the sum of the first part and the sum of the second part.
The solution I submitted is:
class Solution {
public int solution(int[] A) {
long d = A[0] - A[A.length-1];
int l = 1;
int r = A.length -2;
while(l <= r) {
if (Math.abs(d + A[l]) < Math.abs(d - A[r])) {
d += A[l];
l++;
}
else {
d -= A[r];
r--;
}
}
return (int) Math.abs(d);
}
}
I achieved 85% accuracy but couldn't get to correct for some use case. Can someone help me to find what's wrong with this solution. Thanks
The following is my 100% solution:
class Solution {
public int solution(int[] A) {
// write your code in Java SE 8
// int idx = 0;
int sumPre = A[0];
int sumPost = 0;
for (int i = 1; i < A.length; i++) {
sumPost += A[i];
}
int difMin = Math.abs(sumPost - sumPre);
int tempSub = 0;
for (int i = 1; i < A.length - 1; i++) {
sumPre += A[i];
sumPost -= A[i];
tempSub = Math.abs(sumPost - sumPre);
if (tempSub < difMin) {
difMin = tempSub;
// idx = i+1;
}
}
return difMin;
}
}
I can not find their test input, but I find a weird thing is that when "for(int i = 1; i < A.length - 1; i++) " is changed to " for(int i = 1; i < A.length; i++)", then it will trigger two wrong runs...So it still must be a border value issue.
If any one find a test input can break the validity, please share with us, thanks.
Caution: {1,-1} indeed triggered the problem, since P < N, so at least one element should be left in the right part. -> {1,-1},{} is not a valid solution according to the problem definition.
Problem solved.
C# and Linq version for 100% as of May 2021:
public int solution(int[] A)
{
int left = A[0];
int right = A.Skip(1).Aggregate((c,x)=> c+=x);
int min = Math.Abs(left-right);
for(int i=1; i < A.Length-1; i++)
{
left+=A[i];
right-=A[i];
min = Math.Min(min,Math.Abs(left-right));
}
return min;
}
I also tried and got only 83%. My solution:
class Solution {
public int solution(int[] A) {
int[] leftSums = new int[A.length];
for (int i = 0; i < leftSums.length; i++) {
leftSums[i] = 0;
}
int sum = 0;
for (int i = 0; i < A.length; i++) {
sum += A[i];
leftSums[i] = sum;
}
/*
for (int i = 0; i < leftSums.length; i++) {
if (i == 0) {
System.out.print("Left Sums Array is : [");
}
if (i == leftSums.length - 1) {
System.out.println(leftSums[i] + "]");
}
System.out.print(leftSums[i] + ", ");
}
*/
final int total = sum;
//System.out.println("Total is " + total);
int minDiff = Integer.MAX_VALUE;
int currDiff = 0;
for (int i = 0; i < leftSums.length; i++) {
currDiff = Math.abs(leftSums[i] - (total - leftSums[i]));
if (currDiff < minDiff) {
minDiff = currDiff;
}
}
return minDiff;
}
}
Below are those which failed for correctness.
double
two elements 1.280 s WRONG ANSWER
got 0 expected 2000
small
small elements 1.304 s WRONG ANSWER
got 0 expected 20
I tested myself for 2 elements and it worked for me.
I share my 100% score Java solution:
class Solution {
public int solution(int[] A) {
final int size = A.length;
long sumMin = (int)A[0];
long sumMax = 0;
for (int i = 1; i < size; i++) {
sumMax += (int)A[i];
}
int minDif = (int)Math.abs(sumMax - sumMin);
for (int i = 1; i < size; i++) {
int dif = (int)Math.abs(sumMax - sumMin);
if (dif < minDif) {
minDif = dif;
}
sumMin += A[i];
sumMax -= A[i];
}
return minDif;
}
}
The trick is that looping the array twice your complexity is 2N, which is O(N).
Addition results should be 'long' in order not to have problems with big extremes.
For %83 results, the problem is it says "splits this tape into two non-empty parts". So if you split for A[0], your first array will be empty. So you should start with A[1].
Ruby 100%
def solution(a)
left = a.inject(:+)
right = 0
a[0...-1].inject(Float::INFINITY) do |min, el|
left -=el
right += el
candidate = (right-left).abs
min < candidate ? min : candidate
end
end
You can actually do that, with one loop in C#.
Add Linq:
public int solution(int[] A)
{
// write your code in C# 6.0 with .NET 4.5 (Mono)
long sum = A.Sum(p => (long)p);
int val1 = Convert.ToInt32(A.GetValue(0));
int val2 = Convert.ToInt32(sum - val1);
int result = Math.Abs(val1 - val2);
for (int i = 1; i < A.Length-1; i++)
{
val1 += Convert.ToInt32(A.GetValue(i));
val2 -= Convert.ToInt32(A.GetValue(i));
if (result > Math.Abs(val1 - val2))
{
result = Math.Abs(val1 - val2);
}
}
return result;
}
Counterexample for user699681: A = {0, 1, 2, -5, 2},
and for Ism: A = {1, -1}.
TapeEquilibrium in C
int solution(int A[], int N) {
// write your code in C90
long int s_r=0,s_l=A[0],sum=A[0];
int i,min=11111111,r;
for(i=1;i<N;i++)
sum+=A[i];
for(i=1;i<N;i++)
{
s_r=sum-s_l;
r=(int)(s_l-s_r);
if(r<0) r=-r;
if(min>r)min=r;
if(min==0)break;
s_l=sum-s_r+A[i];
}
return min;
}
.. Or even a bit shorter to get 100%
public int solution(int[] A) {
int sumMin = A[0];
int sumMax = 0;
for (int i = 1; i < A.length; i++) {
sumMax += A[i];
}
int minDif = Math.abs(sumMin - sumMax);
for (int i = 1; i < A.length - 1; i++) {
sumMin += A[i];
sumMax -= A[i];
minDif = Math.min(minDif, Math.abs(sumMin - sumMax));
}
return minDif;
}
Here's my implementation using Java 8 IntStream to simplify the sum process...
100% Correct, 100% Performance.
import java.util.stream.IntStream;
public class TapeEquilibrium {
public static int diffIndex( int[] A ) {
long lower = 0, diff = 0, higher = IntStream.of( A ).asLongStream().sum(), minDiff = Integer.MAX_VALUE;
for(int i = 0; i < A.length-1; i++) {
lower += A[i];
higher -= A[i];
diff = Math.abs( higher - lower);
if( diff < minDiff ) {
minDiff = diff;
}
}
return (int) minDiff;
}
public static void main( String[] args ) {
int[] A = { 3, 1, 2, 4, 3 };
System.out.println( diffIndex( A ) );
}
}
here is my Solution with 100% correctness & performance
int solution(int A[], int N)
{
int sum,i;
sum=0;
for(i=0;i<N;i++)
{
sum+=A[i];
A[i]=sum;
}
int min_diff=abs(sum-A[0]*2);
for(i=0;i<N-1;i++)
{
int tmp;
tmp=abs(sum-A[i]*2);
if(tmp<min_diff)
min_diff=tmp;
}
return min_diff;
}
Try this one:
Class Solution {
public int solution(int[] A) {
int sum1 = 0;
int sum2 = 0;
int sum3 = 0;
int len = A.length;
int min = 1 ;
for(int i=0; i<len; i++){
sum2 += A[i];
}
for(int i=0; i< len-1 ; i++){
sum1 += A[i];
sum3 = sum2-sum1;
if( min > Math.abs(sum1- sum3)){
min = Math.abs( sum1 - sum3);
}
}
return min;
}
}
Here is 100% in scala.
def solution(A: Array[Int]): Int = {
//get the whole sum
val allSum = A.sum
//calculate left and right sum
var sumLeft = A(0)
var sumRight = allSum - sumLeft
//set initial diff for P=1
var minDiff = math.abs(sumLeft-sumRight) //difference
// loop for all P after the initial P position
for(p <- 1 to A.length-2){
//recalculate values
sumLeft += A(p)
sumRight -= A(p)
if(math.abs(sumLeft-sumRight) < minDiff){
// if difference is smaller then save new min diff
minDiff = math.abs(sumLeft-sumRight)
}
}
minDiff
}
Performance: https://codility.com/demo/results/trainingZNZCZN-AGC/
long sumofall = 0, leftsideSum = A[0], rightsidesum=0;
int x,LR = 0;
ArrayList listResult = new ArrayList();
for(x=0;x<A.Length;x++)
{
sumofall+= A[x];
}
for(x=1;x<A.Length;x++)
{
rightsidesum = sumofall-leftsideSum;
LR = (int)(rightsidesum - leftsideSum);
if(LR < 0)
{
LR=-LR;
}
listResult.Add(LR);
leftsideSum+=A[x];
}
listResult.Sort();
return Convert.ToInt32(listResult[0].ToString());
}
I share my 100% solution using Java 8.
public class TapeEquilibrium {
public int tapeEquilibrium(int[] A) {
final int N = A.length;
long minimalSum = (int) A[0];
int[] rightSide = Arrays.copyOfRange(A, 1, N);
long maximalSum = IntStream.of(rightSide).sum();
int minimalDifference = (int) Math.abs(maximalSum - minimalSum);
for (int i = 1; i < N; i++) {
int difference = (int) Math.abs(maximalSum - minimalSum);
minimalDifference = difference < minimalDifference ? difference : minimalDifference;
minimalSum += A[i];
maximalSum -= A[i];
}
return minimalDifference;
}
}
Here is my C# solution. Score 100%
if (A == null || A.Length == 0)
{
return 0;
}
int d1 = 0;
int d2 = A.Sum();
int p = 1;
int x = int.MaxValue;
// Replaced using A.sum();
//for (int i=0; i < A.Length; i++)
//{
// d2 += A[i];
//}
for (int j = 0; j < A.Length; j++)
{
if (j < p)
{
d1 += A[j];
}
int ad = Math.Abs(d1 - (d2 - d1));
x = Math.Min(x, ad);
if (p == A.Length -1) { break; }
p++;
}
return x;
Below is my solution which got 100% . As most of you guys did I first got the sum of the array then go through it while adding up left and right parts and then getting the absolutes of them and putting the results into a map then checking the map for the minimum value .
int totalLeft = 0;
int totalRight = 0;
int total = 0;
int result = 0;
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
for (int i = 0; i < A.length; i++) {
total += A[i];
}
for (int i = 0; i < A.length - 1; i++) {
totalRight = total - (A[i] + totalLeft);
totalLeft += A[i];
result = Math.abs(totalLeft - totalRight);
map.put(i, result);
}
return Collections.min(map.values());
TapeEquilibrium in Swift 4
public func solution(_ A : inout [Int]) -> Int {
let P = 1
var splitIndex = P
var firstPartSum = A[splitIndex - 1]
var secondPartSum = Array(A[splitIndex..<A.count]).reduce(0, +)
var minimalDifference = abs(firstPartSum - secondPartSum)
if minimalDifference == 0 {
return minimalDifference
}
splitIndex += 1
while splitIndex < A.count {
firstPartSum += A[splitIndex - 1]
secondPartSum -= A[splitIndex - 1]
let dif = abs(firstPartSum - secondPartSum)
if dif == 0 {
return dif
}
if dif < minimalDifference {
minimalDifference = dif
}
splitIndex += 1
}
return minimalDifference
}
No one posted Javascript solution yet so here is mine with comments:
// you can write to stdout for debugging purposes, e.g.
// console.log('this is a debug message');
function solution(A) {
// write your code in JavaScript (Node.js 8.9.4)
// Making it shorter.
let len = A.length;
// Definitely need to store, and initialise first value.
let left = new Array(len);
left[0] = A[0];
// Same as above, but initialise for last value.
let right = new Array(len);
right[len - 1] = A[len - 1];
let trackLowest = Number.MAX_SAFE_INTEGER;
// One shot calculate for both at any element (from 'outwards' 'in').
// Note there is 2 elements at least, and we already preset the first
// element, so we start and build from index 1.
for (let i = 1; i < len; ++i) {
left[i] = left[i - 1] + A[i];
right[len - 1 - i] = right[len - i] + A[len - 1 - i];
}
// Once the above is done, it's time to calculate the difference.
// If I am at index 0, then I want sum of index 0 AND left, and sum of index
// 1 and right (note not index 0 also).
// We stop before len - 1 because that's the rules and the sum of right will
// have been out of bounds if we want difference for last index, isn't it?
for (let i = 0; i < len - 1; ++i) {
let smallestDiff = Math.abs(left[i] - right[i + 1]);
if (smallestDiff < trackLowest) {
trackLowest = smallestDiff;
}
}
return trackLowest;
}
Basically sum up as you walk the loop simultaneously for the left and right side.
Once done, just get the difference, that's it. O(n) complexity.
My 100% JavaScript solution with O(N) time complexity (should be pretty self-explanatory):
function solution(A) {
let left = 0;
let right = A.reduce((sum, cur) => sum + cur, 0);
let min = Infinity;
for (let p = 0, len = A.length - 1; p < len; p++) {
left += A[p];
right -= A[p];
min = Math.min(min, Math.abs(left - right));
}
return min;
}
100% in Swift 4 for correctness & performance
Detected Time Complexity: 0(n)
var sumMin = A[0]
var sumMax = 0
for i in 1..<A.count {
sumMax += A[i]
}
var diff = abs(sumMin - sumMax)
for i in 1..<A.count-1 {
sumMin += A[i]
sumMax -= A[i]
diff = min(diff, abs(sumMin - sumMax));
}
return diff
Here mine in Java,
// got 91% because "int totalRight = (Arrays.stream(A).sum() - A[0]);" take too long to load
int totalLeft = A[0];
int totalRight = (Arrays.stream(A).sum() - A[0]);
//int afterMinus = 0;
int min = 0;
min = Math.abs(totalLeft - totalRight);
for(int i=1; i<(A.length-1); i++) {
//for(int j=A.length; j>0; j--) {
totalLeft += A[i];
totalRight -= A[i];
//System.out.println("totalLeft = "+ totalLeft);
//System.out.println("totalRight = "+ totalRight);
if(Math.abs(totalLeft - totalRight) < min) {
//System.out.println("min = "+ min);
min = Math.abs(totalLeft - totalRight);
}
}
return min;
// got 100% because change "int totalRight = (Arrays.stream(A).sum() - A[0]);" into for loop
//int totalSum = Arrays.stream(A).sum();
int totalLeft = A[0];
int totalRight = 0;
//int afterMinus = 0;
int min = 0;
for(int i=1; i<A.length; i++) {
totalRight += A[i];
}
min = Math.abs(totalLeft - totalRight);
for(int i=1; i<(A.length-1); i++) {
//for(int j=A.length; j>0; j--) {
totalLeft += A[i];
totalRight -= A[i];
//System.out.println("totalLeft = "+ totalLeft);
//System.out.println("totalRight = "+ totalRight);
if(Math.abs(totalLeft - totalRight) < min) {
//System.out.println("min = "+ min);
min = Math.abs(totalLeft - totalRight);
}
}
return min;
Well, from 91% to 100%, thanks to #sebadagostino after surfing for almost 2 hours for the logic and hints.

Calculating matrix determinant

I am trying to calculate the determinant of a matrix (of any size), for self coding / interview practice. My first attempt is using recursion and that leads me to the following implementation:
import java.util.Scanner.*;
public class Determinant {
double A[][];
double m[][];
int N;
int start;
int last;
public Determinant (double A[][], int N, int start, int last){
this.A = A;
this.N = N;
this.start = start;
this.last = last;
}
public double[][] generateSubArray (double A[][], int N, int j1){
m = new double[N-1][];
for (int k=0; k<(N-1); k++)
m[k] = new double[N-1];
for (int i=1; i<N; i++){
int j2=0;
for (int j=0; j<N; j++){
if(j == j1)
continue;
m[i-1][j2] = A[i][j];
j2++;
}
}
return m;
}
/*
* Calculate determinant recursively
*/
public double determinant(double A[][], int N){
double res;
// Trivial 1x1 matrix
if (N == 1) res = A[0][0];
// Trivial 2x2 matrix
else if (N == 2) res = A[0][0]*A[1][1] - A[1][0]*A[0][1];
// NxN matrix
else{
res=0;
for (int j1=0; j1<N; j1++){
m = generateSubArray (A, N, j1);
res += Math.pow(-1.0, 1.0+j1+1.0) * A[0][j1] * determinant(m, N-1);
}
}
return res;
}
}
So far it is all good and it gives me a correct result. Now I would like to optimise my code by making use of multiple threads to calculate this determinant value.
I tried to parallelize it using the Java Fork/Join model. This is my approach:
#Override
protected Double compute() {
if (N < THRESHOLD) {
result = computeDeterminant(A, N);
return result;
}
for (int j1 = 0; j1 < N; j1++){
m = generateSubArray (A, N, j1);
ParallelDeterminants d = new ParallelDeterminants (m, N-1);
d.fork();
result += Math.pow(-1.0, 1.0+j1+1.0) * A[0][j1] * d.join();
}
return result;
}
public double computeDeterminant(double A[][], int N){
double res;
// Trivial 1x1 matrix
if (N == 1) res = A[0][0];
// Trivial 2x2 matrix
else if (N == 2) res = A[0][0]*A[1][1] - A[1][0]*A[0][1];
// NxN matrix
else{
res=0;
for (int j1=0; j1<N; j1++){
m = generateSubArray (A, N, j1);
res += Math.pow(-1.0, 1.0+j1+1.0) * A[0][j1] * computeDeterminant(m, N-1);
}
}
return res;
}
/*
* Main function
*/
public static void main(String args[]){
double res;
ForkJoinPool pool = new ForkJoinPool();
ParallelDeterminants d = new ParallelDeterminants();
d.inputData();
long starttime=System.nanoTime();
res = pool.invoke (d);
long EndTime=System.nanoTime();
System.out.println("Seq Run = "+ (EndTime-starttime)/100000);
System.out.println("the determinant valaue is " + res);
}
However after comparing the performance, I found that the performance of the Fork/Join approach is very bad, and the higher the matrix dimension, the slower it becomes (as compared to the first approach). Where is the overhead? Can anyone shed a light on how to improve this?
Using This class you can calculate the determinant of a matrix with any dimension
This class uses many different methods to make the matrix triangular and then, calculates the determinant of it. It can be used for matrix of high dimension like 500 x 500 or even more. the bright side of the this class is that you can get the result in BigDecimal so there is no infinity and you'll have always the accurate answer. By the way, using many various methods and avoiding recursion resulted in much faster way with higher performance to the answer. hope it would be helpful.
import java.math.BigDecimal;
public class DeterminantCalc {
private double[][] matrix;
private int sign = 1;
DeterminantCalc(double[][] matrix) {
this.matrix = matrix;
}
public int getSign() {
return sign;
}
public BigDecimal determinant() {
BigDecimal deter;
if (isUpperTriangular() || isLowerTriangular())
deter = multiplyDiameter().multiply(BigDecimal.valueOf(sign));
else {
makeTriangular();
deter = multiplyDiameter().multiply(BigDecimal.valueOf(sign));
}
return deter;
}
/* receives a matrix and makes it triangular using allowed operations
on columns and rows
*/
public void makeTriangular() {
for (int j = 0; j < matrix.length; j++) {
sortCol(j);
for (int i = matrix.length - 1; i > j; i--) {
if (matrix[i][j] == 0)
continue;
double x = matrix[i][j];
double y = matrix[i - 1][j];
multiplyRow(i, (-y / x));
addRow(i, i - 1);
multiplyRow(i, (-x / y));
}
}
}
public boolean isUpperTriangular() {
if (matrix.length < 2)
return false;
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < i; j++) {
if (matrix[i][j] != 0)
return false;
}
}
return true;
}
public boolean isLowerTriangular() {
if (matrix.length < 2)
return false;
for (int j = 0; j < matrix.length; j++) {
for (int i = 0; j > i; i++) {
if (matrix[i][j] != 0)
return false;
}
}
return true;
}
public BigDecimal multiplyDiameter() {
BigDecimal result = BigDecimal.ONE;
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix.length; j++) {
if (i == j)
result = result.multiply(BigDecimal.valueOf(matrix[i][j]));
}
}
return result;
}
// when matrix[i][j] = 0 it makes it's value non-zero
public void makeNonZero(int rowPos, int colPos) {
int len = matrix.length;
outer:
for (int i = 0; i < len; i++) {
for (int j = 0; j < len; j++) {
if (matrix[i][j] != 0) {
if (i == rowPos) { // found "!= 0" in it's own row, so cols must be added
addCol(colPos, j);
break outer;
}
if (j == colPos) { // found "!= 0" in it's own col, so rows must be added
addRow(rowPos, i);
break outer;
}
}
}
}
}
//add row1 to row2 and store in row1
public void addRow(int row1, int row2) {
for (int j = 0; j < matrix.length; j++)
matrix[row1][j] += matrix[row2][j];
}
//add col1 to col2 and store in col1
public void addCol(int col1, int col2) {
for (int i = 0; i < matrix.length; i++)
matrix[i][col1] += matrix[i][col2];
}
//multiply the whole row by num
public void multiplyRow(int row, double num) {
if (num < 0)
sign *= -1;
for (int j = 0; j < matrix.length; j++) {
matrix[row][j] *= num;
}
}
//multiply the whole column by num
public void multiplyCol(int col, double num) {
if (num < 0)
sign *= -1;
for (int i = 0; i < matrix.length; i++)
matrix[i][col] *= num;
}
// sort the cols from the biggest to the lowest value
public void sortCol(int col) {
for (int i = matrix.length - 1; i >= col; i--) {
for (int k = matrix.length - 1; k >= col; k--) {
double tmp1 = matrix[i][col];
double tmp2 = matrix[k][col];
if (Math.abs(tmp1) < Math.abs(tmp2))
replaceRow(i, k);
}
}
}
//replace row1 with row2
public void replaceRow(int row1, int row2) {
if (row1 != row2)
sign *= -1;
double[] tempRow = new double[matrix.length];
for (int j = 0; j < matrix.length; j++) {
tempRow[j] = matrix[row1][j];
matrix[row1][j] = matrix[row2][j];
matrix[row2][j] = tempRow[j];
}
}
//replace col1 with col2
public void replaceCol(int col1, int col2) {
if (col1 != col2)
sign *= -1;
System.out.printf("replace col%d with col%d, sign = %d%n", col1, col2, sign);
double[][] tempCol = new double[matrix.length][1];
for (int i = 0; i < matrix.length; i++) {
tempCol[i][0] = matrix[i][col1];
matrix[i][col1] = matrix[i][col2];
matrix[i][col2] = tempCol[i][0];
}
} }
This Class Receives a matrix of n x n from the user then calculates it's determinant. It also shows the solution and the final triangular matrix.
import java.math.BigDecimal;
import java.text.NumberFormat;
import java.util.Scanner;
public class DeterminantTest {
public static void main(String[] args) {
String determinant;
//generating random numbers
/*int len = 300;
SecureRandom random = new SecureRandom();
double[][] matrix = new double[len][len];
for (int i = 0; i < len; i++) {
for (int j = 0; j < len; j++) {
matrix[i][j] = random.nextInt(500);
System.out.printf("%15.2f", matrix[i][j]);
}
}
System.out.println();*/
/*double[][] matrix = {
{1, 5, 2, -2, 3, 2, 5, 1, 0, 5},
{4, 6, 0, -2, -2, 0, 1, 1, -2, 1},
{0, 5, 1, 0, 1, -5, -9, 0, 4, 1},
{2, 3, 5, -1, 2, 2, 0, 4, 5, -1},
{1, 0, 3, -1, 5, 1, 0, 2, 0, 2},
{1, 1, 0, -2, 5, 1, 2, 1, 1, 6},
{1, 0, 1, -1, 1, 1, 0, 1, 1, 1},
{1, 5, 5, 0, 3, 5, 5, 0, 0, 6},
{1, -5, 2, -2, 3, 2, 5, 1, 1, 5},
{1, 5, -2, -2, 3, 1, 5, 0, 0, 1}
};
*/
double[][] matrix = menu();
DeterminantCalc deter = new DeterminantCalc(matrix);
BigDecimal det = deter.determinant();
determinant = NumberFormat.getInstance().format(det);
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix.length; j++) {
System.out.printf("%15.2f", matrix[i][j]);
}
System.out.println();
}
System.out.println();
System.out.printf("%s%s%n", "Determinant: ", determinant);
System.out.printf("%s%d", "sign: ", deter.getSign());
}
public static double[][] menu() {
Scanner scanner = new Scanner(System.in);
System.out.print("Matrix Dimension: ");
int dim = scanner.nextInt();
double[][] inputMatrix = new double[dim][dim];
System.out.println("Set the Matrix: ");
for (int i = 0; i < dim; i++) {
System.out.printf("%5s%d%n", "row", i + 1);
for (int j = 0; j < dim; j++) {
System.out.printf("M[%d][%d] = ", i + 1, j + 1);
inputMatrix[i][j] = scanner.nextDouble();
}
System.out.println();
}
scanner.close();
return inputMatrix;
}}
The main reason the ForkJoin code is slower is that it's actually serialized with some thread overhead thrown in. To benefit from fork/join, you need to 1) fork all instances first, then 2) wait for the results. Split your loop in "compute" into two loops: one to fork (storing instances of ParallelDeterminants in, say, an array) and another to collect the results.
Also, I suggest to only fork at the outermost level and not in any of the inner ones. You don't want to be creating O(N^2) threads.
There is a new method of calculating the determinant of the matrix you can read more from here
and I've implemented a simple version of this with no fancy optimization techniques or library in plain simple java and I've tested against methods described previously and it was faster on average by a factor of 10
public class Test {
public static double[][] reduce(int row , int column , double[][] mat){
int n=mat.length;
double[][] res = new double[n- 1][n- 1];
int r=0,c=0;
for (int i = 0; i < n; i++) {
c=0;
if(i==row)
continue;
for (int j = 0; j < n; j++) {
if(j==column)
continue;
res[r][c] = mat[i][j];
c++;
}
r++;
}
return res;
}
public static double det(double mat[][]){
int n = mat.length;
if(n==1)
return mat[0][0];
if(n==2)
return mat[0][0]*mat[1][1] - (mat[0][1]*mat[1][0]);
//TODO : do reduce more efficiently
double[][] m11 = reduce(0,0,mat);
double[][] m1n = reduce(0,n-1,mat);
double[][] mn1 = reduce(n-1 , 0 , mat);
double[][] mnn = reduce(n-1,n-1,mat);
double[][] m11nn = reduce(0,0,reduce(n-1,n-1,mat));
return (det(m11)*det(mnn) - det(m1n)*det(mn1))/det(m11nn);
}
public static double[][] randomMatrix(int n , int range){
double[][] mat = new double[n][n];
for (int i=0; i<mat.length; i++) {
for (int j=0; j<mat[i].length; j++) {
mat[i][j] = (Math.random()*range);
}
}
return mat;
}
public static void main(String[] args) {
double[][] mat = randomMatrix(10,100);
System.out.println(det(mat));
}
}
there is a little fault in the case of the determinant of m11nn if happen to be zero it will blow up and you should check for that. I've tested on 100 random samples it rarely happens but I think it worth mentioning and also using a better indexing scheme can also improve the efficiency
This is a part of my Matrix class which uses a double[][] member variable called data to store the matrix data.
The _determinant_recursivetask_impl() function uses a RecursiveTask<Double> object with the ForkJoinPool to try to use multiple threads for calculation.
This method performs very slow compared to matrix operations to get an upper/lower triangular matrix. Try to compute the determinant of a 13x13 matrix for example.
public class Matrix
{
// Dimensions
private final int I,J;
private final double[][] data;
private Double determinant = null;
static class MatrixEntry
{
public final int I,J;
public final double value;
private MatrixEntry(int i, int j, double value) {
I = i;
J = j;
this.value = value;
}
}
/**
* Calculates determinant of this Matrix recursively and caches it for future use.
* #return determinant
*/
public double determinant()
{
if(I!=J)
throw new IllegalStateException(String.format("Can't calculate determinant of (%d,%d) matrix, not a square matrix.", I,J));
if(determinant==null)
determinant = _determinant_recursivetask_impl(this);
return determinant;
}
private static double _determinant_recursivetask_impl(Matrix m)
{
class determinant_recurse extends RecursiveTask<Double>
{
private final Matrix m;
determinant_recurse(Matrix m) {
this.m = m;
}
#Override
protected Double compute() {
// Base cases
if(m.I==1 && m.J==1)
return m.data[0][0];
else if(m.I==2 && m.J==2)
return m.data[0][0]*m.data[1][1] - m.data[0][1]*m.data[1][0];
else
{
determinant_recurse[] tasks = new determinant_recurse[m.I];
for (int i = 0; i <m.I ; i++) {
tasks[i] = new determinant_recurse(m.getSubmatrix(0, i));
}
for (int i = 1; i <m.I ; i++) {
tasks[i].fork();
}
double ret = m.data[0][0]*tasks[0].compute();
for (int i = 1; i < m.I; i++) {
if(i%2==0)
ret += m.data[0][i]*tasks[i].join();
else
ret -= m.data[0][i]*tasks[i].join();
}
return ret;
}
}
}
return ForkJoinPool.commonPool().invoke(new determinant_recurse(m));
}
private static void _map_impl(Matrix ret, Function<Matrix.MatrixEntry, Double> operator)
{
for (int i = 0; i <ret.I ; i++) {
for (int j = 0; j <ret.J ; j++) {
ret.data[i][j] = operator.apply(new Matrix.MatrixEntry(i,j,ret.data[i][j]));
}
}
}
/**
* Returns a new Matrix that is sub-matrix without the given row and column.
* #param removeI row to remove
* #param removeJ col. to remove
* #return new Matrix.
*/
public Matrix getSubmatrix(int removeI, int removeJ)
{
if(removeI<0 || removeJ<0 || removeI>=this.I || removeJ>=this.J)
throw new IllegalArgumentException(String.format("Invalid element position (%d,%d) for matrix(%d,%d).", removeI,removeJ,this.I,this.J));
Matrix m = new Matrix(this.I-1, this.J-1);
_map_impl(m, (e)->{
int i = e.I, j = e.J;
if(e.I >= removeI) ++i;
if(e.J >= removeJ) ++j;
return this.data[i][j];
});
return m;
}
// Constructors
public Matrix(int i, int j) {
if(i<1 || j<1)
throw new IllegalArgumentException(String.format("Invalid array dimensions: (%d,%d)", i, j));
I = i;
J = j;
data = new double[I][J];
}
}
int det(int[][] mat) {
if (mat.length == 1)
return mat[0][0];
if (mat.length == 2)
return mat[0][0] * mat[1][1] - mat[1][0] * mat[0][1];
int sum = 0, sign = 1;
int newN = mat.length - 1;
int[][] temp = new int[newN][newN];
for (int t = 0; t < newN; t++) {
int q = 0;
for (int i = 0; i < newN; i++) {
for (int j = 0; j < newN; j++) {
temp[i][j] = mat[1 + i][q + j];
}
if (q == i)
q = 1;
}
sum += sign * mat[0][t] * det(temp);
sign *= -1;
}
return sum;
}

Find the largest span between the same number in an array

Merry Christmas and hope you are in great Spirits,I have a Question in Java-Arrays as shown below.Im stuck up with this struggling to get it rite.
Consider the leftmost and righmost appearances of some value in an array. We'll say that the "span" is the number of elements between the two inclusive. A single value has a span of 1. Write a **Java Function** that returns the largest span found in the given array.
**Example:
maxSpan({1, 2, 1, 1, 3}) → 4,answer is 4 coz MaxSpan between 1 to 1 is 4
maxSpan({1, 4, 2, 1, 4, 1, 4}) → 6,answer is 6 coz MaxSpan between 4 to 4 is 6
maxSpan({1, 4, 2, 1, 4, 4, 4}) → 6,answer is 6 coz Maxspan between 4 to 4 is 6 which is greater than MaxSpan between 1 and 1 which is 4,Hence 6>4 answer is 6.
I have the code which is not working,it includes all the Spans for a given element,im unable to find the MaxSpan for a given element.
Please help me out.
Results of the above Program are as shown below
Expected This Run
maxSpan({1, 2, 1, 1, 3}) → 4 5 X
maxSpan({1, 4, 2, 1, 4, 1, 4}) → 6 8 X
maxSpan({1, 4, 2, 1, 4, 4, 4}) → 6 9 X
maxSpan({3, 3, 3}) → 3 5 X
maxSpan({3, 9, 3}) → 3 3 OK
maxSpan({3, 9, 9}) → 2 3 X
maxSpan({3, 9}) → 1 1 OK
maxSpan({3, 3}) → 2 3 X
maxSpan({}) → 0 1 X
maxSpan({1}) → 1 1 OK
::Code::
public int maxSpan(int[] nums) {
int count=1;//keep an intial count of maxspan=1
int maxspan=0;//initialize maxspan=0
for(int i=0;i<nums.length;i++){
for(int j=i+1;j<nums.length;j++){
if(nums[i] == nums[j]){
//check to see if "i" index contents == "j" index contents
count++; //increment count
maxspan=count; //make maxspan as your final count
int number = nums[i]; //number=actual number for maxspan
}
}
}
return maxspan+1; //return maxspan
}
Since a solution has been given, here is a more efficient solution which uses one pass.
public static void main(String... args) {
int maxspan = maxspan(3, 3, 3, 2, 1, 4, 3, 5, 3, 1, 1, 1, 1, 1);
System.out.println(maxspan);
}
private static int maxspan(int... ints) {
Map<Integer, Integer> first = new LinkedHashMap<Integer, Integer>(); // use TIntIntHashMap for efficiency.
int maxspan = 0; // max span so far.
for (int i = 0; i < ints.length; i++) {
int num = ints[i];
if (first.containsKey(num)) { // have we seen this number before?
int span = i - first.get(num) + 1; // num has been found so what is the span
if (span > maxspan) maxspan = span; // if the span is greater, update the maximum.
} else {
first.put(num, i); // first occurrence of number num at location i.
}
}
return maxspan;
}
I see the following problems with your attempt:
Your count is completely wrong. You can instead calculate count from i and j: j - i + 1
You're overriding maxcount as soon as you get any span, so you're going to end up with the last span, not the maximum span. Fix it by going maxspan = Math.max(maxspan, count);.
You can remove the line int number = nums[i]; as you never use number.
Remove the +1 in the returnmaxspan+1;` if you follow my tips above.
Initial maxspan should be 1 if there are any values in the array, but 0 if the array is empty.
That should help you get it working. Note that you can do this in a single pass of the array, but that's probably stretching it too far for you. Concentrate on getting your code to work before considering efficiency.
Here is the solution of this problem:
public int maxSpan(int[] nums) {
int maxSpan=0;
int tempSpan=0;
if(nums.length==0){
return 0;
}
for(int i=0;i<nums.length;i++){
for(int j=nums.length-1;j>i;j--){
if(nums[i]==nums[j]){
tempSpan=j-i;
break;
}
}
if(tempSpan>maxSpan){
maxSpan=tempSpan;
}
}
return maxSpan+1;
}
I did it with a List. Easier way to do it.
The only problem is if the Array is too big, maybe it's gonna take a while..
import java.util.ArrayList;
import java.util.List;
public class StackOverflow {
public static void main(String[] args) {
List<Integer> listNumbers = new ArrayList<Integer>();
listNumbers.add(3);
listNumbers.add(3);
listNumbers.add(3);
listNumbers.add(2);
listNumbers.add(1);
listNumbers.add(4);
listNumbers.add(3);
listNumbers.add(5);
listNumbers.add(1);
listNumbers.add(1);
listNumbers.add(1);
listNumbers.add(1);
listNumbers.add(1);
listNumbers.add(3);
int result = 0;
Integer key = null;
for(Integer i : listNumbers){
int resultDistance = returnDistance(listNumbers, i);
if (resultDistance > result){
result = resultDistance;
key = i;
}
}
System.out.println("MaxSpan of key " + key + " is: " + result);
}
private static int returnDistance(List<Integer> listNumbers, Integer term){
Integer startPosition = null;
Integer endPosition = null;
boolean bolStartPosition = false;
boolean bolResult = false;
int count = 1;
int result = 0;
for (Integer i : listNumbers){
if (i == term && !bolStartPosition){
startPosition = count;
bolStartPosition = true;
continue;
}
if (i == term && bolStartPosition){
endPosition = count;
}
count++;
}
if (endPosition != null){
// because it's inclusive from both sides
result = endPosition - startPosition + 2;
bolResult = true;
}
return (bolResult?result:-1);
}
}
public int maxSpan(int[] nums) {
int b = 0;
if (nums.length > 0) {
for (int i = 0; i < nums.length; i++) {
int a = nums[0];
if (nums[i] != a) {
b = nums.length - 1;
} else {
b = nums.length;
}
}
} else {
b = 0;
}
return b;
}
One brute force solution may like this, take one item from the array, and find the first occurance of item from the left most, and calculate the span, and then compare with the previous result.
public int maxSpan(int[] nums) {
int result = 0;
for(int i = 0; i < nums.length; i++) {
int item = nums[i];
int span = 0;
for(int j = 0; j<= i; j++) {//find first occurance of item from the left
if(nums[j]==item) {
span = i -j+1;
break;
}
}
if(span>result) {
result = span;
}
}
return result;
}
Here is the solution -
public int maxSpan(int[] nums) {
int span = 0;
for (int i = 0; i < nums.length; i++) {
for(int j = i; j < nums.length; j++) {
if(nums[i] == nums[j]) {
if(span < (j - i + 1)) {
span = j -i + 1;
}
}
}
}
return span;
}
public int maxSpan(int[] nums) {
int span = 0;
//Given the values at position i 0..length-1
//find the rightmost position of that value nums[i]
for (int i = 0; i < nums.length; i++) {
// find the rightmost of nums[i]
int j =nums.length -1;
while(nums[i]!=nums[j])
j--;
// j is at the rightmost posititon of nums[i]
span = Math.max(span,j-i+1);
}
return span;
}
public int maxSpan(int[] nums) {
//convert the numnber to a string
String numbers = "";
if (nums.length == 0)
return 0;
for(int ndx = 0; ndx < nums.length;ndx++){
numbers += nums[ndx];
}
//check beginning and end of string
int first = numbers.indexOf(numbers.charAt(0));
int last = numbers.lastIndexOf(numbers.charAt(0));
int max = last - first + 1;
int efirst = numbers.indexOf(numbers.charAt(numbers.length()-1));
int elast = numbers.lastIndexOf(numbers.charAt(numbers.length()-1));
int emax = elast - efirst + 1;
//return the max span.
return (max > emax)?max:emax;
}
public int maxSpan(int[] nums) {
int current = 0;
int currentcompare = 0;
int counter = 0;
int internalcounter = 0;
if(nums.length == 0)
return 0;
for(int i = 0; i < nums.length; i++) {
internalcounter = 0;
current = nums[i];
for(int x = i; x < nums.length; x++) {
currentcompare = nums[x];
if(current == currentcompare) {
internalcounter = x - i;
}
if(internalcounter > counter) {
counter = internalcounter;
}
}
}
return counter + 1;
}
public int maxSpan(int[] nums) {
if(nums.length<1){
return 0;
}
int compare=1;
for (int i=0; i<nums.length; i++){
for (int l=1; l<nums.length; l++){
if((nums[l]==nums[i])&&(Math.abs(l)-Math.abs(i))>=compare){
compare = Math.abs(l)-Math.abs(i)+1;
}
}
}
return compare;
}
public static int MaxSpan(int[] input1, int key)
{
int Span = 0;
int length = input1.length;
int i,j,k = 0;
int start = 0, end = 0 ;
k = key;
for (int l = 0; l < length; l++) {
if(input1[l] == k) { start = l;
System.out.println("\nStart = " + start);
break;
}
}
if(start == 0) { Span = 0; System.out.println("Key not found"); return Span;}
for (j = length-1; j> start; j--) {
if(input1[j] == k) { end = j;
System.out.println("\nEnd = " + end);
break;
}
}
Span = end - start;
System.out.println("\nStart = " + start + "End = " + end + "Span = " + Span);
return Span;
}
public int maxSpan(int[] nums) {
int length = nums.length;
if(length <= 0)
return 0;
int left = nums[0];
int rigth = nums[length - 1];
int value = 1;
//If these values are the same, then the max span is length
if(left == rigth)
return length;
// the last match is the largest span for any value
for(int x = 1; x < length - 1; x++)
{
if(nums[x] == left || nums[x] == rigth)
value = x + 1;
}
return value;
}
public int maxSpan(int[] nums) {
int count, largest=0;
for (int x=0; x< nums.length; x++)
{
for (int y=0; y< nums.length; y++)
{
if (nums[x]==nums[y])
{
count= y-x+1;
if (count > largest)
{
largest= count;
}
}
}
}
return largest;
}
import java.io.*;
public class maxspan {
public static void main(String args[])throws java.io.IOException{
int A[],span=0,pos=0;
DataInputStream in=new DataInputStream(System.in);
System.out.println("enter the number of elements");
A=new int[Integer.parseInt(in.readLine())];
int i,j;
for(i=0;i<A.length;i++)
{
A[i]=Integer.parseInt(in.readLine());
}
for(i=0;i<A.length;i++)
{
for(j=A.length-1;j>=0;j--)
if(A[i]==A[j]&&(j-i)>span){span=j-i;pos=i;}
}
System.out.println("maximum span => "+(span+1)+" that is of "+A[pos]);
}
}
public static int maxSpan(int[] nums) {
int left = 0;
int right = 0;
for (int i = 0; i < nums.length; i++) {
if (nums[0] == nums[nums.length - 1 - i]) {
left = nums.length - i;
break;
} else if (nums[nums.length - 1] == nums[i]) {
right = nums.length - i;
break;
}
}
return Math.max(left, right);
}
The above solutions are great, if your goal is to avoid using Arrays.asList and indexOf and LastIndexOf, the code below does the job as lazy as possible, while still being clear and concise.
public int maxSpan(int[] nums) {
if(nums.length < 2){ //weed out length 0 and 1 cases
return nums.length;
}
int maxSpan = 1; //start out as 1
for(int a = 0; a < nums.length; a++){
for(int b = nums.length - 1; b > a; b--){
if(nums[a] == nums[b]){
maxSpan = Math.max(maxSpan, (b + 1 - a));
//A little tricky getting those indices together.
break; //there's no reason to continue,
//at least for this single loop execution inside another loop
}
}
}
return maxSpan; //the maxSpan is here!
}
The Math.max method returns the larger of 2 values, one of them if they are equal.
This is how I did it:
public int maxSpan(int[] nums) {
for (int span=nums.length; span>0; span--) {
for (int i=0; i<nums.length-span+1; i++) {
if (nums[i] == nums[i+span-1]) return span;
}
}
return 0;
}
I am not sure, if I have to use 2 for-loops... or any loop at all?
If not, this version functions without any loop.
At first you check, if the length of the array is > 0. If not, you simply return the length of the array, which will correspond to the correct answer.
If it is longer than 0, you check if the first and last position in the array have the same value.
If yes, you return the length of the array as the maxSpan.
If not, you substract a 1, since the value appears twice in the array.
Done.
public int maxSpan(int[] nums) {
if(nums.length > 0){
if(nums[0] == nums[nums.length - 1]){
return nums.length;
}
else{
return nums.length - 1;
}
}
return nums.length;
}
public int maxSpan(int[] nums) {
Stack stack = new Stack();
int count = 1;
int value = 0;
int temp = 0;
if(nums.length < 1) {
return value;
}
for(int i = 0; i < nums.length; i++) {
for(int j = nums.length - 1; j >= i; j--) {
if(nums[i] == nums[j]) {
count = (j - i) + 1;
stack.push(count);
count = 1;
break;
}
}
}
if(stack.peek() != null) {
while(stack.size() != 0) {
temp = (Integer) stack.pop();
if(value <= temp) {
value = temp;
} else {
value = value;
}
}
}
return value;
}
public int maxSpan(int[] nums) {
int totalspan=0;
int span=0;
for(int i=0;i<nums.length;i++)
{
for (int j=nums.length-1;j>i-1;j--)
{
if(nums[i]==nums[j])
{
span=j-i+1;
if (span>totalspan)
totalspan=span;
break;
}
}
}
return totalspan;
}
public int maxSpan(int[] nums) {
int max_span=0, j;
for (int i=0; i<nums.length; i++){
j=nums.length-1;
while(nums[i]!=nums[j]) j--;
if (j-i+1>max_span) max_span=j-i+1;
}
return max_span;
}
Linear solution with a Map storing the first occurrence, and calculating the distance from it for the next occurrences:
public int maxSpan(int[] nums) {
int span = 0;
Map<Integer, Integer> first = new HashMap<Integer, Integer>();
for (int i = 0; i < nums.length; i++) {
if (!first.containsKey(nums[i]))
first.put(nums[i], i);
span = Math.max(span, (i - first.get(nums[i])) + 1);
}
return span;
}

Categories

Resources