given an Array List with the values [10, 13, 2, 8, 7, 90, -1, 2]. I have to create a method that will reverse each successive sequence of 3 values within said list. For example (10, 13, 2) will become (2,13 10) and the (8, 7, 90) will become (90,7,8) However, it will not print out numbers that aren't part of a sequence of 3. So far this is what I have:
public static ArrayList<Integer> reverse3(ArrayList<Integer> list) {
ArrayList<Integer> newList = new ArrayList<Integer>();
for(int i = 0; i <list.size()-1; i++){
for(int j = list.size()-1; j >= 0 ; j--){
newList.add(list.get(j));
}
}
return newList;
I'm having issues getting this to work properly. The output reverses the sequences of three but -1 and 2 are printed as well.
It sounds like all you really need to do is to swap 1 and 3, 2 and 4 etc. So:
for (int i = 0; i < list.size(); i += 3) {
Collections.swap(list, i, i + 2);
for (int j = i; j < i + 3; j++)
System.out.println(list.get(j) + " ");
}
Or you could just print them out without even swapping the items:
for (int i = 0; i < list.size(); i += 3) {
for (int j = i + 2; j >= i; j--)
System.out.println(list.get(j) + " ");
}
And here's a solution using sublist and Java 8 streams:
IntStream.range(0, list.size() / 3)
.mapToObj(n -> list.sublist(n, n + 3))
.map(Collections::reverse)
.flatMap(List::stream)
.forEach(System.out::println);
Since it looks like it's "do my homework for free" day today,
for extra credit, write it in scala:
list
.grouped(3)
.map(_.reverse)
.flatten
.toList
Something like that should do it:
for( int i = 1; i < list.size()-1; i+=3 ) {
int tmp = list.get(i+1);
list.set(i+1, list.get(i-1));
list.set(i-1, tmp);
}
This is the code you need:
public static ArrayList<Integer> reverse3(List<Integer> list) {
ArrayList<Integer> newList = new ArrayList<Integer>();
for (int i = 0; i < list.size(); i+=3) {
for (int j = i+2; j >= i && j < list.size(); j--) {
newList.add(list.get(j));
}
}
return newList;
}
This is a demo:
public static void main(String[] args) {
List<Integer> list = Arrays.asList(10, 13, 2, 8, 7, 90, -1, 2);
System.out.println(list);
System.out.println(reverse3(list));
}
Input: [10, 13, 2, 8, 7, 90, -1, 2]
Results: [2, 13, 10, 90, 7, 8]
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++;
}
}
}
I'm making a program that arranges an array by moving the largest value to the end but for some reason, the program isn't arranging the values menually.
How can I fix that?
public static void main(String args[]) {
ArrayList<Integer> list = new ArrayList<>();
list.add(15);
list.add(78);
list.add(44);
list.add(99);
list.add(32);
int num = 1;
for(int i = 0; i<=list.size() -1;){
if(list.get(i) > list.get(i+1)){
list.add(list.get(i));
list.remove(i);
System.out.println(list);
}
else{
i+=1;
num+=1;
}
}
}
and this what I'm getting:
[15, 44, 99, 32, 78]
[15, 44, 32, 78, 99]
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index 5 out of bounds for length 5
at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:64)
at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:70)
at java.base/jdk.internal.util.Preconditions.checkIndex(Preconditions.java:248)
at java.base/java.util.Objects.checkIndex(Objects.java:372)
at java.base/java.util.ArrayList.get(ArrayList.java:458)
at MyClass.main(MyClass.java:10)
This works:
public static void main(String args[]) {
ArrayList<Integer> list = new ArrayList<>();
list.add(15);
list.add(78);
list.add(44);
list.add(99);
list.add(32);
for(int i = 0; i < list.size() - 1; i++){
for(int j = 0; j < list.size() - i - 1; j++){
if(list.get(j) > list.get(j + 1)){
int temp = list.get(j);
list.set(j, list.get(j + 1));
list.set(j + 1, temp);
}
}
}
System.out.println(list);
}
First off, it's usually a bad idea to add and/or remove items to a list while looping over it. You are lucky it's working here, because you are adding and removing the same number of items, but it would be better to swap the items at the i and last positions:
int last = list.get(list.size() - 1);
list.set(list.size() - 1) = list.get(i);
list.set(i) = last;
But to your problem: The index of your loop (i) goes from 0 to 4. In the last loop, when you try to list.get(i+1) you attempt to get index 4+1 = 5, but the list only has size of 5, so there is no index 5.
In your case you need to loop to only until the second last index, not the last:
for(int i = 0; i<=list.size() - 2;){
// Change from 1 to 2 ----^
Below code like is the reason for IndexOutOfBoundsException. when i = 4, i + 1 = 5 and no index matching in the List.
if(list.get(i) > list.get(i+1)){
If you want to try the bubble sort you could try below
for (int i = list.size() - 1; i >= 0; i--)
for (int j = 0; j < i; j++) {
if (list.get(j) > list.get(j + 1)) {
int temp = list.get(j);
list.set(j, list.get(j + 1));
list.set(j + 1, temp);
}
}
System.out.println(list);
If your intention is to sort without your own code, you could use
Collections.sort(list);
If you wanna sort manually then this code works :
while ( i < list.size()-1) {
if(list.get(i) > list.get(i+1)){
list.add(list.get(i));
list.remove(i);
i--;
} else {
i++;
}
}
But for efficiency I would suggest you to use :
Collections.sort(list);
How would I rearrange the elements of a given array of integers in place so that the elements of every maximal strictly ascending subarray are reversed?
For example, given the array { 5, 7, 10, 4, 2, 7, 8, 1, 3 }, after executing this method, the elements of the array would be { 10, 7, 5, 4, 8, 7, 2, 3, 1 }.
My attempt only sorts the integers in descending order. How can I make these nested loops identify the maximal strictly ascending subarrays? I believe the outer loop should have to repeatedly find the end of the current ascending sequence, while the inner loop reverses the subarray up to that point.
public class MyClass {
public static void main(String args[]) {
int[] arr = {5, 7, 10, 4, 2, 7, 8, 1, 3};
for (int i=0; i<arr.length-1; i++) {
if (arr[i] < arr[i+1]) {
int t = arr[i+1];
arr[i+1] = arr[i];
arr[i] = t;
}
for (int j=0; j<arr.length-1; j++) {
if (arr[j] < arr[j+1]) {
int t = arr[j+1];
arr[j+1] = arr[j];
arr[j] = t;
}
}
}
String result = Arrays.toString(arr);
System.out.println(result); // [10, 8, 7, 7, 5, 4, 3, 2, 1]
}
}
I see why you are using nested loop. But I think you'll need to keep track of start and end instead of just swapping. Here's how I solved it using a stack:
public static void main(String[] args) {
System.out.println(Arrays.toString(reverseAscendingSubArray(new int[]{5, 7, 10, 4, 2, 7, 8, 1, 3})));
}
private static int[] reverseAscendingSubArray(int[] arr) {
Stack<Integer> stack = new Stack<>();
int[] result = new int[arr.length];
for (int i = 0; i < arr.length; i++) {
if (i == 0 || arr[i - 1] < arr[i]) {
stack.push(arr[i]);
} else {
for (int j = stack.size(); j > 0; j--) {
result[i - j] = stack.pop();
}
stack.push(arr[i]);
}
}
if (!stack.empty()) {
for (int j = stack.size(); j > 0; j--) {
result[arr.length - j] = stack.pop();
}
}
return result;
}
Output
[10, 7, 5, 4, 8, 7, 2, 3, 1]
Explanation
I keep pushing elements into the stack until the current element is greater than the previous one. As soon as I get something smaller than the previous, I pop all elements from the stack and write them to a new array. This pushing and popping will reverse the elements.
You can try using bubble sort as in the code below.
public static void reverseAscendingSubarrays(int[] items){
int start = -1;
int stop = -1;
for (int i = 0; i < items.length; i++){
if (i != items.length - 1){
if (items[i] <= items[i + 1]){
if (start == -1) {
start = i;
}
}
else {
if (start != -1) {
stop = i;
}
}
}
else{
if (start != -1){
stop = i;
}
}
if (start != -1 && stop != -1){
//sort array from start to stop (uses bubble sort - inefficient for large arrays)
for (int n = 0; n < stop - start + 1; n++)
for (int j = start; j < stop; j++){
if (items[j] < items[j+1]){
//swap
int temp = items[j];
items[j] =items[j+1];
items[j+1] = temp;
}
}
start = -1;
stop = -1;
}
}
}
Need assistance with programming issue.
Must be in Java. Cannot use any libraries (Arraylist, etc.).
int[] a = {1, 2, 3, 4, 8, 5, 7, 9, 6, 0}
int[] b = {0, 2, 11, 12, 5, 6, 8}
Have to create an object referencing these two arrays in a method that merges them together, removes duplicates, and sorts them.
Here's my sort so far. Having difficulty combining two arrays and removing duplicates though.
int lastPos;
int index;
int temp;
for(lastPos = a.length - 1; lastPos >= 0; lastPos--) {
for(index = 0; index <= lastPos - 1; index++) {
if(a[index] > a[index+1]) {
temp = a[index];
a[index] = a[index+1];
a[index+1] = temp;
}
}
}
a method that merges them together, removes duplicates, and sorts them.
I suggest you break this down into helper methods (and slightly tweak the order of operations). Step 1, merge the two arrays. Something like,
static int[] mergeArrays(int[] a, int[] b) {
int[] c = new int[a.length + b.length];
for (int i = 0; i < a.length; i++) {
c[i] = a[i];
}
for (int i = 0; i < b.length; i++) {
c[a.length + i] = b[i];
}
return c;
}
Step 2, sort the new array (your existing sort algorithm is fine). Like,
static void sortArray(int[] a) {
for (int lastPos = a.length - 1; lastPos >= 0; lastPos--) {
for (int index = 0; index <= lastPos - 1; index++) {
if (a[index] > a[index + 1]) {
int temp = a[index];
a[index] = a[index + 1];
a[index + 1] = temp;
}
}
}
}
Finally, remove duplicates. Step 3a, count unique values. Assume they're unique, and decrement by counting adjacent (and equal) values. Like,
static int countUniqueValues(int[] c) {
int unique = c.length;
for (int i = 0; i < c.length; i++) {
while (i + 1 < c.length && c[i] == c[i + 1]) {
i++;
unique--;
}
}
return unique;
}
Then step 3b, take the unique count and build your result with the previous methods. Like,
public static int[] mergeDedupSort(int[] a, int[] b) {
int[] c = mergeArrays(a, b);
sortArray(c);
int unique = countUniqueValues(c);
int[] d = new int[unique];
int p = 0;
for (int i = 0; i < c.length; i++) {
d[p++] = c[i];
while (i + 1 < c.length && c[i] == c[i + 1]) {
i++;
}
}
return d;
}
Then you can test it with your arrays like
public static void main(String[] args) {
int[] a = { 1, 2, 3, 4, 8, 5, 7, 9, 6, 0 };
int[] b = { 0, 2, 11, 12, 5, 6, 8 };
int[] c = mergeDedupSort(a, b);
System.out.println(Arrays.toString(c));
}
And I get
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12]
Merge Two Arrays without Duplicates and Sort it (No libraries used).
Using an object.
public class MergeRemoveDupSort {
public int[] mergeRemoveDupSortIt(int[] a, int[] b) {
int [] c = mergeIt(a,b);
int [] d = removeIt(c);
int [] e = sortIt(d);
return e;
}
private int[] mergeIt(int[] a, int[] b) {
int[] c = new int[a.length + b.length];
int k=0;
for (int n : a) c[k++]=n;
for (int n : b) c[k++]=n;
return c;
}
private int[] removeIt(int[] c) {
int len=c.length;
for (int i=0;i<len-1;i++)
for (int j=i+1;j<len;j++)
if (c[i] == c[j]) {
for (int k=j;k<len-1;k++)
c[k]=c[k+1];
--len;
}
int [] r = new int[len];
for (int i=0;i<r.length;i++)
r[i]=c[i];
return r;
}
private int[] sortIt(int[] a) {
for(int index=0; index<a.length-1; index++)
for(int i=index+1; i<a.length; i++)
if(a[index] > a[i]){
int temp = a[index];
a[index] = a[i];
a[i] = temp;
}
return a;
}
public void printIt(int[] a) {
System.out.print("[");
for (int i=0;i<a.length;i++){
System.out.print(a[i]);
if (i!=a.length-1) System.out.print(",");
else System.out.print("]");
}
}
public static void main(String[] args) {
int[] a = {1, 2, 3, 4, 8, 5, 7, 9, 6, 0};
int[] b = {0, 2, 11, 12, 5, 6, 8};
MergeRemoveDupSort array = new MergeRemoveDupSort();
int [] r = array.mergeRemoveDupSortIt(a, b);
array.printIt(r);
}
}
You should use IntStream like this.
int[] a = {1, 2, 3, 4, 8, 5, 7, 9, 6, 0};
int[] b = {0, 2, 11, 12, 5, 6, 8};
int[] merged = IntStream
.concat(IntStream.of(a), IntStream.of(b))
.distinct()
.sorted()
.toArray();
System.out.println(Arrays.toString(merged));
Assuming that array a and array b are sorted, the following code will merge them into a third array merged_array without duplicates :
public static int[] get_merged_array(int[] a, int[] b, int a_size, int b_size)
{
int[] merged_array = new int[a_size + b_size];
int i = 0 , j = 0, x = -1;
for(; i < a_size && j < b_size;)
{
if(a[i] <= b[j])
{
merged_array[++x] = a[i];
++i;
}
else
{
if(merged_array[x] != b[j])
{
merged_array[++x] = b[j]; // avoid duplicates
}
++j;
}
}
--i; --j;
while(++i < a_size)
{
merged_array[++x] = a[i];
}
while(++j < b_size)
{
merged_array[++x] = b[j];
}
return merged_array;
}
Hope this may help, all the best :)
try{
int[] a = {1, 2, 3, 4, 8, 5, 7, 9, 6, 0};
int[] b = {0, 2, 11, 12, 5, 6, 8};
int[] c = new int[a.length+b.length];
int[] final = new int[a.length+b.length];
int i = 0;
for(int j : final){
final[i++] = -1;
}
i = 0;
for(int j : a){
c[i++] = j;
}
for(int j : b){
c[i++] = j;
}
boolean check = false;
for(int j = 0,k = 0; j < c.length; j++){
for(int l : fin){
if( l == c[j] )
check = true;
}
if(!check){
final[k++] = c[j];
} else check = false;
}
} catch(Exception ex){
ex.printStackTrace();
}
I prefer you to use Hashset for this cause it never allow duplicates
and there is another method in java 8 for arraylist to remove duplicates
after copying all elements to c follow this code
List<Integer> d = array.asList(c);
List<Integer> final = d.Stream().distinct().collect(Collectors.toList());
final.forEach(System.out::println());
This code is lot much better than previous one and you can again transform final to array like this
int array[] = new int[final.size()];
for(int j =0;j<final.size();j++){
array[j] = final.get(j);
}
Hope my work will be helpful .
Let me restate your question.
You want a program that takes two arbitrary arrays, merges them removing any duplicates, and sorts the result.
First of all, if you have access to any data structure, there are much better ways of doing this. Ideally, you would use something like a TreeSet.
However, assuming all you have access to is arrays, your options are much more limited. I'm going to go ahead and assume that each of the two arrays initially has no duplicates.
Let's assume the first array is of length m and the second array is of length n.
int[] array1; // length m
int[] array2; // length n
First, let's sort both arrays.
Arrays.sort(array1);
Arrays.sort(array2);
This assumes you have access to the Arrays class which is part of the standard Java Collections Framework. If not, any reasonable merge implementation (like MergeSort) will do the trick.
The sorts will take O(n log n + m log m) with most good sort implementations.
Next, let's merge the two sorted arrays. First, we need to allocate a new array big enough to hold all the elements.
int[] array3 = new int[size];
Now, we will need to insert the elements of array1 and array2 in order, taking care not to insert any duplicates.
int index=0, next=0, i=0, j=0;
int last = Integer.MAX_INT;
while(i < m || j < n) {
if(i == m)
next = array2[j++];
else if(j == n)
next = array1[i++];
else if(array1[i] <= array2[j])
next = array1[i++];
else
next = array2[j++];
if(last == next)
continue;
array3[index++] = next;
}
Now, you have your array. Just one problem - it could have invalid elements at the end. One last copy should take care of it...
int[] result = Arrays.copyOf(array3, index + 1);
The inserts and the final copy will take O(n + m), so the overall efficiency of the algorithm should be O(n log n + m log n).
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));
}