Method that fills the gap between an ArrayList in Java - java

I'm making a method called fillList. The method will require an arrayList in order to work and the output will be void.
What the method is supposed to do is to fill the gaps between the numbers of the List.
Example:
Input:
4 8 5 9
Output:
4 5 6 7 8 7 6 5 6 7 8 9
The code I have so far is this:
public static void fillList(ArrayList<Integer> List) {
for(int i = 0; i < List.size(); i++) {
if(List.get(i) < List.get(i+1) ) {
List.add(List.get(i+1));
} else if(List.get(i) > List.get(i+1)) {
List.add(List.get(i-1));
}
}
}
My idea was to add 1 to the value of the first element if the first element was less than the second element in the List. For example if the first element is 4 then the code would add a 5 to the list and stop once the number added was equal to one less than the second element. And basically do the opposite if the first element was more than the second element.
I don't know how to stop this loop until the numbers that are being added reach the second element of the list. I am not confident about my code as well I'm pretty sure I am making an error I'm not seeing.

Great question, I think you can learn alot by working this one out and really understanding every single line. I have made a litte illutration for you, to visualize the problem better. Hope this can help you. General tips:
variables are always lowercase by convention so write list instead of List
list.add(5) will add the number 5 to the end of your ArrayList. You can use list.add(4, 5) for example to insert the number 5 into the array position 4.

To update the list while iterating over its indices, you can use method List.add(int index, E element), which expects an index and a new element to insert.
While iterating, you need to compare two adjacent elements and insert a new one under the following conditions:
Left element is less than the right one and difference between them is greater than 1. A new element should be equal left + 1.
Left element is greater than the right one, and they differ more than by 1. A new element should be equal left - 1.
Also have a look at the nicely illustrated answer by #yezper. And as a general advice: draw before coding in order to understand the algorithm better.
That's how implementation might look like:
public static void fillList(List<Integer> list) {
for (int i = 0; i < list.size() - 1; i++) {
int left = list.get(i);
int right = list.get(i + 1);
if (left < right && left + 1 != right) {
list.add(i + 1, left + 1);
} else if (left > right && left - 1 != right) {
list.add(i + 1, left - 1);
}
}
}
main()
public static void main(String[] args) {
List<Integer> list1 = new ArrayList<>(List.of(4, 8, 5, 9));
fillList(list1);
System.out.println(list1);
}
Output:
[4, 5, 6, 7, 8, 7, 6, 5, 6, 7, 8, 9]

Related

Understanding Code in Java

public static void mystery2d(int[][] a) {
for (int r = 0; r < a.length; r++) {
for (int c = 0; c < a[0].length - 1; c++) {
if (a[r][c + 1] > a[r][c]) {
a[r][c] = a[r][c + 1];
}
}
}
}
If a two-dimensional array named numbers is initialized to store the following integers, what are its contents after the call shown?
int[][] numbers = {
{3, 4, 5, 6},
{4, 5, 6, 7},
{5, 6, 7, 8}
};
mystery2d(numbers);
I am really trying to understand code with 2D list but am having difficulties following along through the for loops. If someone could walk me through the steps or explain to me how it works that would be great thank you very much!
For example what would be a the values of the code bellow so I could have something to see if I could see the iterations of the loop better?
numbers[0][0] = ??
numbers[1][1] = ??
numbers[2][3] = ??
The code is to remove the smallest element in each row.
This is how it works.
In First row, it will check if 3<4? It is true. So, the a[0]=3 is replaced as a[0]=4 but a[1]=4 remains same. The same procedure happens till it reaches the end of each row. So the number in the last position at the end of every 'c'th iteration remains same.
Hence, the Output will be :
4566
5677
6788
So, the smallest element in each row. i.e. 3,4,5 in 1st, 2nd and 3rd row respectively is removed from array. I hope you got something!
First off, you should use i and j in your for loops rather than r and c, it is good practice. Your loop compares one number with the next number and changes the original to the new number if the new is greater than the original. So numbers[0][0] would be compared 3 ? 4 = 3 < 4 = so the 3 now becomes a 4. numbers[1][1] would be 5 ? 6 = 5 < 6 = 5 now becomes 6. And so on. Hope this helps.

Remove multi-elements from an arraylist error

