How to reduce the number of loops if there is no change? - java

This code is radix sort in Java.
Now I can sort. But I want to reduce its functionality if there is no change in the
array, let it stop the loop and show the value.
Where do I have to fix it? Please guide me, thanks in advance.
public class RadixSort {
void countingSort(int inputArray[], int size, int place) {
//find largest element in input array at 'place'(unit,ten's etc)
int k = ((inputArray[0] / place) % 10);
for (int i = 1; i < size; i++) {
if (k < ((inputArray[i] / place) % 10)) {
k = ((inputArray[i] / place) % 10);
}
}
//initialize the count array of size (k+1) with all elements as 0.
int count[] = new int[k + 1];
for (int i = 0; i <= k; i++) {
count[i] = 0;
}
//Count the occurrence of each element of input array based on place value
//store the count at place value in count array.
for (int i = 0; i < size; i++) {
count[((inputArray[i] / place) % 10)]++;
}
//find cumulative(increased) sum in count array
for (int i = 1; i < (k + 1); i++) {
count[i] += count[i - 1];
}
//Store the elements from input array to output array using count array.
int outputArray[] = new int[size];
for (int j = (size - 1); j >= 0; j--) {
outputArray[count[((inputArray[j] / place) % 10)] - 1] = inputArray[j];
count[(inputArray[j] / place) % 10]--;//decrease count by one.
}
for (int i = 0; i < size; i++) {
inputArray[i] = outputArray[i];//copying output array to input array.
}
System.out.println(Arrays.toString(inputArray));
}
void radixSort(int inputArray[], int size) {
//find max element of inputArray
int max = inputArray[0];
for (int i = 1; i < size; i++) {
if (max < inputArray[i]) {
max = inputArray[i];
}
}
//find number of digits in max element
int d = 0;
while (max > 0) {
d++;
max /= 10;
}
//Use counting cort d no of times
int place = 1;//unit place
for (int i = 0; i < d; i++) {
System.out.print("iteration no = "+(i+1)+" ");
countingSort(inputArray, size, place);
place *= 10;//ten's , hundred's place etc
}
}
1

I'm going to resist typing out some code for you and instead go over the concepts since this looks like homework.
If I'm understanding you correctly, your problem boils down to: "I want to check if two arrays are equivalent and if they are, break out of a loop". Lets tackle the latter part first.
In Java, you can use the keyword"
break;
to break out of a loop.
A guide for checking if two arrays are equivalent in java can be found here:
https://www.geeksforgeeks.org/compare-two-arrays-java/

Sorry if this doesnt answer your question. Im just gonna suggest a faster way to find the digits of each element. Take the log base 10 of the element and add 1.
Like this : int digits = (int) Math.log10(i)+1;

Related

How do I remove the item with the highest value in an unsorted array?

So right now I am trying to code a function that will remove the highest value in an unsorted array.
Currently the code looks like this:
#Override
public void remove() throws QueueUnderflowException {
if (isEmpty()) {
throw new QueueUnderflowException();
} else {
int priority = 0;
for (int i = 1; i < tailIndex; i++) {
while (i > 0 && ((PriorityItem<T>) storage[i - 1]).getPriority() < priority)
storage[i] = storage[i + 1];
i = i - 1;
}
/*int max = array.get(0);
for (int i = 1; i < array.length; i++) {
if (array.get(i) > max) {
max = array.get(i);
}*/
}
tailIndex = tailIndex - 1;
}
Here I have my attempt at this:
int priority = 0;
for (int i = 1; i < tailIndex; i++) {
while (i > 0 && ((PriorityItem<T>) storage[i - 1]).getPriority() < priority)
storage[i] = storage[i + 1];
i = i - 1;
The program runs no bother but still deletes the first item in the array instead of the highest number. This code was given my my college lecturer for a different solution but unfortunately it doesn't work here.
Would this solution work with enough altercations? Or is there another solution I should try?
Thanks.
The code snippet in the question can be updated to below code, while keeping the same data structure i.e. queue and this updated code has 3 steps - finding the index of largest element, shifting the elements to overwrite the largest element and finally set the tailIndex to one less i.e. decrease the size of the queue.
#Override
public void remove() throws QueueUnderflowException {
if (isEmpty()) {
throw new QueueUnderflowException();
} else {
int priority = 0;
int largeIndex = 0;
for (int i = 0; i < tailIndex; i++) {
if (((PriorityItem<T>) storage[i]).getPriority() > priority) {
priority = ((PriorityItem<T>) storage[i]).getPriority();
largeIndex = i ;
}
}
for(int i = largeIndex; i < (tailIndex - 1) ; i++)
storage[i] = storage[i + 1];
}
tailIndex = tailIndex - 1;
}
Hope it helps.
Step 1
Find the highest index.
int[] array;
int highIndex = 0;
for (int i = 1; i < highIndex.size(); i++)
if (array[highIndex] < array[highIndex])
highIndex = i;
Step 2
Create new array with new int[array.size() - 1]
Step 3
Move all values of array into new array (except the highest one).
My hint: When its possible, then use a List. It reduces your complexity.
You can find the largest Number and it's index then copy each number to its preceding number. After that, you have two options:
Either add Length - 1 each time you iterate the array.
Or copy the previous array and don't include removed number in it.
Working Code:
import java.util.Arrays;
public class stackLargest
{
public static void main(String[] args)
{
int[] unsortedArray = {1,54,21,63,85,0,14,78,65,21,47,96,54,52};
int largestNumber = unsortedArray[0];
int removeIndex = 0;
// getting the largest number and its index
for(int i =0; i<unsortedArray.length;i++)
{
if(unsortedArray[i] > largestNumber)
{
largestNumber = unsortedArray[i];
removeIndex = i;
}
}
//removing the largest number
for(int i = removeIndex; i < unsortedArray.length -1; i++)
unsortedArray[i] = unsortedArray[i + 1];
// now you have two options either you can iterate one less than the array's size
// as we have deleted one element
// or you can copy the array to a new array and dont have to add " length - 1" when iterating through the array
// I am doing both at once, what you lke you can do
int[] removedArray = new int[unsortedArray.length-1];
for(int i =0; i<unsortedArray.length-1;i++)
{
System.out.printf(unsortedArray[i] + " ");
removedArray[i] = unsortedArray[i];
}
}
}
Note: Use List whenever possible, it will not only reduce complexity, but, comes with a very rich methods that will help you a big deal.

minimum number of coins to make change

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];
}
}

