Remove trailing zeros in the output of an integer array in java - java

In my code, I get an output of an array but it displays some unwanted zeros after getting the array, Can you explain a way to avoid getting these unwanted zeros.
static int[] cutTheSticks(int[] arr) {
int min,i,j,count=0;
int []arr2=Arrays.copyOf(arr,arr.length);
int []temp =Arrays.copyOf(arr,arr.length);
for(i=0;i<arr.length;i++){
Arrays.sort(arr2);
min= arr2[0];
for(j=0;j<arr.length;j++){
if(temp[j]>0){
count++;
}
temp[j]=temp[j]-min;
}
int []res = new int [arr.length];
while(count!=0) {
res[i] = count;
count = 0;
}
return res;
}

You can figure the "size" of res without its trailing zeros with:
int rlen = res.length;
while (res[rlen-1] == 0) {
--rlen;
}
If you wish, you can then use the calculated "effective length" rlen to reallocate the res array at the correct size:
res = Arrays.copyOf(res, rlen);
Or just use rlen instead of res.length when you need to know the "correct" size of res.

Related

Finding maximum length difference between strings of two arrays

So I've tried to used a nested loop and add the lengths to a int array and then go through the int array and find the highest number but it doesn't pass the test case and I'm starting to think that maybe I'm overcomplicating this problem and that there's a much simpler approach. Here is what I've tried.
public static int mxdiflg(String[] a1, String[] a2) {
int maxDiff=0;
int[] lengths=new int[a1.length*a2.length];
for(int i=0;i<a1.length;i++){
for(int j=0;j<a2.length;j++){
lengths[j]=Math.abs(a1[j].length()-a2[i].length());
}
}
for(int i=0;i<lengths.length;i++){
if(lengths[i]>maxDiff){
maxDiff=lengths[i];
}
}
return maxDiff;
}
You can do it like so with two independent loops.
String[] a1 = { "ab", "cdefghik", "lsls" };
String[] a2 = { "a", "cdefghik", "lsls", "abcdefghijkl" };
int max = mxdiflg(a1, a2);
System.out.println(max);
prints
11
initialize the minvals to largest int value and the maxvals to 0.
each loop finds the min and max of the strings using Math.min and Math.max.
once done, find the maximum of the two max values and the minimum of the two min values.
the subtract the minimum from the maximum and you have the result.
public static int mxdiflg(String[] a1, String[] a2) {
int maxa1 = 0, mina1 = Integer.MAX_VALUE, maxa2 = 0,
mina2 = Integer.MAX_VALUE;
// find max and
for (String s : a1) {
int len = s.length();
maxa1 = Math.max(maxa1, len);
mina1 = Math.min(mina1, len);
}
for (String s : a2) {
int len = s.length();
maxa2 = Math.max(maxa2, len);
mina2 = Math.min(mina2, len);
}
return Math.max(maxa1, maxa2) - Math.min(mina1, mina2);
}
Note: Due to the peculiarities of various character encodings, String.length does accurately count the characters. As stated in the documentation.
Returns the length of this string. The length is equal to the number of Unicode code units in the string.
As some characters use encoding schemes of more than 8 bits, their reported length would greater than 1.
If this is important, the s.length could be replaced with (int)s.codePoints().count() to handle these encodings.
Assuming Java 8+ and a reasonable number of strings in each array, I'd suggest using the following to avoid the nested loop:
int a1max = Arrays.stream(a1).mapToInt(String::length).max().orElse(0);
int a1min = Arrays.stream(a1).mapToInt(String::length).min().orElse(0);
int a2max = Arrays.stream(a2).mapToInt(String::length).max().orElse(0);
int a2min = Arrays.stream(a2).mapToInt(String::length).min().orElse(0);
int maxDiff = Math.max(Math.abs(a2max-a1min), Math.abs(a1max-a2min));

Random array with size, min and max value with short

I'm doing a task where you input 3 parameters which are size, minimum value and maximum value. It then is meant to return a random number between the minimum and maximum value of the size inputted. There are also other validations such as if the min is more than the max which I've already done.
I am able to do the task using integer instead of short. As soon as I change the data type a bunch of errors come.
Below is what I've done so far, it works as expected but I am pretty sure that there is not meant to be a bottom return null, I get errors when I delete it. On the second loop, it should return the array instead of doing a system print line. The other issue is the data types at the top, it should be short maxVal and short minVal instead of int but I can't get it to work with short.
I would very much appreciate all help. Thanks!
public static ArrayList<Short> RandomArray1(int n, int maxVal, int minVal){
if(n <= 0) {
return null;
}
if(minVal > maxVal) {
return new ArrayList<Short>();
}
ArrayList<Integer> ran = new ArrayList<Integer>();
Random rand = new Random();
for(int i = 0; i < n; i++) {
int result = rand.nextInt(maxVal-minVal) + minVal;
//System.out.println(result);
ran.add(result);
}
for (int i = 0; i < ran.size(); i++) {
System.out.println(ran.get(i));
//return (ArrayList<Short>)ran.get(i);
}
return null;
I would do it like this.
first, method names by convention should start with lower case letters.
Use the method to generate the values and return the list
return interface types as opposed to implementation types (e.g. List)
throw exceptions if the arguments don't satisfy the requirements.
Note, having to cast the arguments to shorts is cumbersome but it prevents errors at compile time. Otherwise you may want to throw an additional run time exception if the values aren't within Short.MIN_VALUE and Short.MAX_VALUE.
public class RandomShorts {
public static void main(String[] args) {
List<Short> shortList = randomList(20, (short)200, (short)99);
shortList.forEach(System.out::println);
}
public static List<Short> randomList(short n, short maxVal,
short minVal) {
if (n <= 0 || minVal >= maxVal) {
throw new IllegalArgumentException(
"\nn must be > 0\nminVal must be < maxVal\n");
}
List<Short> ran = new ArrayList<>();
Random rand = new Random();
for (int i = 0; i < n; i++) {
short result =
(short) (rand.nextInt(maxVal - minVal) + minVal);
ran.add(result);
}
return ran;
}
}
If you just want to return a single random number using the supplied arguments, they you can do it like this.
public static short randomShort(int n, short maxVal, short minVal) {
return (short)((Math.random()*(maxVal - minVal))+minVal);
}
For adding the short to random list since there is not Random.nextShort(), you'll have to substitute the line
int result = rand.nextInt(maxVal-minVal) + minVal;
for
short result = (short) (rand.nextInt(maxVal-minVal) + minVal);
Where then you can add to your ran array instead of the second for loop returning the ArrayList as a short
public static short[] generateRandomShortArray (int sampleSize, short min, short max) {
short[] result = new short[sampleSize];
for (int index = 0; index < result.length; index++) {
result[index] = (short)((Math.random() * (max-min)) + min);
}
return result;
}
If an array list is required just return Arrays.asList(result);

Calculate BIg-O for 3 random permutation algorithms

I am trying to calculate the Big-O time complexity for these 3 algorithms, but seems like I have a lack of knowledge on this topic.
1st:
private void firstAlgorithm(int size) {
int[] array = new int[size];
int i=0; int flag=0;
while(i<size) {
int num=(int)(Math.random()*(size));
if (num==0 && flag==0) {
flag=1;
array[i]=0;
i++;
} else if(num==0 && flag==1) {
continue;
} else if(!checkVal(num, array)) {
array[i]=num;
i++;
}
}
}
private static boolean checkVal(int val, int[] arr) {
int i = 0;
for (int num:arr) {
if (num==val) {
return true;
}
}
return false;
}
2nd:
private void secondAlgorithm(int size) {
int i = 0;
int[] array = new int[size];
boolean[] booleanArray = new boolean[size];
while (i < array.length) {
int num = (int) (Math.random() * array.length);
if (!booleanArray[num]) {
booleanArray[num] = true;
array[i] = num;
i++;
}
}
}
3rd:
private void thirdAlgorithm(int size) {
int[] array = new int[size];
for (int i = 0; i < array.length; i++) {
int num = (int) (Math.random() * (i - 1));
if (i > 0) {
array = swap(array, i, num);
}
}
}
private static int[] swap(int[] arr, int a, int b) {
int i = arr[a];
arr[a] = arr[b];
arr[b] = i;
return arr;
}
Would be nice, if you could explain your results.
In my opinion, 1st - O(n^2) because of two loops, 2nd don't know, 3rd O(n)
THank you
I assume that in all your algorithms, where you are generating a random number, you meant to take the remainder of the generated number, not multiplying it with another value (example for the first algorithm: Math.random() % size). If this is not the case, then any of the above algorithms have a small chance of not finishing in a reasonable amount of time.
The first algorithm generates and fills an array of size integers. The rule is that the array must contain only one value of 0 and only distinct values. Checking if the array already contains a newly generated value is done in O(m) where m is the number of elements already inserted in the array. You might do this check for each of the size elements which are to be inserted and m can get as large as size, so an upper bound of the running-time is O(size^2).
The second algorithm also generates and fills an array with random numbers, but this time the numbers need not be distinct, so no need to run an additional O(m) check each iteration. The overall complexity is given by the size of the array: O(size).
The third algorithm generates and fills an array with random numbers and at each iteration it swaps some elements based on the given index, which is a constant time operation. Also, reassigning the reference of the array to itself is a constant time operation (O(1)). It results that the running-time is bounded by O(size).

Adding Numbers and printing the sum vertically using arrays

I have to create a program which adds two integers and prints the sum vertically.
For example, I have.
a=323, b=322.
The output should be:
6
4
5
I've created the code for when the integers are up to two digits, but I want it to work for at least three digits.
Below is the best I could think of.
It may be completely wrong, but the only problem I'm facing is the declaration of array.
It says that the array might not be initialized.
If I set it to null then also it won't assign values to it later.
I know maybe I'm making a big mistake here, but I'll really appreciate if anyone could help me out.
Please keep in mind that I must not use any other functions for this code.
Hope I'm clear.
public class Vert
{
public static void main(String args[])
{
int n,i=0,j,a=323,b=322;
int s[];
n=a+b;
while(n>9)
{
s[i]=n%10;
i++;
s[i]=n/10;
if(s[i]>9)
{
n=s[i];
}
}
j=i;
for(j=i;j>=0;j--)
{
System.out.println(+s[j]);
}
}
}
String conversion seems like cheating, so here's a Stack.
int a = 323, b = 322;
java.util.Stack<Integer> stack = new java.util.Stack<>();
int n = a + b;
while (n > 0) {
stack.push(n % 10);
n = n / 10;
}
while (!stack.isEmpty())
System.out.println(stack.pop());
If an array is required, you need two passes over the sum
int a = 323, b = 322;
// Get the size of the array
int n = a + b;
int size = 0;
while (n > 0) {
size++;
n = n / 10;
}
// Build the output
int s[] = new int[size];
n = a + b;
for (int i = size - 1; n > 0; i--) {
s[i] = n % 10;
n = n / 10;
}
// Print
for (int x : s) {
System.out.println(x);
}
To initialize an array, you need to specify the size of your array as next:
int s[] = new int[mySize];
If you don't know the size of your array, you should consider using a List of Integer instead as next:
List<Integer> s = new ArrayList<Integer>();
Here is how it could be done:
// Convert the sum into a String
String result = String.valueOf(a + b);
for (int i=0; i <result.length();i++) {
// Print one character corresponding to a digit here per line
System.out.println(result.charAt(i));
}
I'd do it like this:
int a = 322;
int b = 322;
int sum = a + b;
String s = Integer.toString(sum);
for(int i = 0; i < s.length(); i++) {
System.out.println(s.charAt(i));
}
But your problem looks like an array is required.
The steps are same as in my solution:
Use int values
Sum the int values (operation)
Convert the int value in an array/string
Output the array/string

Remove Leading Zeros

I am trying to figure out how to remove leading zeros from an array. The array is currently stored with the least significant bit at the first position.
Example: if number is 1101 it is stored in my array as: [1,1,0,1]. I do not want to flip the array or change it in anyway except remove the leading zeros. I have the bolded the leading zero that needs to be removed.
I am trying to just do this with just using the array and not converting it
Ex: current output : 0 1 1 0
Expected output: 0 1 1
public static byte[] normal(byte[] arr)
{
//check if all the numbers are 0 and last is 1
byte [] output = new byte[copy.length];
for(int i = arr.length;i<=0;i--)
{
if(arr[i]==1){
output[i]=copy[i];
}
}
return output;
}
Your problem is that the output array is the same size as the input array... the 0s that you skip are still going to be there because 0 is the default value of any item in an int[].
So, I would start at the end of your input array, and not actually initialize the output array until you hit the first 1. Then you know how big to make the output array.
public static byte[] normal(byte[] arr) {
byte[] output = null;
System.out.println(arr.length);
for (int i = arr.length-1; i >= 0; i--) {
if (arr[i] != 0) {
if (output == null) {
output = new byte[i+1];
}
output[i] = arr[i];
}
}
if (output == null) { // cover case where input is all 0s
output = new byte[0];
}
return output;
}
Your output array is too long. First you should count how many leading zeroes you have, and create an output array shorter than arr but that many elements:
public static byte[] normal(byte[] arr)
{
// Count the leading zeros:
int zeroes = 0;
while (arr[zeroes] == 0) {
++zeroes;
}
//check if all the numbers are 0 and last is 1
byte[] output = new byte[arr.length - zeroes];
for(int i = output.length - 1; i >= 0; ++i) {
output[i] = arr[i - zeroes];
}
return output;
}
Or better yet, use the built-in Arrays.copyOfRange:
public static byte[] normal(byte[] arr)
{
// Count the leading zeros:
int zeroes = 0;
while (arr[zeroes] == 0) {
++zeroes;
}
//check if all the numbers are 0 and last is 1
return Arrays.copyOfRange(zeroes, arr.length);
}
Iterate backwards over the array and find the index of the last occuring 1 (or you reach the front of the array). Then copy the array up to and including that index. Because you know the index of the final array, you know how large the returned array will have to be (size lastIndex + 1)
It's been a while since I've written java code, so this might not compile or run properly. But the code for this might look like this:
public static byte[] normal(byte[] arr)
{
//null check arr if desired
int indexOfLastNonZero = arr.length - 1;
boolean foundOne = false;
while(!foundOne && indexOfLastNonZero >= 0)
{
if (arr[indexOfLastNonZero] == (byte) 1)
foundOne = true;
else
indexOfLastNonZero -= 1;
}
if (foundOne)
{
byte[] output = new byte[indexOfLastNonZero + 1];
System.arraycopy( arr, 0, output, 0, output.length );
return output;
}
else
{
return null; //or size 0 array if you prefer
}
}
I suggest to count the number of continuous zeros from the last and then generate the output array which will be of the count size lesser than that the original size...
public static byte[] normal(byte[] arr)
{
int count = 0;
for(int i = arr.length-1;i>=0;i--)
{
if(arr[i]==1){
break;
}
count++;
}
byte [] output = new byte[copy.length-count];
for(int i = 0;i<(copy.length-count);i++) {
output[i] = copy[i];
}
return output;
}

Categories