How to get a sequence of 5 numbers from an array - java

I want to get a sequence of 5 numbers from an array.
For example :
int arr1[] = {3,88,99,5,4,6,22,32,7,45}; // array where there is the sequence 3,4,5,6,7
Vector<Integer> myVec = new Vector<Integer>(); // vector wehre to save the sequence
Now what do I have to do to get the sequence from that array?
I have a code here but it does not work properly:
for(int i = 0; i < arr1.length -1; i++) {
int a = arr1[i];
int b = arr1[i+1];
int c = b - a;
if(c == 1) {
myvec.add(arr1[i]);
}
}
How should I change my code to solve this?

This program will print all the sequence in the array WITHOUT SORTING THE ARRAY. You could select the list with size.. Say if you want match 5 sequence get the list with size 5. Hope this help. (Modify as per your need.)
import java.util.ArrayList;
import java.util.List;
public class Sequence {
private static int arr1[] = { 3, 88, 99, 5, 4, 6, 22, 32, 7, 45 };
private static int findNextInSequence(int start) {
int next = -1;
for(int i = 0; i < arr1.length; i++){
if((start - arr1[i]) == -1){
next = arr1[i];
}
}
return next;
}
public static void main(String[] args) {
for (int i = 0; i < arr1.length; i++) {
List<Integer> sequence = new ArrayList<Integer>();
int nextSequence = arr1[i];
do{
sequence.add(nextSequence);
nextSequence = findNextInSequence(nextSequence);
} while(nextSequence != -1);
System.out.println(sequence);
}
}
}

Your code checks the difference between two successive values from arr1 array. Because it is not sorted, it works like this:
88-3 !=1 (value not added)
99-88 !=1 (value not added)
5-99 !=1 (value not added)
...
45-7 !=1 (value not added).
You have to ensure that values in your array are sorted first. Use Arrays.sort() and apply the method on sorted array. This should add values: 3,4,5,6, but it WON'T add 7 (because it'll be your arr[i+1] value at the time of loop execution.
4-3 ==1 (value added)
5-4 ==1 (value added)
6-5 ==1 (value added)
7-6 ==1 (value added, but it is only number 6 that is added!)

You should count successive count upto 5 and put the result into ArrayList instead of Vector. Because, ArrayList is more efficient than Vector. Try,
int arr1[] = {3, 88, 99, 5, 4, 6, 22, 32, 7, 45, 11, 12, 13, 14, 15};
List<Integer> myVec = new ArrayList<>();
Arrays.sort(arr1);
int count = 0;
int lastValue = 0;
for (int i = 0; i < arr1.length - 1; i++) {
if (arr1[i + 1] - arr1[i] == 1) {
count++;
System.out.println(arr1[i]);
lastValue = arr1[i + 1];
} else {
System.out.println(count);
if (count >= 4) {
for (int j = 0; j <= count; j++) {
myVec.add(lastValue - 4 + j);
}
}
count = 0;
}
}
System.out.println(myVec);

Related

How to find numbers that appear only once in a matrix?

