Ok so the point of this method is the invert the elements in an ArrayList of type <Integer>. So if I have the elements:
5
6
7
8
9
10
once I call the method, the position of the elements should be Inverted as such:
10
9
8
7
6
5
This is the method, any advice would be greatly appreciated :).
public void invertElements()
{
for (int i = list.size()-1; i <= -1; i--)
{
int temp = list.get(i);
for(int j = 0; j < list.size()-1; j++)
{
list.set(j, temp);
}
}
}
list is the name of my ArrayList<Integer>.
Update: Just tried this way:
public void invertElements()
{
int index = 0;
for (int i = list.size()-1; i > -1; i--)
{
int temp = list.get(i);
list.set(index, temp);
index++;
if(index == list.size()-1)
{
break;
}
}
}
which gives the output: 10, 9, 8, 9, 10
Could someone explain to me why?
You can take the extremities of the list at each iteration and swap them :
ArrayList<Integer> list = new ArrayList<>(Arrays.asList(1,2,3,4,5,6,7,8,9,10));
for (int i = 0; i < list.size()/2; i++){
int temp = list.get(i);
int temp2 = list.get(list.size()-1-i);
list.set(i, temp2);
list.set(list.size()-1-i, temp);
}
for(Integer i : list)
System.out.print(i+"-");
Gives the output :
10-9-8-7-6-5-4-3-2-1-
At the first iteration : temp = 1 / temp2 = 10 : we swap them
At the second iteration : temp = 2 / temp2 = 9 : we swap them
And we loop until we go through all the elem of the list which is the size of the list divided by 2.
Solution is
public void invertElems(List<Integer> list) {
for (int i = 0; i < list.size() / 2; ++i) { // we only need iterating half of the size of list
int elem = list.get(i); // we store element in additional variable
list.set(i, list.get(list.size() - i - 1)); // we set i-th elementh with i-th element from the back
list.set(list.size() - i - 1, elem);
}
}
Linear time. Feel free to ask questions.
Related
For this particular problem I am attempting to remove redundant elements in an sorted array and replace them all with 0s at the end of the array. For example, if I had an array consisting of the int elements
1,3,3,4,4,5,6,6,7
My output array should be
1,3,4,5,6,7,0,0,0
My first attempt at the problem was to create a swapper in order to push all the 0s to the end of the list after removing the elements, but it won't seem to push the zeros to the end of the list. Here is my code.
public void implode(int[] ary)
{
int swapper = -1;
int[] newARY = new int[ary.length];
int current = -1;
for (int i = 0; i < ary.length; i++)
{
if (current != ary[i])
{
newARY[i] = ary[i];
current = ary[i];
}
}
for (int i = 0; i < ary.length; i++)
{
if (ary[i] == 0)
{
if (ary[i + 1] != 0)
{
swapper = ary[i + 1];
ary[i] = swapper;
ary[i + 1] = 0;
}
}
}
ary = newARY;
for (int i = 0; i < newARY.length; i++)
{
System.out.print(newARY[i] + " ");
}
}
The array im testing it with is,
int[] aryIn2 = {1, 1, 2, 3, 4, 4, 5, 6};
However, when outputting the imploded array, I receive this one.
1 0 2 3 4 0 5 6
Is there something I am missing?
Thanks in advance.
not an answer to your problem, but using (if possible) java streams can shorten your way:
int[] arr = {1,3,3,4,4,5,6,6,7};
// distinct
List<Integer> list = Arrays.stream(arr).distinct().boxed().collect(Collectors.toList());
// pad with zero's
while(list.size() < arr.length) {
list.add(0);
}
// display
System.out.println(list.stream().map(String::valueOf).collect(Collectors.joining(",")));
will output
1,3,4,5,6,7,0,0,0
Two issue with you code that I observed.
1) Your swapper logic is performing swapping on a different array than the one in which you had done modification earlier
2) You need to have this logic in a bubble-sort way, i.e. loop inside a loop
Below is a working modified sample code of your method. I have modified only the second for-loop logic
public void implode(int[] ary) {
int swapper = -1;
int[] newARY = new int[ary.length];
int current = -1;
for (int i = 0; i < ary.length; i++) {
if (current != ary[i]) {
newARY[i] = ary[i];
current = ary[i];
}
}
for (int i = 0; i < newARY.length - 1; i++) {
if (newARY[i] == 0 && newARY[i + 1] != 0) {
for (int j = i; (j + 1) < newARY.length; j++) {
swapper = newARY[j + 1];
newARY[j] = swapper;
newARY[j + 1] = 0;
}
}
}
for (int i = 0; i < newARY.length; i++) {
System.out.print(newARY[i] + " ");
}
}
In this first loop:
for (int i = 0; i < ary.length; i++) {
if (current != ary[i]) {
newARY[i] = ary[i];
current = ary[i];
}
}
You fill newARY with elements in ary with duplicated value turns to 0:
newARY: 1 0 2 3 4 0 5 6
However, in the second loop:
for (int i = 0; i < ary.length; i++)
{
if (ary[i] == 0)
{
if (ary[i + 1] != 0)
{
swapper = ary[i + 1];
ary[i] = swapper;
ary[i + 1] = 0;
}
}
}
You're modifying your original ary array. So the newARY is not updated.
However, your attempt to push 0 to the end of array also fail if there are more than two 0s consecutive. And it is also vulnerable to ArrayOutOfBoundIndexException since you try to read ary[i+1] without restriction on i
One simple and straight forward way to push 0s to the end of the array is to create new array with non-0s elements and fill 0s later:
int[] result = new int[ary.lenght];
int resultIndex = 0;
for (int i = 0; i < newARY.length; i++) {
if (newARY[i] != 0) {
result[resultIndex++] = newAry[i];
}
}
for (int i = resultIndex; i < newARY.length; i++) {
result[i] = 0;
}
// Print result array
Hint: Using above strategy, you can simplify your code. No need to create immediate array newARY. Just loop over the original array, push unique elements to the result array, then fill any slot left with 0s.
Method scaleByK should replace every integer of value k with k copies of itself. For example, if the list is: [2, 4, -2, 5, 3, 0, 7] before the method is invoked, it should be [2, 2, 4, 4, 4, 4, 5, 5, 5, 5, 5, 3, 3, 3, 7, 7, 7, 7, 7, 7, 7 ] after the method executes. Note that the method should remove from the list all 0s and negative values.
Right now my code looks like this
`public void scaleByK()
{
int size;
size = length;
for (int i = 0; i < size; i++)
{
if (list[i] < 0 || list[i] == 0)
{
remove(list[i]);
size = size - 1;
}
for (int j =0; j < list[i]; j++)
{
insertEnd(list[i]);
}
}
for (int h = 0; h < size ; h++)
{
remove(list[h]);
}
}
}
the print method will print the list. this scaleByK method will print the new list with the new values. Everything works FINE but the original list doesn't get deleted and i cant figure out how to do that. For example,
Original list is 2 4 -2 5 3 0 7
New list is 2 4 5 3 7 2 2 4 4 4 4 5 5 5 5 5 3 3 3 7 7 7 7 7 7 7
So I don't want those first 5 numbers in the new list to print because I already have the duplicated numbers after those.
You can use 'List' instead of array.
import java.util.ArrayList;
import java.util.List;
public class stack {
public List<Integer> list=new ArrayList<>(5);
public void scaleByK()
{
int size=list.size();
for (int i = 0; i < size; i=i+list.get(i))
{
if (list.get(i) < 0 || list.get(i) == 0)
{
list.remove(i);
size--;
}
for (int j = 1; j < list.get(i); j++) {
list.add(i + j, list.get(i));
size++;
}
}
for(int i=0;i<list.size();i++){
System.out.println(list.get(i));
}
}
public static void main(String arg[]){
stack s1=new stack();
s1.list.add(2);
s1.list.add(4);
s1.list.add(-2);
s1.list.add(5);
s1.list.add(3);
s1.list.add(0);
s1.list.add(7);
s1.scaleByK();
}
}
Using a second list, and filtering the original list before. Then assign the new scaledList to list.
public void scaleByK()
{
int size;
int index = 0;
int scaledSize = 0;
// Check how big the new array will be
for (int i = 0; i < list.length; i++)
{
if (list[i] > 0)
{
scaledSize += list[i];
}
}
int[] scaledList = new int[scaledSize];
for (int i = 0; i < size - 2; i++)
{
for (int j = 0; j < list[i]; j++)
{
scaledList[index] = list[i];
index++;
}
}
list = scaledList;
}
So you don't have to keep track of changes to following indexes due to insertions, work backwards from the last element to the first.
For each element n, insert n - 1 copies of each positive number at its index, but delete non-positives.
public void scaleByK()
{
int size;
size = length;
for (int i = 0; i < size; i++)
{
if (list[i] < 0 || list[i] == 0)
{
remove(list[i]);
size = size - 1;
}
for (int j =0; j < list[i]; j++)
{
insertEnd(list[i]);
}
}
for (int h = 0; h < size ; h++)
{
removeAt(0);
}
}
}
Of course one could approach this using Java8 streams:
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.junit.Assert;
import org.junit.Test;
public class Copies {
int[] nCopies(int[] input) {
if(input==null) {
return null;
}
return Arrays.stream(input) // stream the input array
.filter(i->i>0) // keep just elements >0 and throw away rest
.boxed() // IntStream into Strea<Integer>
.map(i-> Collections.nCopies(i, i)) // convert each n into list containg n-copies of n
.flatMap(List::stream) // flat the result list of lists into simple list
.mapToInt(Integer::intValue) // convert back into IntStream
.toArray(); // and convert the IntStream into array
}
#Test
public void testNCopies() {
Assert.assertArrayEquals(new int[]{2,2,3,3,3}, nCopies(new int[]{2,-2,3}));
}
}
I am trying to write a modified selection sort that selects the biggest number and place it at the end of a list. I ran into a problem. The code is kind of sorting the list but not perfectly. This is the result after I ran the code:
Before selection sort: [2, 8, 7, 1, 3, 5, 9, 4, 6]
After selection sorted: [1, 2, 8, 7, 3, 4, 5, 9, 6]
Here is my code:
public static int[] sort(int[] list) {
int i, j, maxNum, maxInde, temp = 0;
for (i = list.length-1; i >= 0; i--) {
maxNum = list[i];
maxInde = i;
for (j = i; j < list.length; j++) {
if (list[j] < maxNum) {
maxNum = list[j];
maxInde = j;
}
}
if (maxNum < list[i]) {
temp = list[i];
list[i] = list[maxInde];
list[maxInde] = temp;
}
}
return list;
}
I don't know where the issue is located.
The algorithm is conceptually flawed because you scan the array from n-1 downto 0 and at each iteration select the max element from the subarray a[n-1,...,i]. This subarray should always be sorted (and should consist of the n-i largest elements of the array) ---this is analogous to the loop invariant of the classical selection sort---and the max element to be inserted in the current position should come from the other subarray, i.e., a[i,...,0].
Also, as mentioned in the comments, there is no need to return the array because the algorithm can just modify it.
Here is the fixed version:
int i, j, maxNum, maxInde, temp = 0;
for (i = list.length-1; i >= 0; i--) {
// you start iterating from the end of the list
// which means that the elements between i and the end of the list are sorted
maxNum = list[i];
maxInde = i;
for (j = 0; j < i; j++) {
// you have to iterate through the nonsorted elements
if (list[j] > maxNum) {
maxNum = list[j];
maxInde = j;
}
}
if (maxNum > list[i]) {
// if you found an element that is bigger then the current element
// then it should be set as the current element
temp = list[i];
list[i] = list[maxInde];
list[maxInde] = temp;
}
}
public static void sortArray (int [] a) {
//find max value in this array
for (int i = 0; i < a. length; i++) {
int max=a[0];
int index=0;
for (int j=0; j<a. length-i; j++) {
if (a[j] >max) {
max=a[j];
index=j;
}
}
//change the index
a[index]=a[a.length-(i+1)];
a[a.length-(i+1)]=max; //max value change the last element
}
}
public static void main (String args[]) {
int [] a= {91,13,53,64,48,49,99,35,65,38,62,72};
System.Out.Println (Arrays.toString (ar));
sortArray(ar);
System.Out.Println (Arrays.toString (ar));
}
}
Basically, one of my assignments is if the array is odd, remove the middle element or if the array is even, remove the middle two elements.
Here is my code, it may be sloppy as this is my first year of high school Java.
public static void removeMiddle(int[] arr)
{
int size = arr.length;
if(size % 2 ==0)
{
int x = arr.length/2 -1;
for(int i = x; i <= arr.length - 2; i++)
{
arr[i] = arr[i + 2];
}
}
else
{
int z = arr.length/2;
for(int i = z; i < arr.length - 1; i++)
{
arr[i] = arr[i + 1];
}
}
}
I was following the pseudo code that the teacher gave us if we got stuck. When I'm running it, it's adding an extra element.
For example, my array 3, 6, -2, 8, 9 changes to 3, 6, 8, 9, 9, after running it
Create a local variable named "size" that stores the length of the array passed in.
* 2. If the size of the array happens to be even, do the following:
* a. Create a local variable that represents the first to remove by assigning it to be one less than
* half the size of the array
* b. Run a for-loop starting at the value you just calculated (representing the first to remove) and
* terminating at two less than the size of the array
* i. In the for-loop, assign the value at the current index of the array to be the value at two
* more than the current index
* 3. Otherwise, given the size of the array happens to be odd, do the following:
* a. Create a local variable that represents the first to remove by assigning it to be half the
* size of the array
* b. Run a for-loop starting at the value you just calculated (representing the first to remove) and
* terminating at one less than the size of the array
* i. In the for-loop, assign the value at the current index of the array to be the value at one
* more than the current index
Any suggestions?
I'm not sure if I understood your questions correctly.
Is it saying, for example, if an array had the size of 8 (8 elements),
the new array returned after the method should return a new array with 6 elements?
I would first, change the return type of the method you provided to be int[].
You can try to implement stack, or queue, or simply stick to using arrays with a bunch of conditionals.
int size = arr.length;
int newArr[];
if(size % 2 ==0) {
newArr = new int[size-2];
for (int i = 0; i < (newArr.length/2); i++) {
newArr[i] = arr[i];
System.out.println(newArr[i]);
}
for (int i = (newArr.length/2); i < newArr.length; i++) {
newArr[i] = arr[i+2];
System.out.println(newArr[i]);
}
}
else {
newArr = new int[size-1];
for(int i = 0; i < (newArr.length/2); i++) {
newArr[i] = arr[i];
System.out.println(newArr[i]);
}
for (int i = (newArr.length/2); i < newArr.length; i++) {
newArr[i] = arr[i+1];
System.out.println(newArr[i]);
}
}
if the input was 123456, this produces 1256
if the input was 12345, this produces 1245
In my opinion, in the "even" if clause, you should just change the
for(int i = x; i <= arr.length - 2; i++)
to
for(int i = x; i < arr.length - 2; i++)
Do you need to get from 1,2,3,4,5,6 an array like 1,2,5,6,5,6 or 1,2,5,6?
To delete the elements from an array, you need to make a new array from the existing one, and then return the result, or change the reference of the original array to the new created array.
public static void removeMiddle(int[] myArray)
{
int size = myArray.length;
int[] resultArray;
if(size % 2 ==0)
{
resultArray = new int [myArray.length-2];
}
else
{
resultArray = new int [myArray.length-1];
}
int mid1 = myArray.length/2;
int mid2 = myArray.length/2 - 1;
int index = 0;
for(int i=0;i<myArray.length;i++)
{
if(size % 2 ==0 && (i==mid1 || i==mid2))
{
continue;
}
else if(!((size % 2) ==0) && i==mid1)
{
continue;
}
resultArray[index] = myArray[i];
index++;
}
for(int i=0;i<resultArray.length;i++)
{
System.out.println("array[" + i + "] = " + resultArray[i]);
}
}
If myArray hold the value as 1,2,3,4,5,6,7 the output will be as below
array[0] = 1
array[1] = 2
array[2] = 3
array[3] = 5
array[4] = 6
array[5] = 7
and if it hole the value as 1,2,3,4,5,6 the output will be as below
array[0] = 1
array[1] = 2
array[2] = 5
array[3] = 6
I have 999 numbers in my arrayList, some of the numbers are repeated. And i want to find the most frequent number in the list, what is the most efficient way of doing that?
Sort the list and than count which occurs the most by reading the sorted List.
Needs 0(n log n) Time
1 3 6 1 82 42 11 42 1 42 3 42
sorted
1 1 1 3 3 6 11 42 42 42 42 82
Read the list from left to right and remember which value was seen the most so far and how often
I assume, as you wrote in comment, that you read numbers from 0 to 100
from a text file, so you can use
int[] count = new int[101];
...
count[numberJustRead]++;
...
and after read all numbers
int max = 0;
int maxIndex = 0; //this is what you looking for
for(int i = 0, k = count.length; i < k; i++){
if(count[i] > max){
max = count[i];
maxIndex = i;
}
}
or you maybe like guava's Mulitset
Here are two simple implementations with different complexity (of course if you have only a few numbers performance gain is symbolic) :
import java.util.*;
public class Test
{
static AbstractMap.SimpleEntry<Integer, Integer> getMostFrequentN2(ArrayList<Integer> values)
{
ArrayList<AbstractMap.SimpleEntry<Integer, Integer>> frequencies = new ArrayList<>();
int maxIndex = 0;
main:
for (int i = 0; i < values.size(); ++i)
{
int value = values.get(i);
for (int j = 0; j < frequencies.size(); ++j)
{
if (frequencies.get(j).getKey() == value)
{
frequencies.get(j).setValue(frequencies.get(j).getValue() + 1);
if (frequencies.get(maxIndex).getValue() < frequencies.get(j).getValue())
{
maxIndex = j;
}
continue main;
}
}
frequencies.add(new AbstractMap.SimpleEntry<Integer, Integer>(value, 1));
}
return frequencies.get(maxIndex);
}
static AbstractMap.SimpleEntry<Integer, Integer> getMostFrequentNLogN(ArrayList<Integer> values)
{
ArrayList<Integer> tmp = new ArrayList(values);
Collections.sort(tmp);
AbstractMap.SimpleEntry<Integer, Integer> max = new AbstractMap.SimpleEntry<>(0, 0);
int current = tmp.get(0);
int count = 0;
for (int i = 0; i < tmp.size(); ++i)
{
if (tmp.get(i) == current)
{
count++;
}
else
{
if (count > max.getValue())
{
max = new AbstractMap.SimpleEntry<Integer, Integer>(current, count);
}
current = tmp.get(i);
count = 1;
}
}
if (count > max.getValue())
{
max = new AbstractMap.SimpleEntry<Integer, Integer>(current, count);
}
return max;
}
public static void main(String[] args)
{
ArrayList<Integer> numbers = new ArrayList(99);
for (int i = 0; i < 99; ++i)
{
numbers.add((int)(Math.random() * 10));
}
System.out.println(numbers);
System.out.println(getMostFrequentN2(numbers));
System.out.println(getMostFrequentNLogN(numbers));
}
}
Yes, slowly.
You could do this with a List of Lists; an inner list contains the numbers you have seen, and the index of the outer list is the number of occurrences. So after processing "1,2,1,3,1,2,3,4" you would have
[ [4], [2, 3], [1] ]
Once you are done processing the input list, you can get the last inner list contained by the highest index of the outer list, which in this case is [1]. All elements in that list are tied for the maximum number of occurrences.