Java ArrayOutOfBoundException in ArrayList - java

The question is Define a cluster in an integer array to be a maximum sequence of elements that are all the same value. For example, in the array {3, 3, 3, 4, 4, 3, 2, 2, 2, 2, 4} there are 5 clusters, {3, 3, 3}, {4, 4}, {3}, {2, 2, 2, 2} and {4}. A cluster-compression of an array replaces each cluster with the number that is repeated in the cluster. So, the cluster compression of the previous array would be {3, 4, 3, 2, 4}. The first cluster {3, 3, 3} is replaced by a single 3, and so on.
public static void main(String[] args) {
int[] givenArray = {1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1};
System.out.println("Clustered Array = " + Arrays.toString(isTrivalent(givenArray)));
}
public static int[] isTrivalent (int[] a){
List<Integer> cluster = new ArrayList<Integer>();
for (int i=0; i<a.length ; i++ ) {
if(i == 0){
cluster.add(a[i]);
}else{
if(cluster.get(i-1) != a[i]) cluster.add(a[i]);
}
}
int[] arr = new int[cluster.size()];
for (int j =0; j<cluster.size() ; j++) {
arr[j] = cluster.get(j);
}
return arr;
}
But I am getting an ArrayOutOfBoundException. What am I doing wrong?

Change
if(cluster.get(i-1) != a[i]) cluster.add(a[i]);
to
if(a[i-1] != a[i]) cluster.add(a[i]);
cluster.get(i-1) may not exist.

This is happening because when you check
if(cluster.get(i-1) != a[i])
it is not necessary that the cluster arraylist will actually have size of atleast i-1 since you are skipping a lot of array elements. You need to change your condition to
if(cluster.get(cluster.size()-1) != a[i])
or equivalently (as suggested in previous answer)
if(a[i-1] != a[i])
for this code to work as intended.
public static void main(String[] args) {
int[] givenArray = {1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1};
System.out.println("Clustered Array = " + Arrays.toString(isTrivalent(givenArray)));
}
public static int[] isTrivalent(int[] a) {
List<Integer> cluster = new ArrayList<Integer>();
for (int i = 0; i < a.length; i++) {
if (i == 0) {
cluster.add(a[i]);
} else {
if (cluster.get(cluster.size() - 1) != a[i]) {
cluster.add(a[i]);
}
}
}
int[] arr = new int[cluster.size()];
for (int j = 0; j < cluster.size(); j++) {
arr[j] = cluster.get(j);
}
return arr;
}

Related

Sorting a 2D array/Matrix by its diagonals

How could I rearrange a matrix by sorting every diagonal of a matrix?
[8, 4, 1 ] [4, 1, 1]
[4, 4, 1] --> [4, 8, 4]
[4, 8, 9] ‍‍‌‌‌‍‍‍‍‌‍‍‌‍‌‌‌‍‍ [4, 8, 9]
you can try something like this. However this is only for the forward diagonal.
public void diagonalArr(int[][] arr) {
int[] diagonalArr = new int[arr.length];
for(int i = 0;i<arr.length;i++) {
for(int j = 0;j<arr[0].length;j++) {
if(i == j) {
diagonalArr[i] = arr[i][j];
}
}
}
Arrays.sort(diagonalArr);
for(int i = 0;i<arr.length;i++) {
for(int j = 0;j<arr[0].length;j++) {
if(i == j) {
arr[i][j] = diagonalArr[i];
}
}
}
}

Combinations Java [duplicate]

I need to find a way to remove duplicates from a combination like this:
Input: 3 and 2, where 3 is the range (from 1 to 3) and 2 is the length of each combination
Output: {1, 1} {1, 2} {1, 3} {2, 1} {2, 2} {2, 3} {3, 1} {3, 2} {3, 3}
Expected output: {1, 1} {1, 2} {1, 3} {2, 2} {2, 3} {3, 3}
So we start with {1, 1} -> {1, 2} -> {1, 3} -> but {2, 1} is a duplicate of {1, 2} so we ignore it and so on.
Here's my code:
import java.util.Scanner;
public class Main {
private static int[] result;
private static int n;
private static void printArray() {
String str = "( ";
for (int number : result) {
str += number + " ";
}
System.out.print(str + ") ");
}
private static void gen(int index) {
if (index == result.length) {
printArray();
return;
}
for (int i = 1; i <= n; i++) {
result[index] = i;
gen(index + 1);
}
}
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.print("From 1 to: ");
n = input.nextInt();
System.out.print("Length: ");
int k = input.nextInt();
result = new int[k];
gen(0);
}
}
You can pass the last max value used into gen:
private static void gen(int index, int minI) {
if (index == result.length) {
printArray();
return;
}
for (int i = minI; i <= n; i++) {
result[index] = i;
gen(index + 1, i);
}
}
And call it starting with 1: gen(0, 1);

