I have two dimensional float array as below
{0.2,0.0,0.3,0.0,0.0}
{0.4,0.1,0.0,0.0,0.9}
{0.0,0.0,0.0,0.3,0.6}
I want to get the following output
{0.6,0.0,0.3,0.0,0.0}
{0.6,0.1,0.0,0.0,1.5}
{0.0,0.0,0.0,0.3,1.5}
If you analyse, I sum each column's non zero value and update all non zero values with that sum value. For example, in first column I sum (0.2+0.4=0.4) and updated both value position with 0.6.
I am using Java, how can I perform this? Its a simple example, in real time I have really big arrays.
This works assuming they're all the same length. Special cases are exercise to the reader.
class MatTest {
static void makeSums(float[][] floats) {
// we wouldn't be doing any operations on these inputs anyway, so return
if(floats == null || floats.length == 0 || floats.length == 1) return;
// check to make sure it's retangular
for(float[] arr : floats) {
if(arr.length != floats[0].length) {
throw new IllegalArgumentException("makeSums() requires rectangular array");
}
}
for(int i = 0; i < floats[0].length; i++) {
// do each column
float sum = 0f;
for(int j = 0; j < floats.length; j++) {
sum += floats[j][i];
}
for(int j = 0; j < floats.length; j++) {
if(floats[j][i] != 0) floats[j][i] = sum;
}
}
}
public static void main(String[] args) {
float[][] floats = new float[3][5];
floats[0] = new float[] {0.2f,0.0f,0.3f,0.0f,0.0f};
floats[1] = new float[] {0.4f,0.1f,0.0f,0.0f,0.9f};
floats[2] = new float[] {0.0f,0.0f,0.0f,0.3f,0.6f};
makeSums(floats);
for(int i = 0; i < floats.length; i++) {
for(int j = 0; j < floats[0].length; j++) {
System.out.print(floats[i][j]);
System.out.print(" ");
}
System.out.println(" ");
}
}
}
And here's its result:
C:\Documents and Settings\glow\My Documents>javac MatTest.java
C:\Documents and Settings\glow\My Documents>java MatTest
0.6 0.0 0.3 0.0 0.0
0.6 0.1 0.0 0.0 1.5
0.0 0.0 0.0 0.3 1.5
Let's call your input array float[][] a and parallel output array b initialized to all zeroes.
float curSum = 0.0;
first = true;
for(int i = 0; i < a[0].length; i++)
{
for(int j = 0; j < a.length; j++)
{
if(a[i][j] != 0)
{
if (first)
{
for(int k = j; k < a.length; k++)
curSum += a[i][k];
first = false;
}
b[i][j] = curSum;
}
}
curSum = 0.0;
first = true;
}
There might be some finer points you have to change, such as comparison of the floats and stuff, but i think the idea is all there
I think it runs in O(n*m), andwhich doesnt seem great, but I tried to keep the iterations as short as possible. I dont see any faster way to do it. Even tho there are three for loops, the one with k will only run once for every j loop so asymptotically it doesnt increase complexity at all.
Related
I am trying to print the minimum number of coins to make the change, if not possible print -1
In this code variable int[] c (coins array) has denominations I can use to come up with Total sum.
int total has total sum I need to come up with using coins (Unlimited supply)
public static int mincoinDP(int[] c, int total) {
int[][] a = new int[c.length + 1][total + 1];
for (int i = 0; i <= c.length; i++) {
a[i][0] = 0;
}
for (int j = 1; j <= total; j++) {
a[0][j] = Integer.MAX_VALUE - total;
}
for (int i = 1; i <= c.length; i++) {
for (int j = 1; j <= total; j++) {
if (c[i - 1] > j) {
a[i][j] = Integer.MAX_VALUE - total;
} else {
a[i][j] = Math.min(a[i - 1][j], 1 + a[i][j - c[i - 1]]);
}
}
}
return a[c.length][total];
}
For Sum : 4759 and Array: {31 90 8 36} Correct output is: 59
My output is: 60
What is wrong in code ?
Below is my recursive solution, trying to apply same logic in DP solution. Something seems to be wrong in logic here as well. For same input it prints -2147483595
public static void main(String[] args) {
int[] array = new int[] {31, 90, 8, 36};
System.out.println(mincoin(array, 4759, 0));
}
public static int mincoin(int[] c, int total, int i) {
if (total == 0) return 0;
if (i >= c.length) return Integer.MAX_VALUE;
int x = Integer.MAX_VALUE, y = Integer.MAX_VALUE;
if (total - c[i] >= 0) {
x = 1 + mincoin(c, total - c[i], i);
}
y = mincoin(c, total, i + 1);
return Math.min(x, y);
}
Edit: Problems in code were:
DP version: if (c[i -1] > j) , It is case when solution is not
possible choosing this coin: Here we should accept solution without
this coin which is a[i-1][j]
Recursive version: if(i >= c.length),
it is terminating condition when we dont any coin at this position,
here we should return infinity (Integer.MAX_VALUE) and
to avoid integer overflow return Integer.MAX_VALUE - total.
Though I dont like this version of infinity, but dont see any nice way other than this here.
It looks like you're using dynamic programming, with a[i][j] intended to represent the minimum number of coins (using the first i denominations) that sum to j. But I think your recurrence relations are off. They should be:
a[0][j] = 0 if j==0, otherwise infinity
a[i][j] = a[i-1][j] if c[i-1] > j
a[i][j] = min(a[i-1][j], 1 + a[i][j-c[i-1]]) if c[i-1] <= j
The main mistake is the if c[i-1] > j case in your code. You set the value to infinity (or your variant of infinity), but you should just copy the minimum number of coins from the previous row since you may be able to construct the total using the smaller number of coins.
By the way, there is a neater way to write this code. In pseudocode:
a = new int[total+1]
for int j = 1 to total+1 {
a[j] = infinity
}
for int coin in coins {
for j = coin to total+1 {
a[j] = min(a[j], a[j-coin]+1)
}
}
It's essentially the same algorithm, but it uses a smaller one-dimensional array which it modifies in-place.
Just in case someone looking for solution
public int coinChange(int[] coins, int amount) {
int dp[][] = new int[coins.length+1][amount+1];
Arrays.sort(coins);
// First column of every row
for (int i = 0; i < coins.length; ++i) {
dp[i][0] = 0;
}
/*
Setting this so that this is default max value. We always
want our dp[i][j] better than this
*/
for (int j = 0; j <= amount; ++j) {
dp[0][j] = amount+1;
}
for (int i = 1; i <= coins.length; ++i) {
for (int j = 1; j <= amount; ++j) {
if (coins[i-1] > j) {
dp[i][j] = dp[i-1][j]; // Take the already best value in above row
} else {
dp[i][j] = Math.min(dp[i-1][j], 1 + dp[i][j-coins[i-1]]); // Take the best of above row and using current coin
}
}
}
if (dp[coins.length][amount] > amount) { // it means we cannot find any coin
return -1;
} else {
return dp[coins.length][amount];
}
}
Given a set of non-negative integers, and a value sum, determine if there is a subset of the given set with sum equal to given sum.
For example:
set = {1,2,5,7}
sum = 8
=> true
I actually solved the problem with this code:
public boolean isSubsetSum(int[] set, int sum) {
Arrays.sort(set);
boolean[][] memo = new boolean[set.length+1][sum+1];
for (int i = 0; i < memo.length; i++) {
memo[i][0] = true;
}
for (int i = 1; i < memo.length; i++) {
for (int j = 1; j < memo[i].length; j++) {
if (set[i-1] > j) {
memo[i][j] = memo[i-1][j];
} else {
memo[i][j] = memo[i-1][j] || memo[i-1][j-set[i-1]];
}
}
}
return memo[memo.length-1][memo[memo.length-1].length-1];
}
However, now I want to reconstruct all the possible combinations that form the given sum.
Is it possible to do that from my memoization matrix or do I have to do it differently?
Make a new DP table called take[i][j] which is boolean. It is true if you take the i-th element for subset sum j. You fill it concurrently with your normal memo table:
for (int i = 1; i < memo.length; i++) {
for (int j = 1; j < memo[i].length; j++) {
if (memo[i-1][j]){
//no need to take ith elements, first i-1 have sum j
take[i][j] = false;
memo[i][j] = true;
}
else if (j-set[i-1] >= 0 && memo[i-1][j-set[i-1]]){
//take ith element, and search for set of size j-set[i-1] in 1..i-1
take[i][j] = true;
memo[i][j] = true;
}
else{
//neither memo[i-1][j] or memo[i-1][j-set[i-1]] valid, so no way to make sum
take[i][j]=false;
memo[i][j]=false;
}
}
}
Finally, to reconstruct a solution, you start with:
int i =set.length
int j = sum
while (i>=0 && j>=0){
if (take[i][j]){
print(set[i])
j = j - set[i]
i=i-1
}
else{
i=i-1
}
}
You can generalize this for all sets of solutions.
I have this method where I find the distances with an Euclidean algorithm and save the values as double in an array of doubles. Now I need to find the minimum value of each test and return the value indexed.
public static double distance() {
for (int i = 0; i < GetFile.testMatrix.length;) {
double[] distances = new double[4000];
double minDistance = 999999;
for (int j = 0; j < GetFile.trainingMatrix.length; j++) {
distances[j] = EuclideanDistance.findED(GetFile.trainingMatrix[j], GetFile.testMatrix[i]);
}
return minDistance;
}
return 0;
}
I would appreciate any help. Thanks in advance
It doesn't look as though you need to store the result in an array at all, since that's being discarded. You should consider tracking the result in minDistance every time you get a result from findED.
This also looks like the kind of thing that would be a lot easier to understand if you used java's streams, if you're using a version of java that has access to them.
There are several ways to do so.
One way would be iterating over the values and taking always the smallest:
double minDistance = distances[0];
for(int j =1 ;j < GetFile.trainingMatrix.length; j++){
if(distances[j]<minDistance)
minDistance=distances[j];
}
or alternatively
double minDistance = distances[0];
for(int j =1 ;j < GetFile.trainingMatrix.length; j++){
minDistance = Math.min(minDistance, distances[j];
}
or using streams (with distances as List):
double minDistance = distances.stream().mapToDouble(e -> e).min().getAsDouble();
or even nicer (with your for-loop completely implemented):
double minDistance = Stream.iterate(0,j -> j+1)
.limit(GetFile.trainingMatrix.length)
.mapToDouble(j->EuclideanDistance.findED(GetFile.trainingMatrix[j], GetFile.testMatrix[i]))
.min().orElse(-1);
Another way along with your code:
public static double distance() {
for (int i = 0; i < GetFile.testMatrix.length;) {
double[] distances = new double[4000];
for (int j = 0; j < GetFile.trainingMatrix.length; j++) {
distances[j] = EuclideanDistance.findED(GetFile.trainingMatrix[j], GetFile.testMatrix[i]);
}
return getMinDistance(distances);
}
return 0;
}
static double getMinDistance(double[] distances) {
double minDistance = Double.MAX_VALUE;
for (double distance : distances) {
minDistance = Math.min(distance, minDistance);
}
return minDistance;
}
Assign the minDistance to distances[0] unless you are very sure about the maximum value that distances array will contain.
public static double distance() {
for (int i = 0; i < GetFile.testMatrix.length;) {
double[] distances = new double[4000];
double minDistance;
for (int j = 0; j < GetFile.trainingMatrix.length; j++) {
distances[j] = EuclideanDistance.findED(GetFile.trainingMatrix[j], GetFile.testMatrix[i]);
}
minDistance = distances[0];
for(int i = 1 ; i < distances.length; i++) {
if(minDistance > distances[i]) {
minDistance = distances[i];
}
}
return minDistance;
}
This is a easy question. a link
I just tried the simple insertionSorting-like method to solve it, however it failed.
public class Solution {
public void moveZeroes(int[] nums) {
for(int i = 0; i < nums.length; i++)
if(nums[i] == 0){
for(int j = i; j<nums.length-1; j++)
nums[j] = nums[j+1];
nums[nums.length-1] = 0;
}
}
}
Could anyone help me to debug my method?
So i went through your code and re-wrote it to work. If you're moving zeroes to the end this should work perfectly fine for you. Cheers.
What this code does is iterates over your array until it hits a zero. Upon hitting a zero it loops, moving the 0 one place to the right over and over, switching spots with the value to the right of it, until the 0 is moved to the end of the array.
example: 5-loop cycle
[0,1,0,2,3] > [1,0,0,2,3] > [1,0,0,2,3] > [1,0,2,0,3] > [1,0,2,3,0]
int[] array = new int[] {0,1,0,12,3};
for (int x = 0; x < array.length; x++) {
if (array[x] == 0) {
for (int y = x; y < array.length; y++) {
if (y != array.length-1) {
// Store our replacement as temp
int temp = array[y+1];
// Move 0 to the right +1
array[y+1] = array[y];
// Set current position to what used to be right+1
array[y] = temp;
}
}
}
}
I'll share the javascript solution for the Move Zeroes problem from leetcode. It has O(n) time complexity.
Optimized for many zeroes
const snowball1 = nums => {
let i = 0;
let j = 0;
while (i<nums.length) {
if(nums[i] != 0) {
nums[j] = nums[i];
j++;
}
i++;
}
console.log(j);
nums.fill(0, j);
return nums;
}
Optimized for fewer zeroes
const snowball2 = nums => {
for(let i = nums.length; i--;){
if(nums[i]===0){
nums.splice(i,1)
nums.push(0);
}
}
return nums
}
Example
console.log(snowball1([0,0,1,0,0,3,0,12,0]));
console.log(snowball2([0,1,0,3,12]));
I'll try to write a very intuitive and easy approach to this problem. This problem can be solved using 2 indexes, one of which is the read pointer(rp) and the other is the write pointer(wp).
If rp reads a value of 0, it sets the wp to this index. The rp then keeps incrementing until it finds a non-zero value. If it does it overwrites the value at wp and this process fills the non-zero values in the beginning.
We then just need to fill the remaining spots with zeros till the end. Here's a short solution in python:
class Solution:
def moveZeroes(self, nums: List[int]) -> None:
wp=rp=0
while(rp<len(nums)):
if(nums[rp]!=0):
nums[wp]=nums[rp]
wp+=1
rp+=1
for i in range(wp,len(nums)):
nums[i]=0
Please find the optimal solution wrt space O(N) and time O(1) below
public void moveZeroes(int[] nums) {
// [0,1,0,3,12]
int j = 0;
for (int i = 0; i < nums.length; i++) {
if (nums[i] != 0) {
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
j++;
}
}
}
So my task is to read a file line by line and store the integers into an array. Then to add the integers in spots 1-5, 2-6, 3-7 etc. and store those into a new array.
In array 1 there is 4 more values than array 2. I need to compare these Arrays and see if array1 is 0.999 bigger than array2.
If it is indeed larger, I need to print out the LOCATION of the number in the array 1.
Right now my problem is my code is outputting that every number is larger than the corresponding number in array 2.
Code:
import java.io.*;
import java.util.Arrays;
import java.util.Scanner;
public class Asgn7
{
public static void main(String[] args) throws FileNotFoundException
{
Scanner file = new Scanner(new File("asgn7data.txt"));
double[] array = new double[file.nextInt()];
double[] newArray = new double[array.length - 4];
double tempVal = 0;
int j = 0;
int count = 0;
while(file.hasNext())
{
for(int i = 0; i < array.length ; i++)
{
array[i] = file.nextInt();
}
for(j = 0; j < array.length - 4; j++)
{
for(int k = 0; k < 5; k++)
{
newArray[j] += array[j+k] / 5;
}
}
for(int i = 2; i < array.length; i++)
{
if(array[i] > (newArray[i-2] + 0.999));
{
count++;
tempVal = count;
}
System.out.println(tempVal);
}
}
}
}
The values which should be compared are from 3-13.
Judging by the picture, you are not placing the values in the correct index in the second array, or you are not matching the correct ones.
If you want it to look exactly like in the picture, the second array should be declared:
double[] newArray = new double[array.length - 2];
And the loop to fill it should be changed to:
for(j = 2; j < array.length - 2; j++)
{
for(int k = -2; k <= 2; k++)
{
newArray[j] += array[j+k] / 5;
}
}
This will put the averages in the third, fourth, fifth... elements in newArray. And now you can compare them directly:
for(int i = 2; i < array.length - 2; i++)
{
if(array[i] > (newArray[i] + 0.999))
{
count++;
tempVal = count;
}
System.out.println(tempVal);
}
If you want to save the two unused spaces, as you originally did, rather than responding exactly to the picture, then you should calculate the values as you originally did. But remember to compare each element to the one two places before it and stop 2 places before the end.
Instead of
for(int i = 2; i < array.length; i++)
use
for(int i = 2; i < array.length - 2; i++)
To print the location, your construct with the count and tempVal is unnecessary. You just need to print i+1. Also note that you have a ; after your if. This means it's an empty if, and the block after it is always performed. Never have a ; after an if, for, while etc.
Not clear with what you are asking for in your question but without questioning what's the logic, by just looking at your code:
for(int i = 2; i < array.length; i++)
{
if(array[i] > (newArray[i-2] + 0.999));
{
count++;
tempVal = count;
}
System.out.println(tempVal);
}
}
if you relocate the system.out line as follows, I think you will get what you expect as follows:
for(int i = 2; i < array.length - 2; i++)
{
if(array[i] > (newArray[i-2] + 0.999));
{
System.out.println(tempVal);
// count++;
// tempVal = count;
}
}
}
PS: Please note that I have also changed the boundary for the loop to stop iteration on 13th member of the array, instead of 15.
Are you sure you're parsing the numbers correctly?
See Java: Reading integers from a file into an array
Why don't you print them out after parsing for verification?
btw, this will overflow the index of the 2nd array (since it is created using new double[array.length - 4]):
for(int i = 2; i < array.length; i++)
so does your code run?