Remove two or more consecutive numbers ending in 6 in the array

Multi tool use
Multi tool use


Remove two or more consecutive numbers ending in 6 in the array



I have tried it but it is working only for two consecutive digits and not for more than two. Please find the code below which I've tried and kindly suggest a solution for it.



Sample Input:



3
6
36
62
121
66
26
376
661
6



Sample Output:



3
62
121
661
6



My code:


public static List<Integer> processArray(ArrayList<Integer> array) {
int num=0;
int prevnum=0;
for(int i =0;i<array.size();i++) {
num=array.get(i);
if(i>0 && array.get(i-1)%10==6 && num%10==6) {
array.remove(i-1);
array.remove(i-1);
}
}
return array;
}





So would the desired result be 3 62 121 661 (with the final 6 having been removed too)?
– Ole V.V.
Jul 3 at 7:55





@OleV.V. I would guess not as the last 6 isn't preceded by a number ending in 6.
– notyou
Jul 3 at 7:56





No final 6 won't be removed. Only two or more than two consective numbers are removed.
– Alchemist
Jul 3 at 7:56




3 Answers
3



When deleting elements from a list I always find it simplest to process the list backward, from the end towards the beginning. In this way the only indices that shift when deleting elements are the ones that I am already done with, so I can ignore the shifting.


public static void processArray(ArrayList<Integer> array) {
// process from end of list backward
int ix = array.size();
while (ix > 0) {
if (array.get(ix - 1) % 10 == 6) {
// find beginning of run of numbers that end in 6
int beginIx = ix - 1;
while (beginIx > 0 && array.get(beginIx - 1) % 10 == 6) {
beginIx--;
}
List<Integer> runOf6 = array.subList(beginIx, ix);
if (runOf6.size() >= 2) {
// delete entire run
runOf6.clear();
}
ix = beginIx;
}
else {
ix--;
}
}
}



Demo:


ArrayList<Integer> list = new ArrayList<>(Arrays.asList(3, 6, 36, 62, 121, 66, 26, 376, 661, 6));
processArray(list);
System.out.println(list);



Output:



[3, 62, 121, 661, 6]



Edit: Another option is to go the opposite way: to create the result list by adding those elements from the original list that are not part of a run of at least two numbers ending in 6. As a special case, if the original list has length 0 or 1, return it as is since there just can’t be two number ending in 6 in it. Otherwise create a result list. Iterate forward through the original list. For each element, if it ends in 6 and also has a neighbour on (at least) one side that ends in 6, skip it; otherwise add it to the result. Take care not to check the left neighbour of the first element or the right neighbour of the last one since they don’t exist and you will get an IndexOutOfBoundsException. I am leaving it to you to explore this option if you want to.


IndexOutOfBoundsException





I suggest using a for-loop which encloses the scope of ix. Other than that, good solution!
– Lino
Jul 3 at 10:06


ix





Also by setting int ix = array.size() - 1 will remove the computation of always having to subract ix with 1
– Lino
Jul 3 at 10:08


int ix = array.size() - 1


ix


1



As mentioned in the comments. The first solution just happens to work for your current use case. For a more flexible solution you can use the following snippet:


public static List<Integer> processList(List<Integer> list){
int encountered = 0;
for(ListIterator<Integer> it = list.listIterator(); it.hasNext(); ){
int i = it.next();
if(i % 10 == 6){
encountered++;
} else {
encountered = 0;
}
if(encountered > 1){
it.remove();
if(encountered == 2){
it.previous();
it.remove();
}
}
}
return list;
}



It uses a listIterator and a counter variable. That way we can traverse the list, count how many 6 there are and if its more than 2 in a row then remove them.


listIterator



When not using an iterator you begin to skip elements once you start removing some. Because when removing an element at an index, the List is shortened. Hence the element 1 index above will slide into the missing spot. When you then increment the index in the next step you'll have skipped an element.



OLD



I would suggest using an iterator and 2 for loops to achieve that:


public static List<Integer> processList(List<Integer> list){
for(Iterator<Integer> it = list.iterator(); it.hasNext(); ){
for(int i = it.next(); i % 10 == 6 && it.hasNext(); i = it.next()){
it.remove();
}
}
return list;
}



The first for loop iterates the list as usual, where as the second one will remove the numbers if the last digit is a 6.


6





Thanks @Lino. It worked.
– Alchemist
Jul 3 at 8:10





@ManishWadkar You're welcome!
– Lino
Jul 3 at 8:11





What should be the result if the list is 16, 1, 26, 2, 36, 46? I would expect 16, 1, 26, 2. Your code gave me 1, 2, 46. I agree in using two loops.
– Ole V.V.
Jul 3 at 9:15






@OleV.V. I updated the answer with a more solid solution.
– Lino
Jul 3 at 9:37





I am sorry, it doesn’t work correctly. For a list of 16, 1, 26, 36, 2, 46, 56, 66, 3, 76, 86, 96, 106 I had expected 16, 1, 2, 3, but I got just 16.
– Ole V.V.
Jul 3 at 9:59



There is a small problem within the for loop. As your for loop iterates through Arraylist, the value of i increments meanwhile the size your Arraylist decrease because of you're removing the elements ending with 6 .





It’s true. The other problem (of which the asker was probably already aware) is that the code always removes two such elements at a time, so of there are, say, three, only two of them are removed.
– Ole V.V.
Jul 4 at 4:48






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

qUs6DSjAU6LOVWC0ec1 A rn yWGHgMsVkO,YiBSt 8r,UB 3v xQ6Kl ziXy2c,m Nb8Q,H,Ff6,SNYQAw9eI,W4C2j5,M,Sgh4BkmIrK9bo
8TDEtTn XuzGu,0SsJg7hubJ,WU6yGM9pe VvyDxLnN9EL,fdq2FA,opJIKxG2t9Wq07B,RPSlWp68cGLnLHmKLB0PaEiSwJ u8,9

Popular posts from this blog

PHP contact form sending but not receiving emails

Do graphics cards have individual ID by which single devices can be distinguished?

Create weekly swift ios local notifications