I'm trying to solve a problem on CodeFights called firstDuplicate, that states -
Given an array a that contains only numbers in the range from 1 to
a.length, find the first duplicate number for which the second
occurrence has the minimal index. In other words, if there are more
than 1 duplicated numbers, return the number for which the second
occurrence has a smaller index than the second occurrence of the other
number does. If there are no such elements, return -1.
Example
For a = [2, 3, 3, 1, 5, 2], the output should be firstDuplicate(a) =
3.
There are 2 duplicates: numbers 2 and 3. The second occurrence of 3
has a smaller index than than second occurrence of 2 does, so the
answer is 3.
For a = [2, 4, 3, 5, 1], the output should be firstDuplicate(a) = -1.
My solution -
public class FirstDuplicate {
private static HashMap<Integer, Integer> counts = new HashMap<>();
private static void findSecondIndexFrom(int[] num, int n, int i) {
// given an array, a starting index and a number, find second occurrence of that number beginning from next index
for(int x = i; x < num.length; x++) {
if(num[x] == n) {
// second occurrence found - place in map and terminate
counts.put(n, x);
return;
}
}
}
private static int firstDuplicate(int[] a) {
// for each element in loop, if it's not already in hashmap
// find it's second occurrence in array and place number and index in map
for(int i = 0; i < a.length; i++) {
if(!counts.containsKey(a[i])) {
findSecondIndexFrom(a, a[i], i+1);
}
}
System.out.println(counts);
// if map is empty - no duplicate elements, return -1
if(counts.size() == 0) {
return -1;
}
// else - get array of values from map, sort it, find lowest value and return corresponding key
ArrayList<Integer> values = new ArrayList<>(counts.values());
Collections.sort(values);
int lowest = values.get(0);
//System.out.println(lowest);
for(Map.Entry<Integer, Integer> entries: counts.entrySet()) {
if(entries.getValue() == lowest) {
return entries.getKey();
}
}
return -1;
}
public static void main(String[] args) {
// int[] a = new int[]{2, 3, 3, 1, 5, 2};
//int[] a = new int[]{2, 4, 3, 5, 1};
//int[] a = new int[]{8, 4, 6, 2, 6, 4, 7, 9, 5, 8};
//int[] a = new int[]{1, 1, 2, 2, 1};
int[] a = new int[]{10, 6, 8, 4, 9, 1, 7, 2, 5, 3};
System.out.println(firstDuplicate(a));
}
}
This solution passes only for about 4 of the 11 test cases on CodeFights. However, I manually executed each one of the test cases in my IDE, and each one produces the right result.
I can't figure out why this won't work in CodeFights. Does it have something to do with the use of the static HashMap?
Edited: Since adding and checking if element is present in Set can be done in one step, code can be simplified to:
public static int findDuplicateWithLowestIndex(int... a){
Set<Integer> set = new HashSet<>();
for(int num : a){
if(!set.add(num)){
return num;
}
}
return -1;
}
You're completly right Patrick.
Use this solution: here duplicateIndex should be very large number.
package sample;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Duplicate {
public static Integer secondIndex(Integer[] arr) {
List<Integer> arrlist = new ArrayList<>(Arrays.asList(arr));
int duplicateIndex = 999;
int ele = 0;
for (int i = 0; i < arrlist.size(); i++) {
int secondIndex = getSecondIndex(arrlist, arrlist.get(i));
if (secondIndex >= 0 && duplicateIndex > secondIndex) {
duplicateIndex = secondIndex;
ele = arrlist.get(i);
}
}
return duplicateIndex == 999 ? -1 : ele;
}
public static int getSecondIndex(List<Integer> arr, int ele) {
List<Integer> var0 = new ArrayList<>(arr);
var0.set(var0.indexOf(ele), -1);
return var0.indexOf(ele);
}
public static void main(String[] str) {
// Integer[] arr = new Integer[] { 2, 3, 3, 1, 5, 2 };
// Integer[] arr = new Integer[] { 2, 4, 3, 5, 1 };
// Integer[] arr = new Integer[] { 8, 4, 6, 2, 6, 4, 7, 9, 5, 8 };
// Integer[] arr = new Integer[]{1, 1, 2, 2, 1};
Integer[] arr = new Integer[] { 10, 6, 8, 4, 9, 1, 7, 2, 5, 3 };
System.out.println(secondIndex(arr));
}
}
Solution in Javascript
function solution(a) {
const duplicates = [];
for (const i of a) {
if (duplicates.includes(i))
return i;
else
duplicates.push(i);
}
return -1;
}
console.log(solution([2, 1, 3, 5, 3, 2])); // 3
console.log(solution([2, 2])); // 2
console.log(solution([2, 4, 3, 5, 1])); // -1
Related
I have two arrays:
list1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
list2 = [2, 4, 6, 8, 10]
How is it possible to make the output look like this?
list3 = [1, 3, 5, 7, 9]
list3[i] = list1[i] - list2[i];
Unfortunately this does not work for me because the two arrays are not same length.
import java.util.Arrays;
import java.util.Scanner;
public class Infinity {
public static int[] InitialiseStudents(int[] students) {
for (int i = 0; i<students.length; i++){
students[i] = i+1;
}
return students;
}
public static int[] AssignJobs (int[] NumberStudents) {
int StudCount = NumberStudents.length;
int[] Array = NumberStudents;
//loop for every day(t), starting at the second day
for (int t = 2; t <= StudCount; t++) {
System.out.println("Tag" + t);
int[] copy = new int[5];
for (int i = t-1, j=0; j < 5; i+=t) {
copy[j++] = Array[i];
}
System.out.println("-------------");
System.out.println(Arrays.toString(copy));
System.out.println("_________");
break;
}
return Array;
}
public static void main( String[] args) {
Scanner scan = new Scanner(System.in);
System.out.println("Enter Number of Students: ");
//int n = scan.nextInt();
int n = 10;
int[] students = new int[n];
InitialiseStudents(students);
students = AssignJobs(students);
System.out.println(Arrays.toString(students));
}
}
To make to task VERY clear I just show you everything I have done and the context. This is my homework which I am curently working. The task is...
Initially, a numbering 1, 2, 3, 4, . . . of the students is determined. Then it will be that
every second (start counting with the first student) becomes Garbage officer (these are
the students with the numbers 2, 4, 6, 8, . . . ), from the rest (students 1, 3,
5, 7, . . . ) every third person becomes a refrigerator representative (these are students 5, 11, 17,
23, . . . ), of the rest (students 1, 3, 7, 9, . . . ) every fourth . . . , from which then
we can think of something for each k-th and from the rest for
every (k+1)-th etc. Apparently, some of the residents (students 1, 3, 7)
omitted during distribution and do not have to complete any of the tasks that arise.
Numbers of these students are called Omitted Numbers.
Program an application OmittedNumbers that exactly the Omitted Numbers
an area 1; : : : ;N retrieves and prints, where N is passed on the command line
will. Only use methods that are iterative.
Solution # 1
Convert your arrays to list
List<Integer> list1 = Arrays.asList(array1);
List<Integer> list2 = Arrays.asList(array2);
For List, you can use removeAll function
list1.removeAll(list2);
System.out.println(list1)
Solution # 2
Traverse through each index and remove items if same as follow
int[] array1 = new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int[] array2 = new int[]{2, 4, 6, 8, 10};
List<Integer> result = new ArrayList<>();
for (int i = 0; i < array1.length; i++) {
for (int j = 0; j < array2.length; j++) {
if (array1[i] == array2[j]) {
result.add(array1[i]);
}
}
}
// convert list to array (if needed)
Integer[] resultArray = result.toArray(new Integer[0]);
Here's a simple implementation:
import java.util.ArrayList;
import java.util.List;
record ChoiceResult(List<Integer> chosen, List<Integer> remainder) {}
public class Choose {
static ChoiceResult choose(int interval, List<Integer> candidates) {
List<Integer> chosen = new ArrayList<>();
List<Integer> remainder = new ArrayList<>();
for (int i = 0; i < candidates.size(); i++) {
if ((i+1) % interval == 0) {
chosen.add(candidates.get(i));
} else {
remainder.add(candidates.get(i));
}
}
return new ChoiceResult(chosen, remainder);
}
public static void main(String[] args) {
List<Integer> students = List.of(1,2,3,4,5,6,7,8,9,10);
ChoiceResult garbage = choose(2, students);
ChoiceResult fridge = choose(3, garbage.remainder());
System.out.println("Garbage: " + garbage.chosen());
System.out.println("Fridge: " + fridge.chosen());
}
}
It has the feature of working with an immutable List for the input to the function.
You can use double-layer for loop filtering,The following is just a sample code, you need to think about the details(For example, how to improve the efficiency of calculation, because the efficiency of double-layer for loop is very low).
public static void main(String[] args) {
int[] arr1 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int[] arr2 = {2, 4, 6, 8, 10};
List<Integer> rt = new ArrayList<>();
for (int i = 0; i < arr1.length; i++) {
boolean flag = false;
for (int j = 0; j < arr2.length; j++) {
if(arr1[i] == arr2[j]) {
flag = true;
break;
}
}
if (flag == false) {
rt.add(arr1[i]);
}
}
System.out.println(rt);
Integer[] finalArr = rt.toArray(new Integer[rt.size()]);
for (int i = 0; i < finalArr.length; i++) {
System.out.println(finalArr[i]);
}
}
Collection framework supports union/intersection at base level and just utilize it.
import java.util.ArrayList;
import java.util.List;
public class Test {
public static void main(String[] args) {
List<Integer> list1 = new ArrayList<>(List.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
List<Integer> list2 = new ArrayList<>(List.of(2, 4, 6, 8, 10));
list1.removeAll(list2);
System.out.println(list1);
}
}
Using Stream API:
import java.util.List;
import java.util.stream.Collectors;
public class StreamTest {
public static void main(String[] args) {
List<Integer> list1 = List.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
List<Integer> list2 = List.of(2, 4, 6, 8, 10);
List<Integer> list3 = list1.stream()
.filter(i -> !list2.contains(i))
.collect(Collectors.toList());
System.out.println(list3);
}
}
collection methods reference
So what I want is this
int[][] arr=new int[2][8];
input:
1 1 3 1 5 3 7 1
5 2 4 8 3 7 5 2
output:
1 1 5 3 1 7 3 1
2 2 3 4 5 5 7 8
you can see that it is sorted by the second row in ascending order and the first row just follows,
how can I do this? help, please.
I tried doing below
Arrays.sort(arr[1]);
but I don't think it is working. It does sort the second row in ascending order but the first row is not matching the initial pair with the second row
Try this.
public static void main(String[] args) {
int[][] array = {
{1, 1, 3, 1, 5, 3, 7, 1},
{5, 2, 4, 8, 3, 7, 5, 2}
};
List<int[]> list = new AbstractList<int[]>() {
#Override
public int[] get(int index) {
return new int[] {array[1][index], array[0][index]};
}
#Override
public int[] set(int index, int[] value) {
int[] old = get(index);
array[1][index] = value[0];
array[0][index] = value[1];
return old;
}
#Override
public int size() {
return array[0].length;
}
};
Collections.sort(list, Arrays::compare);
for (int[] row : array)
System.out.println(Arrays.toString(row));
}
output:
[1, 1, 5, 3, 1, 7, 3, 1]
[2, 2, 3, 4, 5, 5, 7, 8]
Or
public static void main(String[] args) {
int[][] array = {
{1, 1, 3, 1, 5, 3, 7, 1},
{5, 2, 4, 8, 3, 7, 5, 2}
};
int[] sortedIndexes = IntStream.range(0, array[0].length)
.boxed()
.sorted(Comparator.comparing((Integer i) -> array[1][i])
.thenComparing(i -> array[0][i]))
.mapToInt(Integer::intValue)
.toArray();
int[][] output = IntStream.range(0, array.length)
.mapToObj(r -> IntStream.range(0, array[r].length)
.map(i -> array[r][sortedIndexes[i]])
.toArray())
.toArray(int[][]::new);
for (int[] r : output)
System.out.println(Arrays.toString(r));
}
It may be implemented using helper method(s) to transpose the input array, then transposed array may be sorted by column, and transposed again to restore the original rows/cols:
// create new array to store transposed
public static int[][] transpose(int[][] src) {
return transpose(src, new int[src[0].length][src.length]);
}
// use existing array to store the transposed
public static int[][] transpose(int[][] src, int[][] dst) {
for (int i = 0, n = src.length; i < n; i++) {
for (int j = 0, m = src[i].length; j < m; j++) {
dst[j][i] = src[i][j];
}
}
return dst;
}
Method sortByColumn (reusing the input array):
public static void sortByColumn(int[][] arr, Comparator<int[]> comparator) {
int[][] toSort = transpose(arr);
Arrays.sort(toSort, comparator);
transpose(toSort, arr);
}
Test:
int[][] arr = {
{7, 1, 3, 1, 5, 3, 1, 4, 4},
{5, 2, 4, 8, 3, 7, 5, 2, 5}
};
sortByColumn(arr, Comparator.comparingInt(col -> col[1]));
for (int[] row : arr) {
System.out.println(Arrays.toString(row));
}
Output:
in the first row values appear in the insertion order after sorting by the second element in each column.
[1, 4, 5, 3, 7, 1, 4, 3, 1]
[2, 2, 3, 4, 5, 5, 5, 7, 8]
Square arrays (width == height) may be transposed more efficiently without creating additional array:
public static int[][] transposeSquare(int[][] arr) {
for (int i = 0, n = arr.length; i < n; i++) {
// select the elements only above the main diagonal
for (int j = i + 1, m = arr[i].length; j < m; j++) {
int tmp = arr[i][j];
arr[i][j] = arr[j][i];
arr[j][i] = tmp;
}
}
return arr;
}
So I came across this problem in Java that wants to remove a list of number that has occurred more than twice but keeping the order, and the first two occurrences.
For example, if the list is 2, 3, 5, 4, 5, 2, 4, 3, 5, 2, 4, 4, 2, 10
the expected output would be 2, 3, 5, 4, 5, 2, 4, 3, 10
I've tried several methods, including using a counter int to keep track of the occurrences and filter it out, but I am not sure how I can go about it
class DeDup {
// function to find the element occurring more than 3 times
static void get2Occurrences(int arr[]) {
int i;
int count = 0;
for (i = 0; i < arr.length; i++) {
for (int j = 0; j < arr.length; j++) {
if (arr[i] == arr[j])
count++;
}
if (count < 3 && count > 0) {
//return arr[i];
System.out.print(arr[i] + ", ");
} else {
for (int k = 2; k > 0; k--) {
System.out.print(arr[i] + ", ");
}
}
}
}
// driver code
public static void main(String[]args) {
int arr[] = new int[]{ 2, 3, 5, 4, 5, 2, 4, 3, 5, 2, 4, 4, 2, 10 };
//expected output: 2, 3, 5, 4, 5, 2, 4, 3, 10
//int n = arr.length;
get2Occurrences(arr);
}
}
the expected output would be 2, 3, 5, 4, 5, 2, 4, 3, 10
but i got 2, 2, 3, 3, 5, 5, 4, 4, 5, 5, 2, 2, 4, 4, 3, 3, 5, 5, 2, 2, 4, 4, 4, 4, 2, 2, 10, 10,
I would do it using a pair of Sets: Set.add returns a boolean indicating whether the element was added. Hence:
boolean b = set1.add(num) || set2.add(num);
will be true if it was added into either set - and it will only try to add it to set2 if it was already in set1 - and false otherwise, meaning it was present in both sets already.
Set<Integer> set1 = new HashSet<>();
Set<Integer> set2 = new HashSet<>();
for (Integer a : arr) {
if (set1.add(a) || set2.add(a)) {
System.out.print(a + ", ");
}
}
Ideone demo
Keep track of the number of occurrences found for each element.
Something like this:
static void get2Occurrences(int arr[])
{
// Initialize occurrences found
Hashtable<Integer, Integer> found_elms = new Hashtable<Integer, Integer>();
// Loop over all elements
int counter;
int number;
Integer found;
for (counter = 0; counter < arr.length; counter++)
{
number = arr[counter];
found = found_elms.get(number);
if (found == null)
found = 1;
else
found = found + 1;
found_elms.put(number, found);
if (found < 3)
System.out.print(number + ", ");
}
System.out.println();
} // get2Occurrences
In this solution, you can change the number of repetitions from three to another.
int[] arr = new int[]{2, 3, 5, 4, 5, 2, 4, 3, 5, 2, 4, 4, 2, 10};
Map<Integer, Integer> counting = new HashMap<>();
for (Integer current : arr) {
int count = counting.compute(current, (x, n) -> n == null ? 1 : n + 1);
if (count < 3) {
System.out.print(current + ", ");
}
}
I would propose an insert filter : go through each element with a for loop and insert it into a response array if the response arrays doesnt contain it 2 times yet
import java.util.ArrayList;
import java.util.List;
...
List<Integer> lst = new ArrayList<>();
for (int i : arr) {
if (lst.lastIndexOf(i) == lst.indexOf(i)) {
lst.add(i);
}
}
return lst.stream().mapToInt(i -> i).toArray();
So this is what I came up with in the end
import java.util.ArrayList;
import java.util.Arrays;
class DeDup {
// function to find the element occurring more than 3 times
static void get2Occurrences(ArrayList<Integer> arr)
{
for(int i=0; i<arr.size(); i++){
int count=0;
for(int j=0; j<i; j++){
if(arr.get(j)==arr.get(i)){
count++;
}
}
if (count>=2){
arr.remove(i);
i--;
}
}
System.out.println("Output: "+arr);;
}
// driver code
public static void main(String[] args)
{
ArrayList<Integer> arr = new ArrayList<Integer>(Arrays.asList( 2, 3, 5, 4, 5, 2, 4, 3, 5, 2, 4, 4, 2, 10));
//expected output: 2, 3, 5, 4, 5, 2, 4, 3, 10
//int n = arr.length;
System.out.println("Input: "+arr);
get2Occurrences(arr);
}
}
Solution using Iteartor:
List<Integer> array = Lists.newArrayList(2, 3, 5, 4, 5, 2, 4, 3, 5, 2, 4, 4, 2, 10);
Map<Integer, Integer> control = new HashMap<>();
Iterator<Integer> iterator = array.iterator();
while(iterator.hasNext()) {
Integer element = iterator.next();
Integer occurrences = control.getOrDefault(element, 0);
if (occurrences >= 2) {
iterator.remove();
} else {
control.put(element, occurrences + 1);
}
}
I am trying to write a recursive function to produce all permutations of an array.
static int permus[] = new int[] { 1, 2, 3, 4, 5 };
static void testPermu(int start)
{
// Print it
System.out.println(Arrays.toString(permus));
int k;
for (int i = start + 1; i < permus.length; i++) {
// swap
k = permus[start];
permus[start] = permus[i];
permus[i] = k;
testPermu(i);
// unswap
k = permus[start];
permus[start] = permus[i];
permus[i] = k;
}
}
It's invoked as testPermu(0) and should produce all permutations, however that does not work. How can I fix it?
It needs to be recursive, each time the function is invoked, it should get a fresh permutation.
output now is
[1, 2, 3, 4, 5]
[2, 1, 3, 4, 5]
[2, 3, 1, 4, 5]
[2, 3, 4, 1, 5]
[2, 3, 4, 5, 1]
[2, 3, 5, 4, 1]
[2, 4, 3, 1, 5]
[2, 4, 3, 5, 1]
[2, 5, 3, 4, 1]
[3, 2, 1, 4, 5]
[3, 2, 4, 1, 5]
[3, 2, 4, 5, 1]
[3, 2, 5, 4, 1]
[4, 2, 3, 1, 5]
[4, 2, 3, 5, 1]
[5, 2, 3, 4, 1]
You can see that many of the permutations are missing.
I'm writing it in Java but I'll understand example in C, javascript or anything else as long as it's not using some library tricks not available in Java.
Three corrections are needed in order to work:
print only if (start == permus.length-1), otherwise you'll see duplicates
start the for loop from i = start, not i = start + 1
recursively call testPermu(start + 1); instead of testPermu(i);
Here is a full example:
package eric.math;
import java.util.Arrays;
public class Permute {
// swap 2 elements of an array,
void swap(int[] arr, int x, int y) {
int temp = arr[x];
arr[x] = arr[y];
arr[y] = temp;
}
/**
* print permutations of array
* #param arr
* original int array,
*/
void permute(int[] arr) {
permute(arr, 0, arr.length - 1);
}
/**
* print permutations of array
*
* #param arr
* original int array,
* #param i
* start index
* #param n
* end index
*/
void permute(int[] arr, int i, int n) {
int j;
if (i == n)
System.out.println(Arrays.toString(arr));
else {
for (j = i; j <= n; j++) {
swap(arr, i, j);
permute(arr, i + 1, n);
swap(arr, i, j); // backtrack
}
}
}
public static void main(String[] args) {
int arr[] = { 1, 2, 3 };
new Permute().permute(arr);
}
}
#Enric solution is nice, but using solution below we can avoid 80 swaps and perform only 24 swaps.
static void permutation(int[] a, int i, int j) {
for (; j < a.length && i < a.length; j++) {
int[] temp = null;
if (i != j) {
temp = swap(a, i, j);
System.out.println(Arrays.toString(temp));
}else{
temp = a;
}
permutation(temp, i + 1, i + 1);
}
}
public static void main(String[] args) {
int[] a = { 0, 1, 2, 3 };
permutation(a, 0, 0);
}
Another approach:
static ArrayList<ArrayList<Integer>> getPermutation(ArrayList<Integer> ints) {
if (ints.size() == 1) {
ArrayList<ArrayList<Integer>> list = new ArrayList<>();
list.add(ints);
return list;
} else {
ArrayList<ArrayList<Integer>> list = new ArrayList<>();
for (Integer i: ints) {
ArrayList<Integer> subList = new ArrayList<>(ints);
subList.remove(i);
ArrayList<ArrayList<Integer>> subListNew = getPermutation(subList);
for (ArrayList<Integer> _list: subListNew) {
ArrayList<Integer> local = new ArrayList<>();
local.add(i);
local.addAll(_list);
list.add(local);
}
}
return list;
}
}
This method first selects an element, removes it and obtains a sub-list, then produces a permutation of the sub-list until the list size becomes 1.
I like #tony200910041 approach but maybe someone would like a cleaner and more generic version of it:
public static <T> List<List<T>> getPermutations(List<T> list) {
if (list.size() == 1)
return Collections.singletonList(list);
List<List<T>> perms = new ArrayList<>();
for (T element: list) {
List<T> subList = new ArrayList<>(list);
subList.remove(element);
List<List<T>> subPerms = getPermutations(subList);
for (List<T> subPerm: subPerms) {
List<T> perm = new ArrayList<>();
perm.add(element);
perm.addAll(subPerm);
perms.add(perm);
}
}
return perms;
}
Sort the list before passing it to the getPermutations() function if you want your permutations in ascending order.
Try with
testPermu(start + 1);
You can do it simply without recursion
public static Integer[] permutate(int i)
{
int length = permus.length;
Integer[] result = new Integer[length];
List<Integer> chosen = new ArrayList<Integer>(Arrays.asList(permus));
int divider = 1;
for (int j=2; j<length; j++)
{
divider *= j;
}
for (int j=length; j>1; j--)
{
int index = i/divider;
result[length - j] = chosen.remove(index);
i = i - divider * (i/divider);
divider = divider / (j-1);
}
result[length -1] = chosen.remove(0);
return result;
}
How about the following algorithm (given in pseudocode)
iterate over elements:
pick one of the element at random
call function again on the remaining elements
if elements.size == 1
return or print
This should produce a valid permutation at each run. If you want all possible permutations, just accumulate as you iterate, then you should have all permutations.
I have a 2D array with 2 rows and n columns.
I am trying to sort the array using the built in Arrays.sort method, but I am struggling with the comparator. I want to sort the 2D array by the first row, so that the 2nd row elements will remain with the original elements they were aligned with ie. keep the columns together.
For example original array:
int[] unsortedArray = new int[][]{
{ 6, 3, 1, 2, 3, 0},
{ 2, 1, 6, 6, 2, 4},
sorted array:
int[] unsortedArray = new int[][]{
{ 0, 1, 2, 3, 3, 6},
{ 4, 6, 6, 1, 2, 2},
What is the best way to go about doing this?
Cheers.
Here is an alternative way of keeping your columns aligned. This uses a simple class to hold both column elements.
class TwoInts {
public final int aElement;
public final int bElement;
public TwoInts(int a_element, int b_element) {
aElement = a_element;
bElement = b_element;
}
}
One by one, each column (from sub-array one and two) are placed in this object, and immediately put into a Map<Integer,List<TwoInts>>. The key is the element from intArrayArray[0], and the value is a list of TwoInts, because there may be (and in your example code, are) duplicate values in intArrayArray[0].
You then iterate through the map's key-set, and replace them into the array.
Full code:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
/**
<P>{#code java SortOneArrayKeepSecondArrayElementsAligned}</P>
**/
public class SortOneArrayKeepSecondArrayElementsAligned {
public static final void main(String[] ignored) {
int[][] intArrayArray = new int[][]{
{ 6, 3, 1, 2, 3, 0},
{ 2, 1, 6, 6, 2, 4}};
output2DArray("Unsorted", intArrayArray);
Map<Integer,List<TwoInts>> twoIntMap = new TreeMap<Integer,List<TwoInts>>();
for(int i = 0; i < intArrayArray[0].length; i++) {
int intIn0 = intArrayArray[0][i];
if(!twoIntMap.containsKey(intIn0)) {
List<TwoInts> twoIntList = new ArrayList<TwoInts>(intArrayArray.length);
twoIntList.add(new TwoInts(intArrayArray[0][i], intArrayArray[1][i]));
twoIntMap.put(intIn0, twoIntList);
} else {
twoIntMap.get(intIn0).add(new TwoInts(intArrayArray[0][i], intArrayArray[1][i]));
}
}
int idx = 0;
Iterator<Integer> itr2i = twoIntMap.keySet().iterator();
while(itr2i.hasNext()) {
List<TwoInts> twoIntList = twoIntMap.get(itr2i.next());
for(TwoInts twoi : twoIntList) {
intArrayArray[0][idx] = twoi.aElement;
intArrayArray[1][idx++] = twoi.bElement;
}
}
output2DArray("Sorted", intArrayArray);
}
private static final void output2DArray(String description, int[][] twoD_array) {
System.out.println(description + ":");
System.out.println("0: " + Arrays.toString(twoD_array[0]));
System.out.println("1: " + Arrays.toString(twoD_array[1]));
System.out.println();
}
}
class TwoInts {
public final int aElement;
public final int bElement;
public TwoInts(int a_element, int b_element) {
aElement = a_element;
bElement = b_element;
}
}
Output:
[C:\java_code\]java SortOneArrayKeepSecondArrayElementsAligned
Unsorted:
0: [6, 3, 1, 2, 3, 0]
1: [2, 1, 6, 6, 2, 4]
Sorted:
0: [0, 1, 2, 3, 3, 6]
1: [4, 6, 6, 1, 2, 2]
Try the following:
Disclaimer: Not tested :)
myarray = new int[10][2];
// populate the array here
Arrays.sort(myarray, new Comparator<int[]>() {
public int compare(int[] a, int[] b) {
if (a[0] > b[0])
return 1;
else if (a[0] < b[0])
return -1;
else {
return 0;
}
}
};
You will have to write a custom sort. Look into Comparable and Comparator.
Something along the lines of:
public class MyComparator implements Comparator<T[]> {
int columnToSortOn;
public MyComparator(int columnToSortOn) {
this.columnToSortOn = columnToSortOn;
}
#Override
public int compare(T[] array1, T[] array2) {
return array1[columnToSortOn].compareTo(array2[columnToSortOn]);
}
}