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);
Related
To begin, I am doing this using only arrays (no hash maps or array lists).
I am trying to create a method, project, which inputs two integer arrays with different sizes.
I am trying to compare them in a way to get the following output: projecting [1, 3, 5, 3] to [2, 1, 6, 3, 1, 4, 5, 3] results in: [1, 3, 1, 5, 3].
However, projecting [2, 1, 6, 3, 1, 4, 5, 3] to [1, 3, 5, 3] results in: [1, 3, 5, 3].
I believe the nested for loop might be wrong as it is iterating through the first indices for the first array all the way through the second array, then going to the next.
I'm getting an ArrayIndexOutOfBoundsException for the starred line (tempArray[i] == arr1[i], I know it shouldn't be tempArray[i] but not sure what exactly to put).
I'm not sure how to compare them in a way to produce the line above, as it needs to be "in order". What could be the best way to accomplish this?
I attempted the following code:
public int[] project(int[] arr1, int[] arr2) {
int counter = 0;
for (int i = 0; i < arr1.length; i++) {
for (int j = 0; j < arr2.length; j++) {
if (arr1[i] == arr2[j]) {
counter++;
}
}
}
int[] tempArray = new int[counter];
for(int i = 0 ; i < arr1.length; i++) {
for (int j = 0; j < arr2.length; j++) {
if(arr1[i] == arr2[j]) {
tempArray[i] = arr1[i]; // UNDERLINED
}
}
}
}
Edit
The ArrayIndexOutOfBounds error is gone, but now my return statement is: projecting [1, 3, 5] to [2, 1, 6, 3, 1, 4, 5, 3] results in: [1, 3, 5, 0, 0], when it needs to be: projecting [1, 3, 5] to [2, 1, 6, 3, 1, 4, 5, 3] results in: [1, 3, 1, 5, 3].
Any idea what is causing this issue?
I think you have a typo in your first for loop
change this to later
arr1[i] == arr2[i]
to
arr1[i] == arr2[j]
Regarding overlapping issues in the projection array, you need to maintain different value as your index rather than i or j which is used by arr1 and arr2 respectively
int[] tempArray = new int[counter];
int index = 0;
for(int i=0 ; i < arr1.length; i++) {
for (int j=0; j < arr2.length; j++) {
if(arr1[i] == arr2[j]) {
tempArray[index++] = arr1[i];
}
}
}
For the values which you are expecting you should loop through arr2 first
for(int j=0 ; j < arr2.length; j++) {
for (int i=0; i < arr1.length; i++) {
if(arr1[i] == arr2[j]) {
tempArray[index++] = arr1[i];
}
}
}
If the contents of array are not hardcoded and you dont know the order in which you want to pass, you can make use of length
int[] ans;
if(a.length < b.length) {
ans = project(a, b);
} else {
ans = project(b, a);
}
Output:
[1, 3, 1, 5, 3]
You currently have index variables (i, j) tracking the indexes of each input array as you loop through them, but you also need to keep track of the write head of the result array. Initialize, say int k = 0 before the outer for loop, then set the value like this: tempArray[k++] = array1[i];.
You can forgo the first loop If you are OK with performing a single array copy. Initialize an array as long as the second input array (since there can never be more duplicated elements than existing elements) as the tempArray. Then if you want it to fit exactly, initialize the final array to the exact length k and use System#arrayCopy.
this will probably solve your problem
public int[] project(int[] arr1, int[] arr2) {
int counter = 0;
for (int i : arr2) {
if (Arrays.binarySearch(arr1, i) >= 0) {
counter++;
}
}
int[] arr4 = new int[counter];
int index = 0;
for (int i : arr2) {
if (Arrays.binarySearch(arr1, i) >= 0) {
arr4[index++] = i;
}
}
return arr4;
}
The nested iteration is expensive, so we want to avoid that. The first thing to do is sort the array we are projecting from so we can perform a binary search on it. Second, don't execute the nested iteration to determine the output array size. Create an array the size of the array we are projecting to since it can be no longer than that.
public int[] projection(int[] a, int[] b) {
int[] temp = new int[b.length];
int nextIndex = 0;
for (int x : b) {
if (contains(a, x)) {
temp[nextIndex++] = x;
}
}
return slice(temp, nextIndex);
}
private boolean contains(int[] array, int value) {
for (int element : array) {
if (element == value) {
return true;
}
}
return false;
}
private int[] slice(int[] src, int size) {
int[] slice = new int[size];
for (int index = 0 ; index < size ; ++index) {
slice[index] = src[index];
}
return slice;
}
For your second problem, I think, in your temporary array, you should be saving the values from arr2[j] instead of arr1[i].
Also, you need a different counter (set to 0 initially and incremented in the loop) for setting the values in tempArray[counter].
What I mean exactly is:
int counter = 0;
for (int i = 0; i < arr1.length; i++) {
for (int j = 0; j < arr2.length; j++) {
if (arr1[i] == arr2[j]) {
tempArray[counter] = arr2[j];
counter++;
}
}
}
This question already has answers here:
What is the difference between Linear search and Binary search?
(11 answers)
Closed 2 years ago.
Given an array of elements of length N, ranging from 0 to N – 1. All elements may not be present in the array. If element is not present then there will be -1 present in the array. Rearrange the array such that A[i] = i and if i is not present, display -1 at that place
So that is the question, but my binarySearch is not working, why?
for(int i = 0; i < size; i++) {
int res = i;
// System.out.println(Arrays.binarySearch(arr,res));
int result = Arrays.binarySearch(arr,res);
if(result == -1)
arr[i] = -1;
else {
arr[i] = i;
}
}
for(int i = 0; i < size; i++) {
System.out.print(arr[i]+" ");
}
Binary search works only with sorted arrays. Try using a different search algorithm
If you can use additional array, the solution may be as follows:
Create resulting array
Fill resulting array with -1
Iterate over input array and fill appropriate numbers in the resulting array.
// input array
int[] arr = {-1, 2, 3, 0};
// prepare new resulting array
int[] res = new int[arr.length];
// fill with -1
// Arrays.fill(res, -1); // use this shortcut if you're allowed to use library
for (int i = 0; i < res.length; i++) {
res[i] = -1;
}
// rearrange
for (int i = 0; i < arr.length; i++) {
if (arr[i] != -1) {
res[arr[i]] = arr[i];
}
}
System.out.println("input data: " + Arrays.toString(arr));
System.out.println("rearranged: " + Arrays.toString(res));
Output:
input data: [-1, 2, 3, 0]
rearranged: [0, -1, 2, 3]
Update
Recursive solution without using extra array:
public static void test() {
int[] arr = {-1, 4, 2, 0, 1, 3};
System.out.println("input data: " + Arrays.toString(arr));
// rearrange
for (int i = 0; i < arr.length; i++) {
if (arr[i] != -1 && arr[i] != i) {
swapAtIndex(arr, i);
}
}
System.out.println("rearranged: " + Arrays.toString(arr));
}
private static void swapAtIndex(int[] arr, int i) {
int t = arr[i];
if (t != -1 && t != i) {
int t2 = arr[t];
arr[t] = t;
arr[i] = t2;
if (t2 != -1) {
swapAtIndex(arr, i); // continue swapping at the same index
}
}
}
output:
input data: [-1, 4, 2, 0, 1, 3]
rearranged: [0, 1, 2, 3, 4, -1]
For the input array without -1, you'll get a sorted array after rearrangement:
input data: [5, 4, 2, 0, 1, 3]
rearranged: [0, 1, 2, 3, 4, 5]
This is a pretty beginner assignment, and I would love to get some help with my code.
I need to combine two integer arrays into one using for loops, and make sure I don't have duplicates. Anything I googled is pretty over complicated and uses all sorts of built in methods.
Here is my code:
static void SumArray(){
int[] array1 = { 1, 2, 3 };
int[] array2 = { 3, 4, 5 };
int[] merged = new int[array1.length + array2.length];
int pos = 0;
for (int i = 0; i < array1.length; i++) {
merged[pos] = array1[i];
pos++;
}
for (int j = merged[pos]; j < array2.length; j++) {
if (merged[pos] != array2[j]) {
merged[pos] = array2[j];
pos++;
}
}
System.out.println(Arrays.toString(merged));
Ultimately, it should return {1, 2, 3, 4, 5}. Instead, currently it returns 1, 2, 3, 3, 4, 5.
I would like to know why my if doesn't work. It should skip the 3 since it is already in there.
What am I missing?
Thanks :)
Edit:
Thanks guys, this is what I ended up doing, which still isn't good since I'm not checking for duplicates in the first loop that goes over the first array:
static void SumArray(){
int[] array1 = { 1, 2, 3 };
int[] array2 = { 3, 4, 5 };
int arrSize = array1.length + array2.length;
int[] merged = new int[arrSize];
int pos = 0;
int counter = 0;
for (int i = 0; i < array1.length; i++) {
merged[pos] = array1[i];
pos++;
}
for (int j = merged[pos]; j < array2.length; j++) {
if (merged[pos-1] != array2[j]) {
merged[pos] = array2[j];
pos++;
counter++;
}
}
int[] newMerged = new int[arrSize - counter + 1];
System.arraycopy(merged, 0, newMerged, 0, newMerged.length);
System.out.println(Arrays.toString(newMerged));
}
I'm sure I'll find a way.
I would like to know why my if doesn't work.
Because merged[pos] is always 0, because you've never assigned any other value to it in your code. Array entries are initialized to zero when you create the array.
You can't just check one entry to know whether to add a value from array2. You have to check all of the entries you've written, with a nested loop within your second for loop. Only add a new entry if it isn't already there.
Note that you'll also need to either check ahead of time how many duplicates there are so you know that merged should only be 5 entries long, or you need to re-create merged later when you know how long it should be. Otherwise, your end result will be {1, 2, 3, 4, 5, 0}, not {1, 2, 3, 4, 5}.
because of the "pos++" in the first for loop as you are using as start index of j in the second loop.
Your 3 is in the index 2 and you are comparing it to index 3, which never be equal
here is your answer:
int[] array1 = { 1, 2, 3 };
int[] array2 = { 3, 4, 5 };
int[] merged = new int[array1.length + array2.length];
int pos = 0,i=0, j;
Set<Integer> intSet = new HashSet();
for (i = 0; i < array1.length; i++) {
if(!intSet.contains(array1[i])) {
merged[pos] = array1[i];
intSet.add(Integer.valueOf(i));
pos++;
}
}
for (j= 0, pos = pos-1; j < array2.length; ) {
if(!intSet.contains(Integer.valueOf(array2[j]))) {
merged[pos] = array2[j];
intSet.add(Integer.valueOf(i));
pos++;
j++;
}
}
System.out.println(Arrays.toString(merged));
Here is solution for Java 8 and bigger version:
int[] first = { 1, 2, 3 };
int[] second = { 3, 4, 5 };
int[] merged = Stream.of(first, second)
.flatMapToInt(Arrays::stream)
.distinct()
.toArray();
How do you count the number of numbers that occur in only one of the two arrays?
Example: countdifference([2, 4, 4, 4, 4, 6, 6, 8], [3, 4, 6, 6, 9]) returns 4 because 4 and 6 are duplicates, remaining numbers are 2, 8, 3 and 9.
noOfRepeatsCount method is intended to account for repeated elements in arrayB: i.e. 6
I am getting an index array out of bounds exception: -1 for the noOfRepeatsCount method. Any ideas why?
public class countNonRepeated {
static int countDifference(int[] arrayA, int[] arrayB) {
int count = 0, repeatCount = 0, noOfRepeatsCount = 0;
/*
int noOfRepeats = 0;
for (int k = 0; k < arrayB.length; k++) {
if (arrayB[k] == arrayB[k - 1]) {
noOfRepeats++;
} else {
continue;
}
*/
for (int i = 0; i < arrayA.length; i++) {
for (int j = 0; j < arrayB.length; j++) {
if (arrayA[i] == arrayB[j]) {
if (arrayA[i + 1] == arrayB[j]) {
repeatCount++;
} else {
count++;
}
} else {
continue;
}
}
}
int length = arrayA.length + arrayB.length;
return length - (noOfRepeatsCount * repeatCount) - (count * 2);
}
static int noOfRepeatsCount(int[] arrayB) {
int noOfRepeats = 0;
for (int k = 0; k < arrayB.length; k++) {
if (arrayB[k] == arrayB[k - 1]) {
noOfRepeats++;
} else {
continue;
}
}
return noOfRepeats;
}
public static void main(String args[]) {
int arrayA[] = { 2, 4, 4, 4, 4, 6, 6, 8 };
int arrayB[] = { 3, 4, 6, 6, 9 };
// System.out.println(noOfRepeatsCount(arrayA));
System.out.println(countDifference(arrayA, arrayB));
}
}
See the for loop in noOfRepeatsCount method. if (arrayB[k] == arrayB[k - 1]) makes exception error. Because initial k value is 0, you access arrayB[-1].
If you want to solve this problem, change for (int k = 0; k < arrayB.length; k++) to for (int k = 1; k < arrayB.length; k++).
What about converting the arrays to Sets and using a combination of removeAll(), addAll() and size() to get the desired result. I guess that this would make the algorithm clearer and avoid off-by-one errors.
I have no time right now to post a code sample, sorry.
My following code does the randomization of an array, however, I am wondering if I want to group first two or three elements together always, how should I proceed?
ArrayList<Integer> numbers = new ArrayList<Integer>();
for(int i=1;i<=11;i++)
{
numbers.add(i);
}
Collections.shuffle(numbers);
for (Integer nums : numbers)
System.out.println(nums);
Example Output: 5, 7, 4, 11, 2, 3, 1, 9, 6, 8, 10
(Note that the sequence '1,2,3' is randomized within the main array.)
Something like this maybe:
final int[] array = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
final int iterations = 10;
final int groupOf = 3;
for (int i = 0; i < array.length; i += groupOf) {
int groupOfRemainder = array.length - i < groupOf ? array.length - i : groupOf;
for (int j = 0; j < iterations; j++) {
int rnd1 = Math.random() * groupOfRemainder;
int rnd2 = Math.random() * groupOfRemainder;
Object temp = array[i + rnd1];
array[i + rnd1] = array[i + rnd2];
array[i + rnd2] = temp;
}
}
public static void shuffleKeepingFirstRTogether(List<Integer> list, int r) {
int size = list.size();
Collections.shuffle(list.subList(0, r));
Collections.shuffle(list.subList(r, size));
Collections.rotate(list, new Random().nextInt(size - r));
}