public class test {
public static void main(String[] args) throws supernova, autowin{
ArrayList<Integer> integer = new ArrayList<Integer>();
integer.add(new Integer(0));
integer.add(new Integer(1));
integer.add(new Integer(2));
integer.add(new Integer(3));
System.out.println(integer.get(0));
System.out.println(integer.get(1));
System.out.println(integer.size());
for(int i = 0;i<2;i++){
if(i == integer.get(i)){integer.remove(i);System.out.println("remove");}
}
System.out.println(integer.get(0));
System.out.println(integer.get(1));
System.out.println(integer.size());
}
The outputs are
0
1
4
remove
1
2
3
.I expect this code to remove two elements(0 and 1),but it eventually only remove the first element. What if I want to remove all elements that have a special feature ,speaking like all elements store a odd number ,from an arraylist.
Could you explain the reason? Thank you a lot.
When you use the remove method, all elements ahead of the index are moved to the left. Therefore, after the first element is removed, i == integer.get(i) will always be false, because the Integer's value was set to be its original index, but now they are all "one ahead", so to speak.
Use a debugger in an IDE to see the process happen.
After the first iteration (i=0) the list is modified and becomes to
[1, 2, 3]
then for the next iteration i=1 adn then you do
if (i == integer.get(i)) {
if 1 == elementAtIndex1--> if 1==2 wich returns false an is not removing anything....
therefore your code is behaving like that...
Lets go step by step:
in for loop, when i = 0, you remove value from arraylist on position 0. Now, your ArrayList will be 1,2,3. Now, you check position i = 1, and in that position you have 2, not 1. because 2 is not equal to 1, if will not be executed.
One solution would be to change the direction of the for loop:
for(int i = 1;i >= 0;i--){
if(i == integer.get(i)) {integer.remove(i);System.out.println("remove");}
}
Now, the output will be:
0
1
4
remove
remove
2
3
2
Update: OP asked new question
If you want to remove odd numbers, just place logic for it in if:
for(int i = integer.size() - 1;i >= 0;i--){
if(integer.get(i) % 2 != 0 {
integer.remove(i);
System.out.println("remove");
}
}

Tough recursive task

I've been struggle with question I'm trying to solve as part of test preparation, and I thought I could use your help.
I need to write a Boolean method that takes array with integers (positive and negative), and return true if the array can be split to two equals groups, that the amount of every group's numbers is equals to the other group.
For exmaple, for this array:
int[]arr = {-3, 5, 12, 14, -9, 13};
The method will return true, since -3 + 5 + 14 = 12 + -9 + 13.
For this array:
int[]arr = {-3, 5, -12, 14, -9, 13};
The method will return false since even though -3 + 5 + 14 + -12 = -9 + 13, the amount of numbers in every side of the equation isn't equals.
For the array:
int[]arr = {-3, 5, -12, 14, -9};
The method will return false since array length isn't even.
The method must be recursive, overloading is allowed, every assist method must be recursive too, and I don't need to worry about complexity.
I've been trying to solve this for three hours, I don't even have a code to show since all the things I did was far from the solution.
If someone can at least give me some pseudo code it will be great.
Thank you very much!
You asked for pseudocode, but sometimes it's just as easy and clear to write it as Java.
The general idea of this solution is to try adding each number to either the left or the right of the equation. It keeps track of the count and sum on each side at each step in the recursion. More explanation in comments:
class Balance {
public static void main(String[] args) {
System.out.println(balanced(-3, 5, 12, 14, -9, 13)); // true
System.out.println(balanced(-3, 5, -12, 14, -9, 13)); // false
}
private static boolean balanced(int... nums) {
// First check if there are an even number of nums.
return nums.length % 2 == 0
// Now start the recursion:
&& balanced(
0, 0, // Zero numbers on the left, summing to zero.
0, 0, // Zero numbers on the right, summing to zero.
nums);
}
private static boolean balanced(
int leftCount, int leftSum,
int rightCount, int rightSum,
int[] nums) {
int idx = leftCount + rightCount;
if (idx == nums.length) {
// We have attributed all numbers to either side of the equation.
// Now check if there are an equal number and equal sum on the two sides.
return leftCount == rightCount && leftSum == rightSum;
} else {
// We still have numbers to allocate to one side or the other.
return
// What if I were to place nums[idx] on the left of the equation?
balanced(
leftCount + 1, leftSum + nums[idx],
rightCount, rightSum,
nums)
// What if I were to place nums[idx] on the right of the equation?
|| balanced(
leftCount, leftSum,
rightCount + 1, rightSum + nums[idx],
nums);
}
}
}
This is just a first idea solution. It's O(2^n), which is obviously rather slow for large n, but it's fine for the size of problems you have given as examples.
The problem described is a version of the Partition problem. First note that your formulation is equivalent to deciding whether there is a subset of the input which sums up to half of the sum of all elements (which is required to be an integral number, otherwise the instance cannot be solved, but this is easy to check). Basically, in each recursive step, it is to be decided whether the first number is to be selected into the subset or not, resulting in different recursive calls. If n denotes the number of elements, there must be n/2 (which is required to be integral again) items selected.
Let Sum denote the sum of the input and let Target := Sum / 2 which in the sequel is assumed to be integral. if we let
f(arr,a,count) := true
if there is a subset of arr summing up to a with
exactly count elements
false
otherwise
we obtain the following recursion
f(arr,a,count) = (arr[0] == a && count == 1)
||
(a == 0 && count == 0)
if arr contains only one element
f(arr\arr[0], a, count)
||
f(arr\arr[0], a - arr[0], count -1)
if arr contains more than one element
where || denotes logical disjuction, && denoted logical conjunction and \ denotes removal of an element.
The two cases for a non-singleton array correspond to chosing the first element of arr into the desired subset or its relative complement. Note that in an actual implementation, a would not be actually removed from the array; a starting index, which is used as an additional argument, would be initialized with 0 and increased in each recursive call, eventually reaching the end of the array.
Finally, f(arr,Target,n/2) yields the desired value.
Your strategy for this should be to try all combinations possible. I will try to document how I would go about to get to this.
NOTE that I think the requirement: make every function use recursion is a bit hard, because I would solve that by leaving out some helper functions that make the code much more readable, so in this case I wont do it like that.
With recursion you always want to make progression towards a final solution, and detect when you are done. So we need two parts in our function:
The recursive step: for which we will take the first element of the input set, and try what happens if we add it to the first set, and if that doesn't find a solution we'll try what happens when we add it to the second set.
Detect when we are done, that is when the input set is empty, in that case we either have found a solution or we have not.
A trick in our first step is that after taking the first element of our set, if we try to partition the remainder, we don't want the 2 sets being equal anymore, because we already assigned the first element to one of the sets.
This leads to a solution that follows this strategy:
public boolean isValidSet(MySet<int> inputSet, int sizeDifferenceSet1minus2)
{
if (inputSet.isEmpty())
{
return sizeDifferenceSet1minus2== 0;
}
int first = inptuSet.takeFirst();
return isValidSet(inputSet.copyMinusFirst(), sizeDifferenceSet1minus2+ first)
|| isValidSet(inputSet.copyMinusFirst(), sizeDifferenceSet1minus2+ -1 * first);
}
This code requires some help functions that you will still need to implement.
What it does is first test if we have reached the end condition, and if so returns if this partition is successful. If we still have elements left in the set, we try what happens if we add it to the first set and then what happens when adding it to the second set. Note that we don't actually keep track of the sets, we just keep track of the size difference between set 1 minus 2, decreasing the (but instead you could pass along both sets).
Also note that for this implementation to work, you need to make copies of the input set and not modify it!
For some background information: This problem is called the Partition Problem, which is famous for being NP-complete (which means it probably is not possible to solve it efficiently for large amounts of input data, but it is very easy to verify that a partitioning is indeed a solution.
Here is a verbose example:
public static void main(String[] args)
{
System.out.println(balancedPartition(new int[] {-3, 5, 12, 14, -9, 13})); // true
System.out.println(balancedPartition(new int[] {-3, 5, -12, 14, -9, 13})); // false
System.out.println(balancedPartition(new int[] {-3, 5, -12, 14, -9})); // false
}
public static boolean balancedPartition(int[] arr)
{
return balancedPartition(arr, 0, 0, 0, 0, 0, "", "");
}
private static boolean balancedPartition(int[] arr, int i, int groupA, int groupB, int counterA, int counterB, String groupAStr, String groupBStr)
{
if (groupA == groupB && counterA == counterB && i == arr.length) // in case the groups are equal (also in the amount of numbers)
{
System.out.println(groupAStr.substring(0, groupAStr.length() - 3) + " = " + groupBStr.substring(0, groupBStr.length() - 3)); // print the groups
return true;
}
if (i == arr.length) // boundaries checks
return false;
boolean r1 = balancedPartition(arr, i + 1, groupA + arr[i], groupB, counterA + 1, counterB, groupAStr + arr[i] + " + ", groupBStr); // try add to group 1
boolean r2 = balancedPartition(arr, i + 1, groupA, groupB + arr[i], counterA, counterB + 1, groupAStr, groupBStr + arr[i] + " + "); // try add to group 2
return r1 || r2;
}
Output:
-3 + 5 + 14 = 12 + -9 + 13 // one option for the first array
12 + -9 + 13 = -3 + 5 + 14 // another option for the first array
true // for the first array
false // for the second array
false // for the third array

Print all the combinations of elements in a 2D Matrix

Print all the combinations of elements in matrix of size m * n.
Sample Example:
1 3 5
2 6 7
Expected Output:
2 , 1
2 , 3
2 , 5
6 , 1
6 , 3
6 , 5
7 , 1
7 , 3
7 , 5
Rules:
- Every combination starts from bottom of matrix and proceeds towards top. It may switch columns though.
- Every combination should have number of elements equal to number of rows.
- A combination can't have an element from the same row present twice.
I never could figure the solution out for general case. I can use 3 loops. But I want to understand the recursive solution. I use Java.
Here's a non-recursive way to solve this problem (it's not all that pretty, but it works for your input). I know you were interested in recursion, but I don't have anything like that for you at the moment. Generally, I avoid recursion due to the size of problems I work with (constant heap space errors due to the size of the recursive stack even when -Xmx60G). Hope this helps.
private static List<int[]> combos;
public static void main(String[] args){
combos = new ArrayList<int[]>();
generate(new int[][]{{1,3,5},{2,6,7}});
for(int[] s : combos){
System.out.println(java.util.Arrays.toString(s));
}
}
private static void generate(int[][] elements) {
int rows = elements.length;
int[] elementsIndex = new int[rows];
int[] elementsTotals = new int[rows];
java.util.Arrays.fill(elementsTotals, elements[0].length);
int curIdx = 0;
int[] c = new int[rows];
while(true){
while(curIdx >= 0){
if(curIdx == rows) {
addCombo(c);
curIdx--;
}
if(elementsIndex[curIdx] == elementsTotals[curIdx]){
elementsIndex[curIdx] = 0;
curIdx--;
} else break;
}
if(curIdx < 0) break;
// toggle order:
// bottom up: elements[rows-curIdx-1][elementsIndex[curIdx]++]
// top down: elements[curIdx][elementsIndex[curIdx]++]
c[curIdx] = elements[rows-curIdx-1][elementsIndex[curIdx]++];
curIdx++;
}
}
private static void addCombo(int[] c){
int[] a = new int[c.length];
System.arraycopy(c, 0, a, 0, c.length);
combos.add(a);
}
A recursive solution would look something like this:
printPermutations(String head, Matrix m)
if m is empty print head and return
else for each item in last row of m
printPermutations(head + item, m - bottom row)
here "head" is all the work we've done so far. In the body of a recursive method, there have to be at least two alternatives, one that outputs a result and ends the recursion, and one that goes deeper. For the deeper alternative, we transfer the selected element to head, remove the bottom row since we can't pick more than one item from any row, and do it again.
Done well, a recursive solution is often simpler and cleaner than using loops. On the other hand, recursion tends to use more memory

Removing pairs of elements in an Arraylist in Java

I know similar questions have been asked before, but they typically remove all of the specified element from an Arraylist.
What I need to do, is remove pairs of values from my ArrayList (if a number occurs 3 times, it will remove 2 copies of that element and leave 1 of them). More generally, if a number occurs an odd number of times leave 1, if a number occurs an even number of times remove them all. Thus, if my Arraylist was something like this
[5, 4, 3, 3, 2, 1, 2, 3, 1],
the output would be
[5, 4, 3]
Since the number "2" appears twice, it is complete removed. Same with the number "1". But since the number "3" appears three times, it leaves one of them in the ArrayList, because I only want to remove the numbers in pairs.
I don't care at all about the ordering, as I'm going to reorder it anyways.
Does anyone have any suggestions on doing this? I think I could use a for loop that compares each value over and over, but it seems inefficient, so I was curious if there would be a better way.
Thank you!
If you're allowed to sort the arraylist, this becomes pretty simple.
public void removePairedElements(ArrayList<Integer> a){
Collections.sort(a); //Sort a
int i = 0;
while(i < a.size() - 1){
//Check if i and i+1 are the same element. If so, remove both
if(a.get(i).equals(a.get(i+1))){
//Remove i twice - effectively removes i and i+1
a.remove(i);
a.remove(i);
//Move i *back* one index, which is equivalent to
//moving forward one because we just removed two elements.
//Prevent i from becoming negative though.
i = Math.max(0, (i - 1));
}
else{
i++;
}
}
}
O(n log n) time and O(1) space. Probably the cleanest answer. If you aren't allowed to change the ordering of the arraylist you'd have to do something else, but otherwise this should work.
You can use a Map as a helper.
iterate over the ArrayList
Lets say the i'th element of the list contains the number n.
If map.containsKey(n), map.get(n) is the location in the list of the previous occurrence of n.
remove both the i'th element and the map.get(n)'th element from the list.
remove the key n from the map.
Else
map.put (n,i)
Implementation note :
Don't use an enhanced for loop to iterate over the list (since it doesn't allow removal of elements). Iterate over the indices of the list. This will allow you to remove the elements by their index (but remember that when you remove the i'th element, the previous i+1 element becomes the new i'th element).
I think your best bet would be to sort the list.
Then, going backwards, remove ints if you see the same one while keeping track of the total count of current ints.
If you see an even total count, you will NOT remove the last occurrence.
If you see an odd total count, you will remove the last occurence.
public void removePairElementsFrom(Arraylist<Integer> myArrayList)
{
if (myArrayList == null)
{
return null;
}
int arrayLength = myArrayList.size();
if (arrayLegnth == 1)
{
return myArrayList;
)
Collections.sort(myArrayList);
int lastSeenInt = myArrayList.get(arrayLength - 1);
int lastSeenIntCount = 1;
for (int i = arrayLength - 2; i >= 0; --i)
{
if (myArrayList[i] == lastSeenInt)
{
myArrayList.remove(i+1);
++lastSeenIntCount;
}
else
{
if ((lastSeenIntCount % 2) == 0)
{
myArrayList.remove(i+1);
}
lastSeenInt = myArrayList.get(i);
lastSeenIntCount = 1;
}
}
if ((lastSeenIntCount % 2) == 0)
{
myArrayList.remove(0);
}
}
Enjoy :)
Write a method removeBadPairs that accepts an ArrayList of integers and removes any adjacent pair
of integers in the list if the left element of the pair is larger than the right element of the pair. Every pair's
left element is an even-numbered index in the list, and every pair's right element is an odd index in the list.
For example, suppose a variable called list stores the following element values:
[3, 7, 9, 2, 5, 5, 8, 5, 6, 3, 4, 7, 3, 1]
We can think of this list as a sequence of pairs: (3, 7), (9, 2), (5, 5), (8, 5), (6, 3), (4, 7), (3, 1). The pairs (9,
2), (8, 5), (6, 3), and (3, 1) are "bad" because the left element is larger than the right one, so these pairs
should be removed. So the call of removeBadPairs(list); would change the list to store the following
element values:
[3, 7, 5, 5, 4, 7]
If the list has an odd length, the last element is not part of a pair and is also considered "bad;" it should
therefore be removed by your method.
If an empty list is passed in, the list should still be empty at the end of the call. You may assume that the
list passed is not null. You may not use any other arrays, lists, or other data structures to help you solve
this problem, though you can create as many simple variables as you like.
You will get an error if you start from the start of the list using For loop due to an iterator. So I have an alternate way.
class RemoveBadPairs {
Public Static void main() {
ArrayList numbersList = new ArrayList();
numberslist={3,7,9,2,5,5,8,5,6,3,4,7,3,1,7};
System.out.println("Original List...");
for (e in : numbersList) {
System.out.print("{0},", e);
}
if (((numbersList.Count % 2)!= 0)) {
numbersList.RemoveAt((numbersList.Count - 1));
}
for (int i = (numbersList.Count - 1); (i <= 0); i = (i + -2)) {
if ((numbersList[i] < numbersList[(i - 1)])) {
numbersList.RemoveRange((i - 1), 2);
}
}
System.out.println("Final List...");
for (e in : numbersList) {
System.out.print(","+ e);
}
}
}
I hope this will work.

Categories