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;
}
Related
I'm trying to learn a bit Java with tutorials and currently I'm struggling with piece of code where I should find on which index is difference between arrays (if there is difference at all)
My code
Scanner scanner = new Scanner(System.in);
int[] arrOne = Arrays.stream(scanner.nextLine().split(" ")).mapToInt(Integer::parseInt).toArray();
int[] arrTwo = Arrays.stream(scanner.nextLine().split(" ")).mapToInt(Integer::parseInt).toArray();
int sumArrOne = 0;
int index = 0;
boolean diff = false;
for (int k : arrOne) {
if (Arrays.equals(arrOne, arrTwo)) {
sumArrOne += k;
} else {
for (int i : arrTwo) {
if (k != i) {
index = i;
diff = true;
break;
}
}
}
}
if (diff) {
System.out.println("Found difference at " + index + " index.");
} else {
System.out.println("Sum: " + sumArrOne);
}
So, if arrays are identical I'm sum array elements in arrOne. If they are not identical -> must show at which index they are not.
With this code when I input
1 2 3 4 5
1 2 4 3 5
I should get that difference is at index 2 instead I've got index 1.
I'm not quite sure why and would be glad if someone point me out where is my mistake.
I updated your code. Looks like you're misunderstanding the concept of indexes yet.
Use one common index to check with in both arrays, in my example it's simply called i:
import java.util.Arrays;
import java.util.Scanner;
public class BadArray {
static private final int INVALID_INDEX = Integer.MIN_VALUE;
public static void main(final String[] args) {
try (final Scanner scanner = new Scanner(System.in);) {
final int[] arrOne = Arrays.stream(scanner.nextLine().split(" ")).mapToInt(Integer::parseInt).toArray();
final int[] arrTwo = Arrays.stream(scanner.nextLine().split(" ")).mapToInt(Integer::parseInt).toArray();
int sumArrOne = 0;
int diffIndex = INVALID_INDEX;
final int minLen = Math.min(arrOne.length, arrTwo.length);
for (int i = 0; i < minLen; i++) {
sumArrOne += arrOne[i];
if (arrOne[i] != arrTwo[i]) {
diffIndex = i;
break;
}
}
if (diffIndex != INVALID_INDEX) {
System.out.println("Found difference at " + diffIndex + " index.");
} else if (arrOne.length != arrTwo.length) {
System.out.println("Arrays are equal but have different length!");
} else {
System.out.println("Sum: " + sumArrOne);
}
}
}
}
I also put the scanner into a try-resource-catch to handle resource releasing properly.
Note you could also do the array lengths comparison right at the start if different array lengths play a more crucial role.
You are trying to find out which index has the first difference so you should iterate via the index rather than using a for-each loop (aka enhanced for loop). The following method should work for this.
/**
* Returns the index of the first element of the two arrays that are not the same.
* Returns -1 if both arrays have the same values in the same order.
* #param left an int[]
* #param right an int[]
* #return index of difference or -1 if none
*/
public int findIndexOfDifference(int[] left, int[] right) {
// short-circuit if we're comparing an array against itself
if (left == right) return -1;
for (int index = 0 ; index < left.length && index < right.length ; ++index) {
if (left[index] != right[index]) {
return index;
}
}
return -1;
}
In your code you compare, where the indexes are different, not the values at the indexes. Also your code has several other issues. I'll try to go through them step by step:
// compare the whole array only once, not inside a loop:
diff = !Arrays.equals(arrOne, arrTwo));
if (!diff) {
// do the summing without a loop
sumArrOne = Arrays.stream(arrOne).sum();
} else {
// find the difference
// it could be the length
index = Math.min(arrOne.length, arrTwo.length);
// or in some different values
for (int i = 0; i < index; i++) { // do a loop with counter
if (arrOne[i] != arrTwo[i]) {
index = i;
break;
}
}
}
It doesn't matter that I set index here above the loop as it's value will be overwritten anyways inside the loop, if relevant.
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.
The longest increasing subsequence is the well known problem and I have a solution with the patience algorithm.
Problem is, my solution gives me the "Best longest increasing sequence" instead of the First longest increasing sequence that appears.
The difference is that some of the members of the sequence are larger numbers in the first(but the sequence length is exactly the same).
Getting the first sequence is turning out to be quite harder than expected, because having the best sequence doesn't easily translate into having the first sequence.
I've thought of doing my algorithm then finding the first sequence of length N, but not sure how to.
So, how would you find the First longest increasing subsequence from a sequence of random integers?
My code snippet:
public static void main (String[] args) throws java.lang.Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int inputInt;
int[] intArr;
try {
String input = br.readLine().trim();
inputInt = Integer.parseInt(input);
String inputArr = br.readLine().trim();
intArr = Arrays.stream(inputArr.split(" ")).mapToInt(Integer::parseInt).toArray();
} catch (NumberFormatException e) {
System.out.println("Could not parse integers.");
return;
}
if(inputInt != intArr.length) {
System.out.println("Invalid number of arguments.");
return;
}
ArrayList<ArrayList<Integer>> sequences = new ArrayList<ArrayList<Integer>>();
int sequenceCount = 1;
sequences.add(new ArrayList<Integer>());
sequences.get(0).add(0);
for(int i = 1; i < intArr.length; i++) {
for(int j = 0; j < sequenceCount; j++) {
if(intArr[i] <= intArr[sequences.get(j).get(sequences.get(j).size() - 1)]) {
sequences.get(j).remove(sequences.get(j).size() - 1);
sequences.get(j).add(i);
break;
} else if (j + 1 == sequenceCount) {
sequences.add(new ArrayList<Integer>(sequences.get(j)));
sequences.get(j + 1).add(i);
sequenceCount++;
break; //increasing sequenceCount causes infinite loop
} else if(intArr[i] < intArr[sequences.get(j + 1).get(sequences.get(j + 1).size() - 1)]) {
sequences.set(j+ 1, new ArrayList<Integer>(sequences.get(j)));
sequences.get(j+ 1).add(i);
break;
}
}
}
int bestSequenceLength = sequenceCount;
ArrayList<Integer> bestIndexes = new ArrayList<Integer>(sequences.get(bestSequenceLength - 1));
//build bestSequence, then after it I'm supposed to find the first one instead
int[] bestSequence = Arrays.stream(bestIndexes.toArray()).mapToInt(x -> intArr[(int) x]).toArray();
StringBuilder output = new StringBuilder("");
for(Integer x : bestSequence) {
output.append(x + " ");
}
System.out.println(output.toString().trim());
}
I'm storing indexes instead in preparation for having to access the original array again. Since it's easier to go from indexes to values than vice versa.
Example:
3 6 1 2 8
My code returns: 1 2 8
First sequence is: 3 6 8
Another Example:
1 5 2 3
My code correctly returns: 1 2 3
Basically, my code works as long as the first longest sequence is the same as the best longest sequence. But when you have a bunch of longest sequences of the same length, it grabs the best one not the first one.
Code is self-explanatory. (Have added comments, let me know if you need something extra).
public class Solution {
public static void main(String[] args) {
int[] arr = {3,6,1,2,8};
System.out.println(solve(arr).toString());
}
private static List<Integer> solve(int[] arr){
int[][] data = new int[arr.length][2];
int max_length = 0;
// first location for previous element index (for backtracing to print list) and second for longest series length for the element
for(int i=0;i<arr.length;++i){
data[i][0] = -1; //none should point to anything at first
data[i][1] = 1;
for(int j=i-1;j>=0;--j){
if(arr[i] > arr[j]){
if(data[i][1] <= data[j][1] + 1){ // <= instead of < because we are aiming for the first longest sequence
data[i][1] = data[j][1] + 1;
data[i][0] = j;
}
}
}
max_length = Math.max(max_length,data[i][1]);
}
List<Integer> ans = new ArrayList<>();
for(int i=0;i<arr.length;++i){
if(data[i][1] == max_length){
int curr = i;
while(curr != -1){
ans.add(arr[curr]);
curr = data[curr][0];
}
break;
}
}
Collections.reverse(ans);// since there were added in reverse order in the above while loop
return ans;
}
}
Output:
[3, 6, 8]
I need to write function that gets 3 params(int num, int k, int nDigit).
The function get number and replace the digit inside the number in k index by nDigit.
for example:
int num = 5498
int k = 2
int nDigit= 3
the result is num = 5398
My question is how can I implement it?I undastand that the best way to convert the num to string and then just replace char on specific index by nDigit char.
But is there any way to implement it?Without
public int changeDigit(int num, int k, int nDigit){
k = pow(10,k);
double saved = num%k; // Save digits after
num = num - (num%(k*10)); //Get what's before k
return ((int) (num + (nDigit*k) + saved));
}
I won't do your homework for you, but here's some hints:
Convert integer to string:
String s = Integer.toString(1234);
Enumerating a string:
for (i = 0; i < s.length; i++)
{
char c = s.charAt(i);
}
String building (a little less efficient without the StringBuilder class)
char c = '1';
String s = "3";
String j = "";
j = j + c;
j = j + s; // j is now equal to "13"
String back to integer:
int val = Integer.parseInt("42");
You can use a StringBuilder. It's easier to see what you're doing and you don't need to perform mathematics, only adjust the characters in their positions. Then convert it back to int.
public class Main {
static int swapParams(int num, int k, int nDigit) {
StringBuilder myName = new StringBuilder(Integer.toString(num));
myName.setCharAt(k-1, Integer.toString(nDigit).charAt(0));
return Integer.parseInt(myName.toString());
}
public static void main(String[] args) {
System.out.println(swapParams(5498, 2, 3));
}
}
http://ideone.com/e4MF6m
You can do it like this:
public int func(int num, int k, int nDigit) {
String number = String.valueOf(num);
return Integer.parseInt(number.substring(0, k - 1) + nDigit + number.substring(k, number.length()));
}
This function takes the first characters of the number without the k'th number and adds the nDigit to it. Then it adds the last part of the number and returns it as an integer number.
This is my javascript solution.
const solution = numbers => { //declare a variable that will hold
the array el that is not strictly ascending let flawedIndex;
//declare a boolean variable to actually check if there is a flawed array el in the given array let flawed = false;
//iterate through the given array for(let i=0; i<numbers.length; i++) {
//check if current array el is greater than the next
if(numbers[i] > numbers[i+1])
{
//check if we already set flawed to true once.
//if flawed==true, then return that this array cannot be sorted
//strictly ascending even if we swap one elements digits
if(flawed) {
return false;
}
//if flawed is false, then set it to true and store the index of the flawed array el
else {
flawed = true;
flawedIndex = i;
}
}
}
//if flawed is still false after the end of the for loop, return true //where true = the array is sctrictly ascending if(flawed ==
false) return true;
//if flawed==true, that is there is an array el that is flawed if(flawed){
//store the result of calling the swap function on the digits of the flawed array el
let swapResult = swap(flawedIndex,numbers);
//if the swapresult is true, then return that it is ascending
if (swapResult == true) return true; }
//else return that its false return false; }
const swap = (flawIndex, numbers) => {
let num = numbers[flawIndex];
//convert the given array el to a string, and split the string based on '' let numToString = num.toString().split('');
//iterate through every digit from index 0 for(let i=0;
i<numToString.length; i++) {
//iterate from every digit from index 1
for(let j=i+1; j<numToString.length; j++) {
//swap the first index digit with every other index digit
let temp = numToString[i];
numToString[i] = numToString[j]
numToString[j] = temp;
console.log(numToString)
//check if the swapped number is lesser than the next number in the main array
//AND if it is greater than the previous el in the array. if yes, return true
let swappedNum = Number(numToString.join(''));
if(swappedNum < numbers[flawIndex + 1] && swappedNum > numbers[flawIndex-])
{
return true;
}
} } //else return false return false; }
console.log("the solution is ",solution([1, 3, 900, 10]))
I am trying to add 1 to a byte array containing binary number. It works for some cases and not for others. I cannot convert my array to an integer and add one to it. I am trying to do the addition with the number in the array. If someone could please point me i where I am messing up on this!
Test cases that have worked: 1111, 0, 11
EDIT: I understand how to do it with everyone's help! I was wondering if the binary number had the least significant bit at the first position of the array.
Example: 1101 would be stored as [1,0,1,1]-how could I modify my code to account for that?
public static byte[] addOne(byte[] A)
{
//copy A into new array-size+1 in case of carry
byte[] copyA = new byte[A.length+1];
//array that returns if it is empty
byte [] copyB = new byte [1];
//copy A into new array with length+1
for(byte i =0; i <copyA.length&& i<A.length; i ++)
{
copyA[i]=A[i];
}
//if there is nothing in array: return 1;
if(copyA.length == 0)
{
//it will return 1 bc 0+1=1
copyB[0]=1;
return copyB;
}
//if first slot in array is 1(copyA) when you hit zero you dont have to carry anything. Go until you see zero
if(copyA[0] ==1 )
{
//loops through the copyA array to check if the position 0 is 1 or 0
for(byte i =0; i<copyA.length; i ++)
{
if(copyA[i] == 0)//if it hits 0
{
copyA[i]=1;//change to one
break;//break out of for loop
}
else{
copyA[i]=0;
}
}
return copyA;
}
else if (copyA[0]==0)
{
copyA[0]=1;
}
return copyA;
}
The idea:
100010001 + 1000000 + 1111111 +
1 = 1 = 1 =
--------- ------- -------
100010010 1000001 (1)0000000
I designed the operation as you can do on paper.
As for decimal operation adding a number is done starting from right (less significant digit) to left (most significant digit).
Note that 0 + 1 = 1 and I finished so I can exit
Instead 1 + 1 = 10 (in binary) so I write 0 (at the rightest position) and I have a remainder of 1 to add to next digit. So I move left of one position and I redo the same operation.
I hope this is helpful to understand it
It is a simple algorithm:
Set position to the last byte.
If current byte is 0 change it to 1 and exit.
If current byte is 1 change it to 0 and move left of one position.
public static byte[] addOne(byte[] A) {
int lastPosition = A.length - 1;
// Looping from right to left
for (int i = lastPostion; i >= 0; i--) {
if (A[i] == 0) {
A[i] = 1; // If current digit is 0 I change it to 1
return A; // I can exit because I have no reminder
}
A[i] = 0; // If current digit is 1 I change it to 0
// and go to the next position (one position left)
}
return A; // I return the modified array
}
If the starting array is [1,0,1,1,1,1,1,0,0] the resulting array will be [1,0,1,1,1,1,1,0,1].
If the starting array is [1,0,1,1,1,1,1,1,1] the resulting array will be [1,1,0,0,0,0,0,0,0].
If the starting array is [1,1,1,1,1,1,1,1,1] the resulting array will be [0,0,0,0,0,0,0,0,0].
Note If you need to handle this last situation (overflow) in a different manner you can try one of the following:
throw an exception
enlarge the array of 1 and result [1,0,0,0,0,0,0,0,0,0]
Here is a piece of code to handle both situations:
Throwing exception:
public static byte[] addOne(byte[] A) throws Exception {
for (int i = A.length - 1; i >= 0; i--) {
if (A[i] == 0) {
A[i] = 1;
return A;
}
A[i] = 0;
if (i == 0) {
throw new Exception("Overflow");
}
}
return A;
}
Enlarging array:
public static byte[] addOne(byte[] A) {
for (int i = A.length - 1; i >= 0; i--) {
if (A[i] == 0) {
A[i] = 1;
return A;
}
A[i] = 0;
if (i == 0) {
A = new byte[A.length + 1];
Arrays.fill(A, (byte) 0); // Added cast to byte
A[0] = 1;
}
}
return A;
}
I suspect it works in some cases but not other as your code is too complicated.
static byte[] increment(byte[] bits) {
byte[] ret = new byte[bytes.length+1];
int carry = 1, i = 0;
for(byte b: bits) {
// low bit of an add;
ret[i++] = b ^ carry;
// high bit of an add.
carry &= b;
}
if (carry == 0)
return Arrays.copyOf(ret, bytes.length);
ret[i] = 1;
return ret;
}
For an array bits containing the binary numbers, the algorithm for adding 1 is:
Boolean carried = true;
for(int i = bits.length-1; i>=0; i--) {
if(bits[i] == 1 && carried) {
carried = true;
bits[i] = 0;
}
else if (bits[i] == 0 && carried) {
carried = false;
bits[i] = 1;
}
{
if(carried)
throw new Exception("Overflow");