Depth of an array - java

If we are given an array arr1 consisting of n integers, we can calculate the depth of it in the following way as in image.
The first line of input contains 3 integers n, a, b where n is the size of array.
The second line of input contains array elements. Now if the depth of array = a/b we need to print "yes" else "no".
I have tried to implement the following code:
public static void solve(int n, int a,int b, int[] arr) {
String result = "";
double depth = 0;
for (int i = 0; i < n - 1; i++) {
depth = (double)((double)(depth + arr[i]) + (double)(1 / arr[i + 1]));
}
double d = (double) a / b;
if (depth == d) {
result = "YES";
} else {
result = "NO";
}
System.out.println(result);
}

Related

Multiply numbers represented as arrays in Java?

I have to write a function that multiplies two numbers represented by two int arrays (so I can't use ArrayLists or something).
Each digit of a number is represented by an int between 0 and 9 in the array, no element should be greater than that.
The first element of the array represents the last digit of the number and so on, therefore the number 1234 would be {4,3,2,1} as an array in this function.
I thought multiplying those arrays that way would be similar to long multiplication, so I tried to implement it in a similar way: You multiply every digit of the first array with every digit of the second one and store the rest if the result is equal or greater to 10 and then add it to the next digit. However, I seem to have done something wrong in the code (maybe the calculation of the rest??) because the result of my function is not correct: I tested it with 190 times 86 (represented by the arrays {0,9,1} and {6,8}) and get 15342 ({2,4,3,5,1}) instead of the actual result 16340 (which would be {0,4,3,6,1}).
Can somebody here help me out with this please? This is my code:
import java.util.Arrays;
public class MultiplyArrays {
static int[ ] times(int[ ] a, int[ ] b) {
int[] arr = new int[a.length + b.length - 1];//arr should be the result of a*b. The result shouldn't be shorter than that
int tmp = 0;//stores the rest of two-digit numbers
for(int i = b.length - 1; i >= 0; i--){
for(int j = 0; j < a.length; j++){//should multiply all digits of a with the current index of b
arr[i + j] = (arr[i + j] + (b[i] * a[j] + tmp)) % 10;//sets the value of the (i+j)th index in arr to the multiplication of two numbers from a and b adding the rest tmp.
if((arr[i + j] + b[i] * a[j] + tmp) < 10){//if this number is less than 10, there is no rest
tmp = 0;
}
else{//otherwise, the rest should be the second digit
tmp = (((arr[i + j] + (b[i] * a[j] + tmp))) - ((arr[i + j] + (b[i] * a[j] + tmp)) % 10)) / 10;//something in the formula for the rest is wrong, I guess
}
}
}
if(tmp != 0){//if the last number of the array containing the result is calculated and there still is a rest, a new array with one more digit is created
int[] arr2 = new int[arr.length + 1];
for(int i = arr.length - 1; i >= 0; i--){//the new array copies all numbers from the old array
arr2[i] = arr[i];
arr2[arr2.length - 1] = tmp;//the last space is the rest now
}
return arr2;
}
else{//if there is no rest after calculating the last number of arr, a new array isn't needed
return arr;
}
}
public static void main(String[] args) {//test the function with 190 * 86
int[] a = {0,9,1};
int[] b = {6,8};
System.out.println(Arrays.toString(times(a,b)));
}
}
Maybe this comes from the fact that your indices in the for-loops of the times()-method are incrementing AND decrementing.
The i is going down and the j is going up.
Also, in the second for loop, you should only increment to 'a.length - 1', not to 'a.length'.
Arbitrary precision multiplication is more complex than it seems, and contains corner cases (like one and zero). Fortunately, Java has an arbitrary precision type; BigInteger. In order to use it here, you would need to create two additional methods; one for converting an int[] to a BigInteger, and the second the convert a BigInteger to an int[].
The first can be done with a single loop adding each digit at index i (multiplied by 10i) to a running total. Like,
private static BigInteger fromArray(int[] arr) {
BigInteger bi = BigInteger.ZERO;
for (int i = 0, pow = 1; i < arr.length; pow *= 10, i++) {
bi = bi.add(BigInteger.valueOf(arr[i] * pow));
}
return bi;
}
And the second can be done a number of ways, but the easiest is simply to convert the BigInteger to a String to get the length() - once you've done that, you know the length of the output array - and can populate the digits in it. Like,
private static int[] toArray(BigInteger bi) {
String s = bi.toString();
int len = s.length();
int[] r = new int[len];
for (int i = 0; i < len; i++) {
r[i] = s.charAt(len - i - 1) - '0';
}
return r;
}
Finally, call those two methods and let BigInteger perform the multiplication. Like,
static int[] times(int[] a, int[] b) {
BigInteger ba = fromArray(a), bb = fromArray(b);
return toArray(ba.multiply(bb));
}
Running your original main with those changes outputs (as expected)
[0, 4, 3, 6, 1]
Well, your thought would work with addition, but on multiplication you multiply each digit of one with the whole number of the other and step one digit to the left (*10) each time you change the multiplication digit of the first number.
So you might brought something into confusion.
I just solved it in a more structured way, running the debugger will hopefully explain the process. In the solutions you can remove the trailing / leading zero by checking the digit if 0 and replace the array with one of length - 1.
The solutions are:
With conditions mentioned (numbers in reverse order):
public static void main(String[] args) {
int[] a = {3,2,1};
int[] b = {9,8};
System.out.println("Result is: " + Arrays.toString(calculate(a, b)));
}
private static int[] calculate(int[] a, int[] b) {
// final result will be never longer than sum of number lengths + 1
int[] finalResult = new int[a.length + b.length + 1];
int position = 0;
for(int i = 0; i < a.length; i++) {
int[] tempResult = multiplyWithOther(a[i], b);
addToFinalResult(finalResult, tempResult, position);
position++;
}
return finalResult;
}
private static int[] multiplyWithOther(int number, int[] otherArray) {
// The number cannot be more digits than otherArray.length + 1, so create a temp array with size +1
int[] temp = new int[otherArray.length + 1];
// Iterate through the seconds array and multiply with current number from first
int remainder = 0;
for(int i = 0; i < otherArray.length; i++) {
int result = number * otherArray[i];
result += remainder;
remainder = result / 10;
temp[i] = result % 10;
}
// Add remainder (even if 0) to start
temp[temp.length - 1] = remainder;
return temp;
}
private static void addToFinalResult(int[] finalResult, int[] tempResult, int position) {
int remainder = 0;
for(int i = 0; i < tempResult.length; i++) {
int currentValue = tempResult[i];
int storedValue = finalResult[i + position];
int sum = storedValue + currentValue + remainder;
remainder = sum / 10;
finalResult[i + position] = sum % 10;
}
finalResult[position + tempResult.length] = remainder;
}
And with numbers in normal order in array:
public static void main(String[] args) {
int[] a = {1,2,3,6};
int[] b = {8, 9, 1};
System.out.println("Result is: " + Arrays.toString(calculate(a, b)));
}
private static int[] calculate(int[] a, int[] b) {
// final result will be never longer than sum of number lengths + 1
int[] finalResult = new int[a.length + b.length + 1];
int positionFromEnd = 0;
for(int i = 1; i <= a.length; i++) {
int[] tempResult = multiplyWithOther(a[a.length-i], b);
addToFinalResult(finalResult, tempResult, positionFromEnd);
positionFromEnd++;
}
return finalResult;
}
private static int[] multiplyWithOther(int number, int[] otherArray) {
// The number cannot be more digits than otherArray.length + 1, so create a temp array with size +1
int[] temp = new int[otherArray.length + 1];
// Iterate through the seconds array and multiply with current number from first
int remainder = 0;
for(int i = 1; i <= otherArray.length; i++) {
int result = number * otherArray[otherArray.length - i];
result += remainder;
remainder = result / 10;
temp[otherArray.length - i +1] = result % 10;
}
// Add remainder (even if 0) to start
temp[0] = remainder;
return temp;
}
private static void addToFinalResult(int[] finalResult, int[] tempResult, int positionFromEnd) {
int remainder = 0;
for(int i = 1; i <= tempResult.length; i++) {
int currentValue = tempResult[tempResult.length - i];
int storedValue = finalResult[finalResult.length - positionFromEnd - i];
int sum = storedValue + currentValue + remainder;
remainder = sum / 10;
finalResult[finalResult.length - positionFromEnd - i] = sum % 10;
}
finalResult[finalResult.length - positionFromEnd - tempResult.length - 1] = remainder;
}

prime factorization decryption

I have a program that is supposed to decrypt a number to its primes. The primes also have an order: for instance, 2 is the 1st prime number, 3 is the second 5 is the third and so on. The indexes are 1 is for a, two is for b, three is for c and so on. I don't know how to compare the two array lists in order to assign an index to each prime so I can decode a word which is encrypted in the number 72216017. The number 72216017 has the primes 17,19,47,67,71. If 2,3,5,7,11... are a,b,c,d,e... these five prime numbers make up the word ghost, I just don't know how to assign and sort these numbers by their index.
package name;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class PrimeFactorsEffective {
private static int z;
private int w = z;
public static List<Integer> primeFactors(int numbers) {
int n = numbers;
List<Integer> factors = new ArrayList<Integer>();
for (int i = 2; i <= n / i; i++) {
while (n % i == 0) {
factors.add(i);
n /= i;
}
if (n > 1) {
factors.add(n);
System.out.println(factors);
z = Collections.max(factors);
}
}
return factors;
}
public static void main(String[] args) {
System.out.println("Primefactors of 72216017");
for (Integer integer : primeFactors(72216017)) {
System.out.println(integer);
}
List<Integer> factors1 = new ArrayList<Integer>();
List<String> index1 = new ArrayList<String>();
int i;
int element = 0;
int num = 0;
int maxCheck = z; // maxCheck limit till which you want to find prime numbers
boolean isPrime = true;
String primeNumbersFound = "";
//Start loop 1 to maxCheck
for (i = 1; i <= maxCheck; i++) {
isPrime = CheckPrime(i);
if (isPrime) {
primeNumbersFound = primeNumbersFound + i + " ";
factors1.add(i);
factors1.get(num);
}
}
System.out.println("Prime numbers from 1 to " + maxCheck + " are:");
System.out.println(factors1);
}
public static boolean CheckPrime(int numberToCheck) {
int remainder;
for (int i = 2; i <= numberToCheck / 2; i++) {
remainder = numberToCheck % i;
if (remainder == 0) {
return false;
}
}
return true;
}
}
You can store the primes in a List (primes in this list will be in increasing order). Now you can use Collections.BinarySearch to get the index of the prime for which you wan to find the corresponding alphabet. Once you got the index (index here according to you starts from 1, so a's index is 1, b's index is 2, c's index is 3 and so on) you can do simply something like char currentCharacter = (char) ('a' + primeIndex - 1) and the variable currentCharacter will store the alphabet corresponding to primeIndex.
Some other minor things that I'd like to suggest:
Which checking whether a number is prime or not, you can simply check upto square-root of numberToCheck. So you can replace your loop for (int i = 2; i <= numberToCheck / 2; i++) to for (int i = 2; i*i <= numberToCheck; i++). Note that It is not a good idea to calculate square-root using Math.sqrt, instead you can have a condition like i*i <= numberToCheck.
Please refrain from naming your packages that seem to be random.
As of Java SE 7 explicit type-arguments while initializing the list are not required. You can replace List<Integer> factors1 = new ArrayList<Integer>() with List<Integer> factors1 = new ArrayList<>(). Please read this for more information.
Your factor method don't really look good to me, it don't give correct results. Please see the following method that gives correct result:
{{
public static List<Integer> primeFactors(int numbers) {
int n = numbers;
List<Integer> factors = new ArrayList<>();
for (int i = 2; n>1; i++) {
while (n % i == 0) {
factors.add(i);
n /= i;
}
}
z = Collections.max(factors);
return factors;
}

Subset sum for double data-type?

I have the following code for subset sum which is suitable for integers. How to extend this code to double data type input? for example, how to extend this same code when the input is 1.01,2.65,3.08,4.07,5.12 (say) and output is 15.62 (say).These inputs and out are example even if they vary the code should work.
// A Java program to count all subsets with given sum.
import java.util.ArrayList;
public class subset_sum
{
// dp[i][j] is going to store true if sum j is
// possible with array elements from 0 to i.
static boolean[][] dp;
static void display(ArrayList<Integer> v)
{
System.out.println(v);
}
// A recursive function to print all subsets with the
// help of dp[][]. Vector p[] stores current subset.
static void printSubsetsRec(int arr[], int i, int sum,
ArrayList<Integer> p)
{
// If we reached end and sum is non-zero. We print
// p[] only if arr[0] is equal to sun OR dp[0][sum]
// is true.
if (i == 0 && sum != 0 && dp[0][sum])
{
p.add(arr[i]);
display(p);
p.clear();
return;
}
// If sum becomes 0
if (i == 0 && sum == 0)
{
display(p);
p.clear();
return;
}
// If given sum can be achieved after ignoring
// current element.
if (dp[i-1][sum])
{
// Create a new vector to store path
ArrayList<Integer> b = new ArrayList<>();
b.addAll(p);
printSubsetsRec(arr, i-1, sum, b);
}
// If given sum can be achieved after considering
// current element.
if (sum >= arr[i] && dp[i-1][sum-arr[i]])
{
p.add(arr[i]);
printSubsetsRec(arr, i-1, sum-arr[i], p);
}
}
// Prints all subsets of arr[0..n-1] with sum 0.
static void printAllSubsets(int arr[], int n, int sum)
{
if (n == 0 || sum < 0)
return;
// Sum 0 can always be achieved with 0 elements
dp = new boolean[n][sum + 1];
for (int i=0; i<n; ++i)
{
dp[i][0] = true;
}
// Sum arr[0] can be achieved with single element
if (arr[0] <= sum)
dp[0][arr[0]] = true;
// Fill rest of the entries in dp[][]
for (int i = 1; i < n; ++i)
for (int j = 0; j < sum + 1; ++j)
dp[i][j] = (arr[i] <= j) ? (dp[i-1][j] ||
dp[i-1][j-arr[i]])
: dp[i - 1][j];
if (dp[n-1][sum] == false)
{
System.out.println("There are no subsets with" +
" sum "+ sum);
return;
}
// Now recursively traverse dp[][] to find all
// paths from dp[n-1][sum]
ArrayList<Integer> p = new ArrayList<>();
printSubsetsRec(arr, n-1, sum, p);
}
//Driver Program to test above functions
public static void main(String args[])
{
int arr[] = {1, 2, 3, 4, 5};
int n = arr.length;
int sum = 10;
printAllSubsets(arr, n, sum);
}
}
Output:[4, 3, 2, 1] [5, 3, 2] [5, 4, 1]
I found answer to this question by simply converting double to integer by calculating decimal places and multiply it by 100(say) as the algorithm uses addition this change does not affect final values in that case I divided the final value by 100 to get the result and displayed it in double data type

Modifying Summation using Recursion

How do I modify the summation method using recursive definition to get the sum of 1 to N via - (1 to N/2) + ((N/2+1) to N)?
I'm confused a bit here, I've typed out something along the lines of this, but it's not recursion:
public static int Sum(int n){
int sum1 = 0;
int sum2 = 0;
int totalSum = 0;
for(int i = 1; i <= n/2; i++){
sum1 += i;
}
for(int i = n/2 + 1; i <= n; i++){
sum2 += i;
}
totalSum = sum1 + sum2;
return totalSum;
}
First off, your implementation is not recursive.
Your question states the right algorithm: to sum the values between 1 and n, you can sum them between 1 and n/2, then between n/2 + 1 and n. This means we need to create a helper function sum(int a, int b) whose goal will be to return the sum of all the values between a and b.
The base case is when a == b: in this case, the helper should just return a.
In the recursive step, we do the previous algorithm: sum from a to (a+b)/2 and sum from (a+b)/2 + 1 to b.
This would be an implementation:
public static int sum(int a, int b) {
if (a == b) {
return a;
}
int middle = (a + b) / 2;
return sum(a, middle) + sum(middle + 1, b);
}
with this, the initial task becomes:
public static int sum(int n) {
return sum(1, n);
}
Some samples:
public static void main(String[] args) {
System.out.println(sum(4)); // prints 10
System.out.println(sum(5)); // prints 15
System.out.println(sum(6)); // prints 21
}

substring difference between two strings

Given two strings of length n,P = p1...pn and Q = q1...qn, we define M(i, j, k) as the number of mismatches between pi...pi+k-1 and qj..qj+k-1. That is in set notation, M(i, j, k) refers to the size of the set { 0<=x<k | pi+x not equal to qj+x| }.
Given an integer K, your task is to find the maximum length L such that there exists pair of indices (i,j) for which we have M(i, j, L) <= K. Of course, we should also have i+L-1 <=n and j+L-1 <=n.
Input
First line of input contains a single integer T (1 <=T <=10). T test cases follow.
Each test case consists of an integer K and two strings P and Q separated by a single space.
Output
For each test case output a single integer L which is the maximum value for which there exists pair of indices (i,j) such that M(i, j, L) <=K.
Constraints
0 <= K <= length of the string P
Both P & Q would have the same length
The size of each of the string would be at the max 1500
All characters in P & Q are lower-case English letters.
Sample Input
3
2 tabriz torino
0 abacba abcaba
3 helloworld yellomarin
Sample Output
4
3
8
Explanation:
First test-case: If we take "briz" from the first string, and "orin" from the second string, then the number of mismatches between these two substrings is equal to 2, and the length of these substrings are 4. That's we have chosen i=3, j=2, L=4, and we have M(3,2,4) = 2.
Second test-case: Since K=0, we should find the longest common substring for the given input strings. We can choose "aba" as the result, and we don't have longer common substring between two strings. So, the answer is 3 for this test-case. That's we have chosen i=1, j=4, and L=3, and we have M(1,4,3)=0.
Third test-case: We can choose "hellowor" from first string and "yellomar" from the second string. So, we have chosen i=1, j=1, and L=8, and we have M(1,1,8)=3. Of course we can also choose i=2, j=2, and L=8 and we still have M(2,2,8)=3.
here is my implementation
import java.io.*;
import java.util.*;
class Solution {
public static int mismatch(String a, String b, int ii, int jj, int xx) {
int i, j = 0;
for (i = 0; i < xx; i++) {
if (a.charAt(ii) != b.charAt(jj)) {
j++;
}
ii++;
jj++;
}
return j;
}
public static boolean find(int x, String a, String b, int kx) {
int nn = a.length();
for (int i = 0; i <= (nn - x); i++) {
for (int j = 0; j <= (nn - x); j++) {
int k;
k = mismatch(a, b, i, j, x);
if (k == kx) {
return true;
}
}
}
return false;
}
public static void main(String args[]) throws IOException {
Scanner scanner = new Scanner(System.in);
int t = scanner.nextInt();
while (t > 0) {
int k, n;
String a, b;
k = scanner.nextInt();
a = scanner.next();
b = scanner.next();
n = a.length();
int i = (n + k) / 2;
int st = k, en = n
while (i != k || i != n) {
boolean ch = false, chh = false;
ch = find(i, a, b, k);
if (i != n) {
chh = find(i + 1, a, b, k);
}
if (i == n && ch == true) {
System.out.println(i);
break;
}
if (ch == true && chh == false) {
System.out.println(i);
break;
}
if (ch) {
st = i;
i = (i + en + 1) / 2;
} else {
en = i;
i = (st + i) / 2;
}
}
t--;
}
}
}
the above implementation is taking 5.1 sec for input 0f 1500 string length.But maximum time limit in java is 5sec.if any one can improve this code,please kindly share yor thougths
Your code doesn't take 5.1s on the site. They stop running your code as soon as it exceeds the time limit. Your code might be taking even minutes. So, even if you optimize it with this algorithm you will again get 5.1s in details section. So work on your algo, not optimization!
You could make a boolean array compare[n,n], for which compare[i,j]=(a[i]==b[j]). Later use it instead of making repeating comparisons. You'll have incomparably less comparisons and addressing.
public static int mismatch(String a, String b, int ii, int jj, int xx) {
int i, j = 0;
for (i = 0; i < xx; i++) {
if (! compare[ii,jj]) {
j++;
}
ii++;
jj++;
}
return j;
}

Categories

Resources