How to compare two arrays of different sizes?

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?

Find majority number in an array

This question has been asked before. However I just want to know what is wrong with my code. It passes most of the test cases but not all of them on lintcode.
Given an array of integers, the majority number is the number that occurs more than half of the size of the array. Find it.
public class Solution {
/**
* #param nums: a list of integers
* #return: find a majority number
*/
public int majorityNumber(ArrayList<Integer> nums) {
// write your code
Collections.sort(nums);
int j = 0, count = 0, out = 0, size = nums.size();
for(int i = 0; i < size; i++) {
if(nums.get(j) == nums.get(i)) {
count++;
if(count > size/2){
out = nums.get(i);
}
} else {
count = 1;
j = i;
}
}
return out;
}
}
EDIT
I changed the code to j = i & count = 1 as suggested by an answer.
For example for the input [1,1,1,2,2,2,2] the output should be 2.
My code works in this case. It doesn't work in large input cases.
I don't want another solution, as I have already found many O(n) solutions on other sites. I just want to fix my own code and know what I am doing wrong.
There's a smart solution that runs in O(n) worst case time, and no additional space:
public static int majorityNumber(List<Integer> nums) {
int candidate = 0;
int count = 0;
for (int num : nums) {
if (count == 0)
candidate = num;
if (num == candidate)
count++;
else
count--;
}
return candidate;
}
Note that it assumes the existence of a majority value, otherwise it returns an arbitrary value.
In your else block do:
...
else {
count = 1;
j = i;
}
Debug your code and print the values of i and j. I'm sure that will not be what you wanted to do.
You wanted to read each element and count it's frequency. That would be a O(n*n)(because the array is sorted O(n log(n))) solution.
ArrayList<Integer> readNums = new ArrayList();
for(int i = 0; i < a.length; ++i)
{
int currentNum = a[i];
if(list.contains(currentNum)
continue;//to check if you already processed that num
else
list.add(currentNum);
int count = 0;
for(int j = i + 1; j < a.length; ++j)
{
if(currentNum == a[j])
count ++;
}
if(count > size / 2)
reqNum = currentNum;
}
This is what you wanted to do.
A better method would be to use a space of O(n) and track the frequencies and then process the array in O(n).
HashMap<Integer, Intege> map = new HashMap();
for(int i = 0; i < a.length; ++i)
{
int currentNum = a[i];
int count = 1;
if(map.containsKey(currentNum))
{
count = map.getValue(currentNum);
map.put(currentNum, count + 1);
count ++;
}
else
{
map.put(currentNum, count);
}
if(count > size / 2)
reqNum = currentNum;
}

How do I trim the leading zeros in an array of digits without using an arraylist in java?

I have an array made that represents digits and I am trying to make a method so that if there are zeros in front of the first significant digit I want to trim them, I understand you can't re size arrays so I have created a new array, but my code doesn't seem to run correctly?
Here is my code I can't figure out what is wrong I've tried everything: (I put stars around the error** It gives an arrayoutofbounds error **)
package music;
import java.util.Random;
/**Music Array
*
* #author Ryan Klotz
* #version February 3, 2015
*/
public class Music
{
private int length; // length of the array
private int numOfDigits; // number of actual digits in the array
int[] musicArray;
/**Explicit Constructor
* #param x The length of the array
*/
public Music(int x)
{
length = x;
musicArray = new int[length];
Random rand = new Random();
numOfDigits = rand.nextInt(length);
int posOrNeg; // determines positive or negative sign
int digit;
for (int i = 0; i <= numOfDigits; i++)
{
digit = rand.nextInt(10);
posOrNeg = rand.nextInt(2);
if (posOrNeg == 0)
{
digit *= -1;
musicArray[i] = digit;
}
else
{
musicArray[i] = digit;
}
}
}
public void trimLeadingSilence(Music x)
{
while (x.musicArray[0] == 0)
{
int[] newMusicArray;
int count = 0;
**while (x.musicArray[count] == 0)**
{
count++;
}
if (count == x.numOfDigits)
{
newMusicArray = new int[1];
newMusicArray[0] = 0;
x.numOfDigits = 1;
x.musicArray = newMusicArray;
}
else
{
newMusicArray = new int[x.numOfDigits - count];
for (int i = 0; i <= x.numOfDigits - count; i++)
{
newMusicArray[i] = x.musicArray[i + count];
}
x.numOfDigits -= count;
x.musicArray = newMusicArray;
}
}
}
}
i <= x.numOfDigits - count should use < instead. But Arrays.copyOfRange is probably a better solution.
for (int i = 0; i <= numOfDigits; i++)
Should be
for (int i = 0; i < numOfDigits; i++)
Currently you are generating 1 more digit than numOfDigits is. This will not give you any exceptions in any case since randInt(length) will be in range of 0 and length - 1.
while (x.musicArray[count] == 0)
{
count++;
}
Will throw an exception if all values in array are 0.
while (count < x.musicArray.length && x.musicArray[count] == 0){
count++;
}
Will fix that for you.
for (int i = 0; i <= x.numOfDigits - count; i++)
Will also throw you ArrayIndexOutOfBoundsException so you should fix it to:
for (int i = 0; i < x.numOfDigits - count; i++)
Anyway, this is very inefficient since if you have 10 "0" values at the start you are creating 10 new arrays. Take a look at Arrays.copyOfRange method, you should be able to do the same job in less than 10 lines of code.
Inside your for loop, use i < x.numOfDigits - count (you were using <=).
That will solve the problem.

Categories