I have a given matrix called m and its dimensions are n by n and it contains whole numbers. I need to copy the numbers that appear just once to a new array called a.
I think the logic would be to have a for loop for each number in the matrix and compare it to every other number, but I don't know how to actually do that with code.
I can only use loops (no maps or such) and this is what I've come up with:
public static void Page111Ex14(int[][] m) {
int previous = 0, h = 0;
int[] a = new int[m.length*m[0].length];
for (int i = 0; i < m.length; i++) {
for (int j = 0; j < m[0].length; j++) {
previous = m[i][j];
if (m[i][j] != previous) {
a[h] = m[i][j];
h++;
}
}
}
It's probably not correct though.
Loop through it again to see if there's any repeated one. Assuming you can use labels, the answer might look a bit like that:
public static int[] getSingleInstanceArrayFromMatrix(int[][] m) {
int[] a = new int[m.length * m[0].length];
// Main loop.
for (int x = 0; x < m.length; x++) {
for (int y = 0; y < m[0].length; y++) {
// Gets the current number in the matrix.
int currentNumber = m[x][y];
// Boolean to check if the variable appears more than once.
boolean isSingle = true;
// Looping again through the array.
checkLoop:
for (int i = 0; i < m.length; i++) {
for (int j = 0; j < m[0].length; j++) {
// Assuring we are not talking about the same number in the same matrix position.
if (i != x || j != y) {
// If it is equal to our current number, we can update the variable and break.
if (m[i][j] == currentNumber) {
isSingle = false;
break checkLoop;
}
}
}
}
if (isSingle) {
a[(x * m.length) + y] = currentNumber;
}
}
}
return a;
}
Not sure if it's the most efficient, but I think it will work. It's somewhat hard to form your final array without the help of Lists or such. Since the unassigned values will default to 0, any actual zero (i.e. it's "supposed" to be there based on the matrix) will be undetected if you look up the returned array. But if there's such limitations I imagine that it's not crucially important.
This is one of those problems you can just throw a HashMap at and it just does your job for you. You traverse the 2d array, use a HashMap to store each element with its occurence, then traverse the HashMap and add all elements with occurence 1 to a list. Then convert this list to an array, which is what you're required to return.
This has O(n*n) complexity, where n is one dimension of the square matrix m.
import java.util.*;
import java.io.*;
class GetSingleOccurence
{
static int[] singleOccurence(int[][] m)
{
// work with a list so that we can append to it
List<Integer> aList = new ArrayList<Integer>();
HashMap<Integer, Integer> hm = new HashMap<>();
for (int row = 0; row < m.length; row++) {
for (int col = 0; col < m[row].length; col++) {
if (hm.containsKey(m[row][col]))
hm.put(m[row][col], 1 + hm.get(m[row][col]));
else
hm.put(m[row][col], 1);
}
}
for (Map.Entry entry : hm.entrySet())
{
if (Integer.parseInt(String.valueOf(entry.getValue())) == 1)
a.add(Integer.parseInt(String.valueOf(entry.getKey())));
}
// return a as an array
return a.toArray(new int[a.size()]);
}
public static void main(String args[])
{
// A 2D may of integers with some duplicates
int[][] m = { { 1, 2, 3, 4, 5 },
{ 6, 7, 8, 9, 10 },
{ 11, 12, 12, 14, 15 },
{ 16, 17, 18, 18, 20 },
{ 21, 22, 23, 24, 25 } };
a = singleOccurence(m);
}
}
It may be better to use a boolean array boolean[] dups to track duplicated numbers, so during the first pass this intermediate array is populated and the number of singles is counted.
Then create the resulting array of appropriate size, and if this array is not empty, in the second iteration over the dups copy the values marked as singles to the resulting array.
public static int[] getSingles(int[][] arr) {
int n = arr.length;
int m = arr[0].length;
boolean[] dups = new boolean[n * m];
int singles = 0;
for (int i = 0; i < dups.length; i++) {
if (dups[i]) continue; // skip the value known to be a duplicate
int curr = arr[i / m][i % m];
boolean dup = false;
for (int j = i + 1; j < dups.length; j++) {
if (curr == arr[j / m][j % m]) {
dup = true;
dups[j] = true;
}
}
if (dup) {
dups[i] = true;
} else {
singles++;
}
}
// debugging log
System.out.println("singles = " + singles + "; " + Arrays.toString(dups));
int[] res = new int[singles];
if (singles > 0) {
for (int i = 0, j = 0; i < dups.length; i++) {
if (!dups[i]) {
res[j++] = arr[i / m][i % m];
}
}
}
return res;
}
Test:
int[][] mat = {
{2, 2, 3, 3},
{4, 2, 0, 3},
{5, 4, 2, 1}
};
System.out.println(Arrays.toString(getSingles(mat)));
Output(including debugging log):
singles = 3; [true, true, true, true, true, true, false, true, false, true, true, false]
[0, 5, 1]
Your use of previous is merely an idea on the horizon. Remove it, and fill the one dimensional a. Finding duplicates with two nested for-loops would require n4 steps. However if you sort the array a, - order the values - which costs n² log n², you can find duplicates much faster.
Arrays.sort(a);
int previous = a[0];
for (int h = 1; h < a.length; ++h) {
if (a[h] == previous)...
previous = a[h];
...
It almost looks like this solution was already treated in class.
It doesn't look good:
previous = m[i][j];
if (m[i][j] != previous) {
a[h] = m[i][j];
h++;
}
you assigned m[i][j] to previous and then you check if if (m[i][j] != previous)?
Are there any limitations in the task as to the range from which the numbers can come from?

Merge K sorted arrays

I am given k sorted arrays and need to merge them into one sorted array. We are assuming that n is the total number of elements in all the input arrays and that k=3.
public class Merge {
// Create a mergeklists() to merge 3 sorted arrays into one sorted array
// Input: 3 sorted arrays a1[], a2[], a3[]
// Output: one sorted array a[] that contains all the elements from input arrays
public static void merge3lists(int[] a1, int[] a2, int[] a3, int[] a)
{
int i=0;
int j=0;
int h=0;
int n = a1.length + a2.length + a3.length;
for(int k; a.length < n-1; k++){
if(a1[i] < a2[j]){
k = a1[i];
i++;
}
else if(a2[j] < a3[h]){
k = a2[j];
j++;
}
else{
k = a3[h];
h++;
}
}
}
public static void main(String[] args) {
int[] l1 = {1,5,9,10,20};
int[] l2 = {2,4,5,6,7,9,15};
int[] l3 = {3,8,13,15,22};
int[] newl = new int[l1.length+l2.length+l3.length];
merge3lists(l1,l2,l3,newl);
for(int i = 0; i< newl.length; i++)
{
System.out.print(newl[i]+ " ");
}
}
}
I know that the integers I am using (I,j,and h) are messing up the problem, but I don't think I can use i while comparing all the arrays. I need to use the declared array a, but I'm not sure how to reference it in this case.
To have to method merge an arbitrary number of arrays (k), you need to make the method use varargs.
It would also be better to have the method create the result array for you.
You then loop until the result array is filled. For each iteration, you find the smallest of the next value from each source array, and add that to the result array, and step forward in the source array you picked the value from.
Like this:
public static int[] mergeArrays(int[]... arrays) {
// Create result array
int n = 0;
for (int[] a : arrays)
n += a.length;
int[] result = new int[n];
// Start at index 0 in each source array
int[] idx = new int[arrays.length];
// Merge source arrays into result array
for (int i = 0; i < n; i++) {
// Find smallest value
int minJ = -1, minVal = 0;
for (int j = 0; j < arrays.length; j++) {
if (idx[j] < arrays[j].length) {
int val = arrays[j][idx[j]];
if (minJ == -1 || val < minVal) {
minJ = j;
minVal = val;
}
}
}
// Add to result array and step forward in appropriate source array
result[i] = minVal;
idx[minJ]++;
}
return result;
}
Test
int[] merged = mergeArrays(new int[] { 23, 39, 63, 68 },
new int[] { 11, 21, 76 },
new int[] { 5, 10, 37, 80 },
new int[] { 30, 49, 50, 94 },
new int[] { 13, 25, 48 });
System.out.println(Arrays.toString(merged));
Output
[5, 10, 11, 13, 21, 23, 25, 30, 37, 39, 48, 49, 50, 63, 68, 76, 80, 94]
Looks like a preparation exercise to motivate the introduction of array of arrays :)
Number the indices analogous to the lists to avoid confusion.
Identify the list with the smallest element at its current index. Avoid reading beyond the end of the array, as it will result in an exception.
Take this element and proceed.
int i1=0;
int i2=0;
int i3=0;
int n = a1.length + a2.length + a3.length;
for( int k = 0; k < n; k++) {
int advance = 0;
int value = Integer.MAX_VALUE;
if (i1 < a1.length && a1[i1] <= value) {
advance = 1;
value = a1[i1];
}
if (i2 < a2.length && a2[i2] <= value) {
advance = 2;
value = a2[i2];
}
if (i3 < a3.length && a3[i3] <= value) {
advance = 3;
value = a3[i3];
}
a[k] = value;
switch(advance) {
case 1: i1++; break;
case 2: i2++; break;
case 3: i3++; break;
}
}
A more efficient algorithm is to use a min-heap.
The algorithm is roughly described as follows:
First, construct a min-heap of size k (in this case size 3 for the three lists) taking the minimum elements in each list. You would then delete then the minimum element from the heap (noting which list it came from), add it to your newly constructed list, and then insert the next element from that same list which it was initially drawn from.
The time complexity would drop from O(n * k) to O(n * log(k)). Where n is the total number of elements in the final sorted list.
https://cs.stackexchange.com/questions/12853/heap-give-an-on-lg-k-time-algorithm-to-merge-k-sorted-lists-into-one-so

Java - Sorting out an array

I am encountering some slight and stupid issue while trying to sort out my arrays.
So here's what I'm doing and what I want to do :
I generate an array of ints (good ol' t = new int[];) filled with random generated numbers from -1 to 9. The size of the array is irrelevant. I would like to make so that each "-1" will get to the end of the array while every other will get "pushed" to take the place.
As I'm not a native english speaker it's really hard to express myself correctly on this.
Example :
my array is : 9 2 -1 4 6 -1
I want : 9 2 4 6 -1 -1
I currrently managed to get this BUT it won't work if there are two consecutives -1 cause the second one will get swapped.
Ex :
Initial : 9 2 -1 -1 4 6
After modif : 9 2 -1 4 6 -1
As I said the problem is probably really near from being solved but I really can't find a fix right now.
Here's my code :
for(int i=0;i<NB_CARD;i++)
{
t[i]=randomGenerator.nextInt(10)-1;
System.out.print("t["+i+"]= "+t[i]+"\t\t");
if(i==4){System.out.println("");}
}
//each -1 should be at the end of array
for(int i=0;i<NB_CARD;i++)
{
int tmp=0;
if(t[i]==-1)
{
for(int y=i;y<NB_CARD-1;y++)
{
tmp=t[y+1];
t[y+1]=t[y];
t[y]=tmp;
}
}
}
for(int i=0;i<NB_CARD;i++)
{
System.out.print("t["+i+"]= "+t[i]+"\t\t");
if(i==4){System.out.println("");}
}
Thank you in advance for every tip/help that could lead me to solve this
A more efficient way of doing this with one loop is.
int j = 0;
// copy all the non -1 values down.
for (int i = 0; i < NB_CARD; i++)
if (t[i] != -1)
t[j++] = t[i];
// fill the rest with -1
Arrays.fill(t, j, NB_CARD, -1);
if NB_CARD == t.length you can do
int[] t = {3, -1, -1, -1, 4, 5, 6, -1, -1};
int j = 0;
// copy all the non -1 values down.
for (int i : t)
if (i != -1)
t[j++] = i;
// fill the rest with -1
Arrays.fill(t, j, t.length, -1);
System.out.println(Arrays.toString(t));
prints
[3, 4, 5, 6, -1, -1, -1, -1, -1]
In Java 8 you can do this
int[] t = {6, -1, -1, -1, 4, 5, 3, -1, -1};
List<Integer> sorted = IntStream.of(t).boxed()
.sorted((a, b) -> (a > -1 ? 1 : 0) - (b > -1 ? 1 : 0))
.collect(Collectors.toList());
for (int i = 0; i < t.length; i++)
t[i] = sorted.get(i);
System.out.println(Arrays.toString(t));
which prints
[6, 4, 5, 3, -1, -1, -1, -1, -1]
though it is O(N log N) instead of O(N) and has more code.
I'd use Arrays.sort(T[] a, Comparator c), supplying your own Comparator that puts -1 at the end of the output.
Using bubble sort
package com.appkart.collections;
import java.util.Random;
public class Test {
public void fillRandomNumber(int a[]) {
Random random = new Random();
for (int i = 0; i < a.length; i++) {
a[i] = random.nextInt(10)-1;
}
}
public void printNumber(int a[]) {
for (int i = 0 ; i < a.length ;i++) {
System.out.print(a[i] +" ");
}
}
//Using bubble sort
public void sortRandomNumber(int a[]) {
int length = a.length;
int temp;
for (int i = 0; i < length; i++) {
for (int j = 1; j < length - i; j++) {
if (a[j - 1] < a[j]) {
temp = a[j - 1];
a[j - 1] = a[j];
a[j] = temp;
}
}
}
}
public static void main(String[] args) {
int a[] = new int[10];
Test test = new Test();
test.fillRandomNumber(a);
System.out.println("Random Number bofore sort");
test.printNumber(a);
test.sortRandomNumber(a);
System.out.println("\n Random Number after sort");
test.printNumber(a);
}
}
You can use something like this:
int[] a = { 9, 2, -1, 4, 6, -1 };
for(int i=a.length-1; i>0; i--)
{
for(int j=0; j<i; j++)
{
if(a[i] < a[j])
{
int jvalue = a[j];
a[j] = a[i];
a[i] = jvalue;
}
}
}
If I am understanding the code correctly, if you find a -1, you eventually bubble it up to the end.
What you could do, would be to store the location of the current last element, which at the beginning would be n - 1.
When you find a -1, you could replace the ith element with the current last element and then, decrease the value of current by 1. This should allow you to always put any new -1 elements you encounter at the end.
Code wise:
int[] t = new int[5];
t[0] = -1; t[1] = -1; t[2] = 4;
t[3] = -1; //Just for demonstration purposes
t[4] = -1; //Just for demonstration purposes
int currentLast = 0;
for(int i = t.length - 1; i >=0; i--)
{
if(t[i] == -1)
currentLast = i - 1;
else
break;
}
for(int i = 0; i < t.length; i++)
System.out.println(t[i]);
System.out.println("After");
for(int i = 0; i < currentLast; i++)
{
if(t[i] == -1)
{
int temp = t[currentLast];
t[currentLast] = t[i];
t[i] = temp;
currentLast--;
}
}
for(int i = 0; i < t.length; i++)
System.out.println(t[i]);
}
Yields:
-1
-1
4
-1
-1
After
4
-1
-1
-1
-1
You can convert the array into list, iterate over list and remove all -1, counting how many you removed. Then add that many at the end of the list. If the end result has to be an array, you can use List.toArray method to convert it back.
public static void main(String[] args) {
Integer[] t = {3, -1, -1, -1, 4, 5, 6, -1, -1};
List<Integer> list = new ArrayList<>();
Collections.addAll(list, t);
int numberOfMinusOnes = 0;
for (Integer number : list) {
if (number == -1) {
numberOfMinusOnes++;
}
}
list.removeAll(Arrays.asList(-1));
for (int i = 0; i < numberOfMinusOnes; i++) {
list.add(-1);
}
list.toArray(t);
System.out.println(Arrays.toString(t));
}
Some of boiler plate code can be simplified using google collections library. I would also advise to extract some parts into separate methods to increase readability.

Move 0's to end of array

I need to move all 0's in an array to the end of the array.
Example: [1, 10, 0, 5, 7] should result in [1, 10, 5, 7, 0].
I am open to doing a reverse loop or a regular loop.
I cannot create a new array.
Here is what I have so far:
for (int i = arr.length; i <= 0; --i) {
if (arr[i] != 0) {
arr[i] = arr.length - 1;
}
}
Thanks!
SIZE(n) where n = arr.size, retain ordering:
Create an array that is the same size as the initial array you need to remove 0s from. Iterate over the original array and add each element to the new array provided it is not 0. When you encounter a 0, count it. Now, when you've reached the end of the first array, simply add the counted number of 0s to the end of the array. And, even simpler, since Java initializes arrays to 0, you can forget about adding the zeroes at the end.
Edit
Since you have added the additional constraint of not being able to create a new array, we need to take a slightly different approach than the one I've suggested above.
SIZE(1)
I assume the array needs to remain in the same order as it was before the 0s were moved to the end. If this is not the case there is another trivial solution as detailed in Brads answer: initialize a "last zero" index to the last element of the array and then iterate backwards swapping any zeros with the index of the last zero which is decremented each time you perform a swap or see a zero.
SIZE(1), retain ordering:
To move the 0s to the end without duplicating the array and keeping the elements in the proper order, you can do exactly as I've suggested without duplicating the array but keeping two indices over the same array.
Start with two indices over the array. Instead of copying the element to the new array if it is not zero, leave it where it is and increment both indices. When you reach a zero, increment only one index. Now, if the two indices are not the same, and you are not looking at a 0, swap current element the location of the index that has fallen behind (due to encountered 0s). In both cases, increment the other index provided the current element is not 0.
It will look something like this:
int max = arr.length;
for (int i = 0, int j = 0; j < max; j++) {
if (arr[j] != 0) {
if (i < j) {
swap(arr, i, j);
}
i++
}
}
Running this on:
{ 1, 2, 0, 0, 0, 3, 4, 0, 5, 0 }
yeilds:
{ 1, 2, 3, 4, 5, 0, 0, 0, 0, 0 }
I made a fully working version for anyone who's curious.
Two choices come to mind
Create a new array of the same size, then Iterate over your current array and only populate the new array with values. Then fill the remaining entries in the new array with "zeros"
Without creating a new array you can iterate over your current array backwards and when you encounter a "zero" swap it with the last element of your array. You'll need to keep a count of the number of "zero" elements swapped so that when you swap for a second time, you swap with the last-1 element, and so forth.
[Edit] 7 years after originally posting to address the "ordering" issue and "last element is zero" issues left in the comments
public class MyClass {
public static void main(String[] args) {
int[] elements = new int[] {1,0,2,0,3,0};
int lastIndex = elements.length-1;
// loop backwards looking for zeroes
for(int i = lastIndex; i >=0; i--) {
if(elements[i] == 0) {
// found a zero, so loop forwards from here
for(int j = i; j < lastIndex; j++) {
if(elements[j+1] == 0 || j == lastIndex) {
// either at the end of the array, or we've run into another zero near the end
break;
}
else {
// bubble up the zero we found one element at a time to push it to the end
int temp = elements[j+1];
elements[j+1] = elements[j];
elements[j] = temp;
}
}
}
}
System.out.println(Arrays.toString(elements));
}
}
Gives you...
[1, 2, 3, 0, 0, 0]
Basic solution is to establish an inductive hypothesis that the subarray can be kept solved. Then extend the subarray by one element and maintain the hypothesis. In that case there are two branches - if next element is zero, do nothing. If next element is non-zero, swap it with the first zero in the row.
Anyway, the solution (in C# though) after this idea is optimized looks like this:
void MoveZeros(int[] a)
{
int i = 0;
for (int j = 0; j < a.Length; j++)
if (a[j] != 0)
a[i++] = a[j];
while (i < a.Length)
a[i++] = 0;
}
There is a bit of thinking that leads to this solution, starting from the inductive solution which can be formally proven correct. If you're interested, the whole analysis is here: Moving Zero Values to the End of the Array
var size = 10;
var elemnts = [0, 0, 1, 4, 5, 0,-1];
var pos = 0;
for (var i = 0; i < elemnts.length; i++) {
if (elemnts[i] != 0) {
elemnts[pos] = elemnts[i];
pos++;
console.log(elemnts[i]);
}
}
for (var i = pos; i < elemnts.length; i++) {
elemnts[pos++] = 0;
console.log(elemnts[pos]);
}
int arrNew[] = new int[arr.length];
int index = 0;
for(int i=0;i<arr.length;i++){
if(arr[i]!=0){
arrNew[index]=arr[i];
index++;
}
}
Since the array of int's is initialized to zero(according to the language spec). this will have the effect you want, and will move everything else up sequentially.
Edit: Based on your edit that you cannot use a new array this answer doesnt cover your requirements. You would instead need to check for a zero(starting at the end of the array and working to the start) and swap with the last element of the array and then decrease the index of your last-nonzero element that you would then swap with next. Ex:
int lastZero = arr.length - 1;
if(arr[i] == 0){
//perform swap and decrement lastZero by 1 I will leave this part up to you
}
/// <summary>
/// From a given array send al zeros to the end (C# solution)
/// </summary>
/// <param name="numbersArray">The array of numbers</param>
/// <returns>Array with zeros at the end</returns>
public static int[] SendZerosToEnd(int[] numbersArray)
{
// Edge case if the array is null or is not long enough then we do
// something in this case we return the same array with no changes
// You can always decide to return an exception as well
if (numbersArray == null ||
numbersArray.Length < 2)
{
return numbersArray;
}
// We keep track of our second pointer and the last element index
int secondIndex = numbersArray.Length - 2,
lastIndex = secondIndex;
for (int i = secondIndex; i >= 0; i--)
{
secondIndex = i;
if (numbersArray[i] == 0)
{
// While our pointer reaches the end or the next element
// is a zero we swap elements
while (secondIndex != lastIndex ||
numbersArray[secondIndex + 1] != 0)
{
numbersArray[secondIndex] = numbersArray[secondIndex + 1];
numbersArray[secondIndex + 1] = 0;
++secondIndex;
}
// This solution is like having two pointers
// Also if we look at the solution you do not pass more than
// 2 times actual array will be resume as O(N) complexity
}
}
// We return the same array with no new one created
return numbersArray;
}
In case if question adds following condition.
Time complexity must be O(n) - You can iterate only once.
Extra
space complexity must be O(1) - You cannot create extra array.
Then following implementation will work fine.
Steps to be followed :
Iterate through array & maintain a count of non-zero elements.
Whenever we encounter a non-zero element put at count location in array & also increase the count.
Once array is iterated completely put the zeros at end of array till the count reach to original length of array.
public static void main(String args[]) {
int[] array = { 1, 0, 3, 0, 0, 4, 0, 6, 0, 9 };
// Maintaining count of non zero elements
int count = -1;
// Iterating through array and copying non zero elements in front of array.
for (int i = 0; i < array.length; i++) {
if (array[i] != 0)
array[++count] = array[i];
}
// Replacing end elements with zero
while (count < array.length - 1)
array[++count] = 0;
for (int i = 0; i < array.length; i++) {
System.out.print(array[i] + " ");
}
}
Time complexity = O(n), Space Complexity = O(1)
import java.util.Scanner;
public class ShiftZeroesToBack {
int[] array;
void shiftZeroes(int[] array) {
int previousK = 0;
int firstTime = 0;
for(int k = 0; k < array.length - 1; k++) {
if(array[k] == 0 && array[k + 1] != 0 && firstTime != 0) {
int temp = array[previousK];
array[previousK] = array[k + 1];
array[k + 1] = temp;
previousK = previousK + 1;
continue;
}
if(array[k] == 0 && array[k + 1] != 0) {
int temp = array[k];
array[k] = array[k + 1];
array[k + 1] = temp;
continue;
}
if(array[k] == 0 && array[k + 1] == 0) {
if(firstTime == 0) {
previousK = k;
firstTime = 1;
}
}
}
}
int[] input(Scanner scanner, int size) {
array = new int[size];
for(int i = 0; i < size; i++) {
array[i] = scanner.nextInt();
}
return array;
}
void print() {
System.out.println();
for(int i = 0; i < array.length; i++) {
System.out.print(array[i] + " ");
}
System.out.println();
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
ShiftZeroesToBack sztb = new ShiftZeroesToBack();
System.out.print("Enter Size of Array\t");
int size = scanner.nextInt();
int[] input = sztb.input(scanner, size);
sztb.shiftZeroes(input);
sztb.print();
}
}
let's say we have an array
[5,4,0,0,6,7,0,8,9]
Let's assume we have array elements between 0-100, now our goal is to move all 0's at the end of the array.
now hold 0 from the array and check it with non zero element if any non zero element found swap with that element and so on, at the end of the loop we will find the solution.
here is the code
for (int i = 0; i < outputArr.length; i++)
{
for (int j = i+1; j < outputArr.length; j++)
{
if(outputArr[i]==0 && outputArr[j]!=0){
int temp = outputArr[i];
outputArr[i] = outputArr[j];
outputArr[j] = temp;
}
}
print outputArr[i]....
}
output:
[5,4,6,7,8,9,0,0,0]
Here is how i have implemented this.
Time complexity: O(n) and Space Complexity: O(1)
Below is the code snippet:
int arr[] = {0, 1, 0, 0, 2, 3, 0, 4, 0};
int i=0, k = 0;
int n = sizeof(arr)/sizeof(arr[0]);
for(i = 0; i<n; i++)
{
if(arr[i]==0)
continue;
arr[k++]=arr[i];
}
for(i=k;i<n;i++)
{
arr[i]=0;
}
output: {1, 2, 3, 4, 0, 0, 0, 0, 0}
Explanation: using another variable k to hold index location, non-zero elements are shifted to the front while maintaining the order. After traversing the array, non-zero elements are shifted to the front of array and another loop starting from k is used to override the remaining positions with zeros.
This is my code with 2 for loops:
int [] arr = {0, 4, 2, 0, 0, 1, 0, 1, 5, 0, 9,};
int temp;
for (int i = 0; i < arr.length; i++)
{
if (arr[i] == 0)
{
for (int j = i + 1; j < arr.length; j++)
{
if (arr[j] != 0)
{
temp = arr[j];
arr[j] = arr[i];
arr[i] = temp;
break;
}
}
}
}
System.out.println(Arrays.toString(arr));
output: [4, 2, 1, 1, 5, 9, 0, 0, 0, 0, 0]
public static void main(String[] args) {
Integer a[] = {10,0,0,0,6,0,0,0,70,6,7,8,0,4,0};
int flag = 0;int count =0;
for(int i=0;i<a.length;i++) {
if(a[i]==0 ) {
flag=1;
count++;
}else if(a[i]!=0) {
flag=0;
}
if(flag==0 && count>0 && a[i]!=0) {
a[i-count] = a[i];
a[i]=0;
}
}
}
This is One method of Moving the zeroes to the end of the array.
public class SeparateZeroes1 {
public static void main(String[] args) {
int[] a = {0,1,0,3,0,0,345,12,0,13};
movezeroes(a);
}
static void movezeroes(int[] a) {
int lastNonZeroIndex = 0;
// If the current element is not 0, then we need to
// append it just in front of last non 0 element we found.
for (int i = 0; i < a.length; i++) {
if (a[i] != 0 ) {
a[lastNonZeroIndex++] = a[i];
}
}//for
// We just need to fill remaining array with 0's.
for (int i = lastNonZeroIndex; i < a.length; i++) {
a[i] = 0;
}
System.out.println( lastNonZeroIndex );
System.out.println(Arrays.toString(a));
}
}
This is very simple in Python. We will do it with list comprehension
a =[0,1,0,3,0,0,345,12,0,13]
def fix(a):
return ([x for x in a if x != 0] + [x for x in a if x ==0])
print(fix(a))
int[] nums = { 3, 1, 2, 5, 4, 6, 3, 2, 1, 6, 7, 9, 3, 8, 0, 4, 2, 4, 6, 4 };
List<Integer> list1 = new ArrayList<>();
List<Integer> list2 = new ArrayList<>();
for (int i = 0; i < nums.length; i++) {
if (nums[i] == 3) {
list1.add(nums[i]);
} else if (nums[i] != 3) {
list2.add(nums[i]);
}
}
List<Integer> finalList = new ArrayList<>(list2);
finalList.addAll(list1);
}
}
int[] nums = {3,1,2,5,4,6,3,2,1,6,7,9,3,8,0,4,2,4,6,4};
int i = 0;
for(int j = 0, s = nums.length; j < s;) {
if(nums[j] == 3)
j++;
else {
int temp = nums[i];
nums[i] = nums[j];``
nums[j] = temp;
i ++;
j ++;
}
}
For Integer array it can be as simple as
Integer[] numbers = { 1, 10, 0, 5, 7 };
Arrays.sort(numbers, Comparator.comparing(n -> n == 0));
For int array :
int[] numbers = { 1, 10, 0, 5, 7 };
numbers = IntStream.of(numbers).boxed()
.sorted(Comparator.comparing(n -> n == 0))
.mapToInt(i->i).toArray();
Output of both:
[1, 10, 5, 7, 0]
Lets say, you have an array like
int a[] = {0,3,0,4,5,6,0};
Then you can sort it like,
for(int i=0;i<a.length;i++){
for(int j=i+1;j<a.length;j++){
if(a[i]==0 && a[j]!=0){
a[i]==a[j];
a[j]=0;
}
}
}
public void test1(){
int [] arr = {0,1,0,4,0,3,2};
System.out.println("Lenght of array is " + arr.length);
for(int i=0; i < arr.length; i++){
for(int j=0; j < arr.length - i - 1; j++){
if(arr[j] == 0){
int temp = arr[j];
arr[j] = arr[arr.length - i - 1];
arr[arr.length - i - 1] = temp;
}
}
}
for(int x = 0; x < arr.length; x++){
System.out.println(arr[x]);
}
}
Have a look at this function code:
vector<int> Solution::solve(vector<int> &arr) {
int count = 0;
for (int i = 0; i < arr.size(); i++)
if (arr[i] != 0)
arr[count++] = arr[i];
while (count < arr.size())
arr[count++] = 0;
return arr;
}
import java.io.*;
import java.util.*;
class Solution {
public static int[] moveZerosToEnd(int[] arr) {
int j = 0;
for(int i = 0; i < arr.length; i++) {
if(arr[i] != 0) {
swap(arr, i, j);
j++;
}
}
return arr;
}
private static void swap(int arr[], int i, int j){
int temp = arr[j];
arr[j] = arr[i];
arr[i] = temp;
}
public static void main(String[] args) {
int arr[] =new int[] {1, 10, 0, 2, 8, 3, 0, 0, 6, 4, 0, 5, 7, 0 };
System.out.println(Arrays.toString(moveZerosToEnd(arr)));
}
}
Reimplemented this in Python:
Pythonic way:
lst = [ 1, 2, 0, 0, 0, 3, 4, 0, 5, 0 ]
for i, val in enumerate(lst):
if lst[i] == 0:
lst.pop(i)
lst.append(0)
print("{}".format(lst))
#dcow's implementation in python:
lst = [ 1, 2, 0, 0, 0, 3, 4, 0, 5, 0 ]
i = 0 # init the index value
for j in range(len(lst)): # using the length of list as the range
if lst[j] != 0:
if i < j:
lst[i], lst[j] = lst[j], lst[i] # swap the 2 elems.
i += 1
print("{}".format(lst))
a = [ 1, 2, 0, 0, 0, 3, 4, 0, 5, 0 ]
count = 0
for i in range(len(a)):
if a[i] != 0:
a[count], a[i] = a[i], a[count]
count += 1
print(a)
#op [1, 2, 3, 4, 5, 0, 0, 0, 0, 0]

Efficient way to count unique pairs in int array

This is my first post, hope it complies with posting guidelines of the site.
First of all a generic thanks to all the community: reading you from some months and learned a lot :o)
Premise: I'm a first years student of IT.
Here's the question: I'm looking for an efficient way to count the number of unique pairs (numbers that appear exactly twice) in a given positive int array (that's all I know), e.g. if:
int[] arr = {1,4,7,1,5,7,4,1,5};
the number of unique pairs in arr is 3 (4,5,7).
I have some difficulties in... evaluating the efficiency of my proposals let's say.
Here's the first code I did:
int numCouples( int[] v ) {
int res = 0;
int count = 0;
for (int i = 0 ; i < v.length; i++){
count = 0;
for (int j = 0; j < v.length; j++){
if (i != j && v[i] == v[j]){
count++;
}
}
if (count == 1){
res++;
}
}
return res/2;
}
This shoudn't be good cause it checks the whole given array as many times as the number of elements in the given array... correct me if I'm wrong.
This is my second code:
int numCouples( int[] v) {
int n = 0;
int res = 0;
for (int i = 0; i < v.length; i++){
if (v[i] > n){
n = v[i];
}
}
int[] a = new int [n];
for (int i = 0; i < v.length; i++){
a[v[i]-1]++;
}
for (int i = 0; i < a.length; i++){
if (a[i] == 2){
res++;
}
}
return res;
}
I guess this should be better than the first one since it checks only 2 times the given array and 1 time the n array, when n is the max value of the given array. May be not so good if n is quite big I guess...
Well, 2 questions:
am I understanding good how to "measure" the efficiency of the code?
there's a better way to count the number of unique pairs in a given array?
EDIT:
Damn I've just posted and I'm already swamped by answers! Thanks! I'll study each one with care, for the time being I say I don't get those involving HashMap: out of my knowledge yet (hence thanks again for the insight:o) )
public static void main(String[] args) {
int[] arr = { 1, 4, 7, 1, 5, 7, 4, 1, 5 };
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
for (int i = 0; i < arr.length; i++) {
Integer count = map.get(arr[i]);
if (count == null)
map.put(arr[i], 1);
else
map.put(arr[i], count + 1);
}
int uniqueCount = 0;
for (Integer i : map.values())
if (i == 2)
uniqueCount++;
System.out.println(uniqueCount);
}
Well, here's another answer to your's 2 questions:
am I understanding good how to "measure" the efficiency of the code?
There are various ways to measure efficiency of the code. First of all, people distinguish between memory efficiency and time efficiency. The usual way to count all these values is to know, how efficient are the building blocks of your algorithm. Have a look at the wiki.
For instance, sorting using quicksort would need n*log(n) operations. Iterating through the array would need just n operations, where n is number of elements in the input.
there's a better way to count the number of unique pairs in a given array?
Here's another solution for you. The complixity of this one would be: O(n*log(n)+n), where O(...) is Big O notation.
import java.util.Arrays;
public class Ctest {
public static void main(String[] args) {
int[] a = new int[] { 1, 4, 7, 1, 7, 4, 1, 5, 5, 8 };
System.out.println("RES: " + uniquePairs(a));
}
public static int uniquePairs(int[] a) {
Arrays.sort(a);
// now we have: [1, 1, 1, 4, 4, 5, 5, 7, 7]
int res = 0;
int len = a.length;
int i = 0;
while (i < len) {
// take first number
int num = a[i];
int c = 1;
i++;
// count all duplicates
while(i < len && a[i] == num) {
c++;
i++;
}
System.out.println("Number: " + num + "\tCount: "+c);
// if we spotted number just 2 times, increment result
if (c == 2) {
res++;
}
}
return res;
}
}
public static void main(String[] args) {
int[] arr = {1,4,7,1,7,4,1,5};
Map<Integer, Integer> counts = new HashMap<Integer,Integer>();
int count = 0;
for(Integer num:arr){
Integer entry = counts.get(num);
if(entry == null){
counts.put(num, 1);
}else if(counts.get(num) == 1){
count++;
counts.put(num, counts.get(num) + 1);
}
}
System.out.println(count);
}
int [] a = new int [] {1, 4, 7, 1, 7, 4, 1, 5, 1, 1, 1, 1, 1, 1};
Arrays.sort (a);
int res = 0;
for (int l = a.length, i = 0; i < l - 1; i++)
{
int v = a [i];
int j = i + 1;
while (j < l && a [j] == v) j += 1;
if (j == i + 2) res += 1;
i = j - 1;
}
return res;
you can use HashMap for easy grouping. here is my code.
int[] arr = {1,1,1,1,1,1,4,7,1,7,4,1,5};
HashMap<Integer,Integer> asd = new HashMap<Integer, Integer>();
for(int i=0;i<arr.length;i++)
{
if(asd.get(arr[i]) == null)
{
asd.put(arr[i], 1);
}
else
{
asd.put(arr[i], asd.get(arr[i])+1);
}
}
//print out
for(int key:asd.keySet())
{
//get pair
int temp = asd.get(key)/2;
System.out.println(key+" have : "+temp+" pair");
}
added for checking the unique pair, you can delete the print out one
//unique pair
for(int key:asd.keySet())
{
if(asd.get(key) == 2)
{
System.out.println(key+" are a unique pair");
}
}
after some time another solution, which should work great.
public getCouplesCount(int [] arr) {
int i = 0, i2;
int len = arr.length;
int num = 0;
int curr;
int lastchecked = -1;
while (i < len-1) {
curr = arr[i];
i2 = i + 1;
while (i2 < len) {
if (curr == arr[i2] && arr[i2] != lastchecked) {
num++; // add 1 to number of pairs
lastchecked = curr;
i2++; // iterate to next
} else if (arr[i2] == lastchecked) {
// more than twice - swap last and update counter
if (curr == lastchecked) {
num--;
}
// swap with last
arr[i2] = arr[len-1];
len--;
} else {
i2++;
}
i++;
}
return num;
}
i am not shure if it works, but it is more effective than sorting the array first, or using hashmaps....
A Java8 parallel streamy version which uses a ConcurrentHashMap
int[] arr = {1,4,7,1,5,7,4,1,5};
Map<Integer,Long> map=Arrays.stream(arr).parallel().boxed().collect(Collectors.groupingBy(Function.identity(),
ConcurrentHashMap::new,Collectors.counting()));
map.values().removeIf(v->v!=2);
System.out.println(map.keySet().size());
#include <bits/stdc++.h>
using namespace std;
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int arr[9] = {1,4,7,1,5,7,4,1,5}; // given array
int length=9; // this should be given
int count=0;
map<int,int> m;
for(int i=0;i<length;i++)
m[arr[i]]++;
cout<<"List of unique pairs : ";
for(auto it=m.begin();it!=m.end();it++)
if(it->second==2)
{
count++;
cout<<it->first<<" ";
}
cout<<"\nCount of unique pairs(appears exactly twice) : "<<count;
return 0;
}
OUTPUT :
List of unique pairs : 4 5 7
Count of unique pairs(appears exactly twice) : 3
Time Complexity : O(N) where N is the number of elements in array
Space Complexity : O(N) total no. of unique elements in array always <=N
var sampleArray = ['A','B','C','D','e','f','g'];
var count = 0;
for(var i=0; i<=sampleArray.length; i++) {
for(var j=i+1; j<sampleArray.length; j++) {
count++;
console.log(sampleArray[i] , sampleArray[j]);
}
}
console.log(count);
This is the simple way I tried.

Categories

Resources