Sort multidimensional array by pairs

I am trying to sort a multidimensional array by pairs. I know I can use a Comparator, but I want to achieve that with my code. Here is what I tried so far:
private static void sortArr(int[][] arr) {
for (int i = 0; i < arr.length; i++) {
int maxValColumnIndex0 = arr[i][0];
int maxValColumnIndex1 = arr[i][1];
int maxIndex = i;
for (int column = i + 1; column < arr[i].length; column++) {
if (maxValColumnIndex1 < arr[column][1]){
maxValColumnIndex1 = arr[column][1];
maxValColumnIndex0 = arr[column][0];
maxIndex = column;
}
if (i != maxIndex){
arr[maxIndex][0] = arr[i][0];
arr[maxIndex][1] = arr[i][1];
arr[i][0] = maxValColumnIndex0;
arr[i][1] = maxValColumnIndex1;
}
}
}
}
Sample input:
{{4, 2}, {1, 7}, {4, 5}, {1, 2}, {1, 1}, {4, 1}}
The output should be like:
{{1, 1}, {1, 2}, {1, 7}, {4, 1}, {4, 2}, {4, 5}}
What I already get:
{{1, 7}, {4, 2}, {4, 5}, {1, 2}, {1, 1}, {4, 1}}`
How to sort that array by pair?
A solution could be to sort them as pairs as you said. Here's modified bubble sort, to work with your example:
private static void sortArr(int[][] arr) {
for (int i = 0; i < arr.length; i++) {
for (int column = 0; column < arr.length - 1; column++) {
if(arr[column][0] > arr[column + 1][0]) {
swap(arr, column);
} else if(arr[column][0] == arr[column + 1][0] && arr[column][1] > arr[column + 1][1]) {
swap(arr, column);
}
}
}
}
private static void swap(int[][] arr, int column) {
int[] temp = arr[column];
arr[column] = arr[column + 1];
arr[column + 1] = temp;
}
The result is as you want : [[1, 1], [1, 2], [1, 7], [4, 1], [4, 2], [4, 5]]

Finding all possible combinations of a given array in Java

I'm working on a problem in Java to find all possible combinations given an arbitrary starting array, by decrementing the values one at a time of each item in the array until the value 1 is reached at each index.
I've started on the below test case but haven't got very far.
I would like some help in solving my problem please.
import org.junit.Assert;
import org.junit.Test;
public class ComboTest
{
#Test
public void test()
{
int[][] answers = {
{4, 3, 2}, {3, 3, 2}, {2, 3, 2}, {1, 3, 2},
{4, 2, 2}, {3, 2, 2}, {2, 2, 2}, {1, 2, 2},
{4, 1, 2}, {3, 1, 2}, {2, 1, 2}, {1, 1, 2},
{4, 3, 1}, {3, 3, 1}, {2, 3, 1}, {1, 3, 1},
{4, 2, 1}, {3, 2, 1}, {2, 2, 1}, {1, 2, 1},
{4, 1, 1}, {3, 1, 1}, {2, 1, 1}, {1, 1, 1},
};
int[] start = {4, 3, 2};
int dim = 1;
for (int i = 0; i < start.length; i++)
{
dim *= start[i];
}
int[][] combos = new int[dim][start.length];
for (int i = 0; i < combos[0].length; i++)
{
combos[0][i] = start[i];
}
for (int i = 1; i < combos.length; i++)
{
for (int j = 0; j < combos[i].length; j++)
{
int k = combos[i - 1][j] - 1;
if (k < 1)
{
k = start[j];
}
combos[i][j] = k;
}
}
for (int i = 0; i < combos.length; i++)
{
for (int j = 0; j < combos[i].length; j++)
{
Assert.assertEquals(answers[i][j], combos[i][j]);
}
}
}
}
This is a simple state search problem. You have a starting state, and you can expand it (create its children) following some criteria. In your case, by decrementing one of the values, but not below some lower bound.
If you're not familiar with DFS or BFS, I suggest reading on those. In the meantime, here's the code (perhaps the solution is not in the format you're expecting, but you can work on it :D):
public class ComboTest {
public static class Combo {
private Integer[] values;
public Combo(Integer[] values) {
this.values = values;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + Arrays.hashCode(values);
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (!(obj instanceof Combo)) {
return false;
}
Combo other = (Combo) obj;
if (!Arrays.equals(values, other.values)) {
return false;
}
return true;
}
#Override
public String toString() {
return Arrays.toString(values);
}
}
public static Set<Combo> combos(Combo start, int lowerBound) {
Set<Combo> answers = new HashSet<Combo>();
compute(start, lowerBound, answers);
return answers;
}
private static void compute(Combo start, int lowerBound, Set<Combo> answers) {
Deque<Combo> dfsStack = new ArrayDeque<Combo>();
dfsStack.push(start);
while (!dfsStack.isEmpty()) {
Combo current = dfsStack.pop();
answers.add(current);
for (Combo next : expand(current, lowerBound)) {
if (!answers.contains(next)) {
dfsStack.push(next);
}
}
}
}
private static List<Combo> expand(Combo current, int lowerBound) {
List<Combo> nexts = new ArrayList<Combo>();
for (int i = 0; i < current.values.length; i++) {
if (current.values[i] > lowerBound) {
Integer[] copyCurrent = Arrays.copyOf(current.values, current.values.length);
copyCurrent[i]--;
nexts.add(new Combo(copyCurrent));
}
}
return nexts;
}
public static void main(String[] args) {
Combo start = new Combo(new Integer[] { 4, 3, 2 });
Set<Combo> combos = combos(start, 1);
for (Combo combo : combos) {
System.out.println(combo);
}
System.out.println(combos.size());
}
}
Output:
[4, 3, 1]
[2, 1, 1]
[3, 2, 1]
[1, 1, 2]
[2, 2, 2]
[3, 3, 2]
[4, 3, 2]
[4, 2, 1]
[3, 1, 1]
[2, 1, 2]
[3, 2, 2]
[4, 1, 1]
[4, 2, 2]
[3, 1, 2]
[4, 1, 2]
[1, 3, 1]
[1, 2, 1]
[2, 3, 1]
[1, 3, 2]
[1, 1, 1]
[2, 2, 1]
[3, 3, 1]
[1, 2, 2]
[2, 3, 2]
24
you Seaching all permutation of an Array with n elements so this is Already asked here
Permutation algorithm for array of integers in Java
This is not my Answer im Only Refering to it
static ArrayList<int[]> permutations(int[] a) {
ArrayList<int[]> ret = new ArrayList<int[]>();
permutation(a, 0, ret);
return ret;
}
public static void permutation(int[] arr, int pos, ArrayList<int[]> list){
if(arr.length - pos == 1)
list.add(arr.clone());
else
for(int i = pos; i < arr.length; i++){
swap(arr, pos, i);
permutation(arr, pos+1, list);
swap(arr, pos, i);
}
}
public static void swap(int[] arr, int pos1, int pos2){
int h = arr[pos1];
arr[pos1] = arr[pos2];
arr[pos2] = h;
}
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class New{
public static void main(String[] args) {
Scanner in=new Scanner(System.in);
System.out.println("ENTER THE ARRAY SIZE");
int n=in.nextInt();
System.out.println("ENTER THE ARRAY VALUES");
int[] a=new int[n];
String s="";
for(int i=0;i<n;i++)
{
a[i]=in.nextInt();
s=s+(char)a[i];
}
List<String> hs=mac(s);
System.out.println("THE COMBINATIONS ARE");
for(String str:hs)
{
char[] ch=str.toCharArray();
for(int i=0;i<ch.length;i++)
{
System.out.print((int)ch[i]);
}
System.out.println();
}
}
public static List<String> mac(String s)
{
List<String> ss=new ArrayList<String>();
if(s==null)
{
return null;
}
else if(s.length()==0)
{
ss.add("");
}
else
{
String str=s.substring(1);
char c=s.charAt(0);
List<String> hs=mac(str);
for(String st:hs)
{
for(int i=0;i<=st.length();i++)
{
ss.add(sru(st,c,i));
}
}
}
return ss;
}
public static String sru(String s,char c,int i)
{
String start=s.substring(0,i);
String end=s.substring(i);
return start+c+end;
}
}
Easier method:
There's a library called Google Guava, that will do this thing for you.
You can find it here: https://github.com/google/guava
Idk if this code fits for you but anyway here's the code. Hope it helps :) ...
Collection<List<String>> permutations = null;
String[] foo = //your array in here
permutations = Collections2.permutations(Lists.newArrayList(foo));
//use for each loop to read
for (List<String> permutation : permutations) {
//Output here
}

Duplicate array elements and unique elements

So, i am writing a program that analyzes an entire array and displays the repeated values as well as the unique values:
int dupe = 0;
int[] range = {1, 1, 2, 2, 2, 3, 3, 3, 4, 5, 6, 6};
for (int i = 0; i < range.length; i++) {
for (int j = i + 1; j < range.length; j++) {
if (range[i] == range[j]) {
dup = range[j];
System.out.println(dup);
}
}
}
The above code outputs the repeated values correctly but when the value repeats three or more times, it outputs that value many times instead of just once
1
2
2
2
3
3
3
6
How can i fix this?
For the unique value part of the program, i don't know where to start.
Thanks!
EDIT: The only Arrays class methods i can use are: binarySearch, copyOf, equals, fill, sort, and toString
I need to write my own implementation - not to use Set, HashSet etc. Or any other tools such as iterators
You can do somthing like bellow:
int[] range = {1, 1, 2, 2, 2, 3, 3, 3, 4, 5, 6, 6};
boolean duplicate = false;
for (int i = 0; i < range.length; i++) {
duplicate = false;
for (int j = i + 1; j < range.length; j++) {
if (range[i] == range[j]) {
duplicate = true
}
}
if(!duplicate){
System.out.println(range[i]);
}
}
You can add your values to Set. it will do all work for you.
int end = arr.length;
Set<Integer> set = new HashSet<Integer>();
for(int i = 0; i < end; i++){
set.add(arr[i]);
}
If you cannot use other data structures, here is a good solution: https://stackoverflow.com/a/17974322/2290763
Other solution are correct but they will give O(n^2), you don't need to use two for loops. This will give you O(n)
int[] range = {1, 1, 2, 2, 2, 3, 3, 3, 4, 5, 6, 6};
int temp = range[0];
if(temp != range[range.length-1]){
for (int i = 1; i < range.length; i++) {
if(temp != range[i]){
System.out.println(temp);
temp = range[i];
}
}
}
else
System.out.println(temp);
Try after sorting the array:
int[] range = { 1, 1, 2, 2, 2, 3, 3, 3, 4, 5, 6, 6 };
Arrays.sort(range);
System.out.println(range.length > 0 ? range[0]
: "No sufficient elements");
for (int i = 1; i < range.length; i++) {
if (range[i - 1] != range[i]) {
System.out.println(range[i]);
}
}
Each value in the array is either unique or occurs multiple times. There are no other cases.
So your task can be stripped down to just remove the duplicates and print everything else.
If the array is sorted then it is sufficient to just check against the last value while iterating to recognize duplicates.
I would do this:
int[] range = {1, 1, 2, 2, 2, 3, 3, 3, 4, 5, 6, 6};
Arrays.sort(range);
for (int i = 0; i < range.length; i++) {
if (i == 0) {
System.out.println(range[0]);
} else if (range[i - 1] != range[i]) {
System.out.println(range[i]);
}
}
Edited. Try this:
int[] range = { 1, 1, 2, 2, 2, 3, 3, 3, 4, 5, 6, 6};
for (int i = 0; i < range.length; i++) {
int j = i + 1;
for (; j < range.length && range[i] == range[j]; j++) {
// do nothing
}
if (j >= i + 2) {
System.out.println(range[i]);
i = j;
}
}
}
The problem in your solution is int this part
for (int i = 0; i < range.length; i++) {
for (int j = i + 1; j < range.length; j++) {
For every element in array you are checking is there element with same value, and index is greater than index of element.
For example, for element with index 2 (value 2) it's checking all (indexes: 3, 4, 5, 6, ...). And there are two matches (elements with index 3 and 4).
Edit: (After #FabianBarney comment)
Solution:
String uni = "Uniques: ";
String dup = "Duplicates: ";
int[] range = { 1, 1, 2, 2, 2, 3, 3, 3, 4, 5, 6, 6};
for (int i = 0; i < range.length; i++) {
if (i + 1 < range.length && range[i + 1] == range[i]) {
dup += range[i] + " ";
int j = i + 1;
while (j < range.length && range[i] == range[j]) {
j++;
}
i = j - 1;
} else {
uni += range[i] + " ";
}
}
System.out.println(uni);
System.out.println(dup);

Categories