Almost increasing sequence coding problem - java

I am trying to solve a coding problem. The problem is following:
Given a sequence of integers as an array, determine whether it is possible to obtain a strictly increasing sequence by removing no more than one element from the array.
For example:
[1,3,2,1] is false
[1,3,2] is true
I implemented it in Java. The code is as follows:
boolean almostIncreasingSequence(int[] sequence) {
int count =0;
for(int i =0; i < sequence.length; i++){
if (sequence[i] <= sequence[i-1]){
count++;
}
if(count>1){
return false;
}
if(sequence[i] <= sequence[i-2] && sequence[i+1] <= sequence[i-1]){
return false;
}
}
return true;
}
This is the following error:
Execution error on test 1: Your program had a runtime error.
Any help will be appreciated. It seems a small problem but I can't resolve it.

One implementation can be based on remove just 1 element when strictly ascending condition is not achieved.
public class TestAlmostIncreasingSequence {
public static boolean almostIncreasingSequence(int[] sequence)
{
if(sequence==null) return false;
//mandatory to remove just 1 element, if no one(or more) removed then false
boolean flag_removed=false;
for(int i=1, prev=sequence[0];i<sequence.length;i++)
{
if(prev>=sequence[i] && flag_removed==false)
{
//mark removed
flag_removed=true;
}
//if element was removed then false
else if(prev>=sequence[i] && flag_removed==true)
{
return false;
}
else
{
//change only if element removed is not the current
//comparisons will not be done with removed element
prev=sequence[i];
}
//System.out.println(prev);
}
//could have a strictly increased arr by default which will return false [1,2,3]
return flag_removed;
}
public static void main(String[] args)
{
//only for printing purpose
String arr="";
int s1[] = {1,2,3,1};
arr=Arrays.stream(s1).mapToObj(t->String.valueOf(t)).
collect(Collectors.joining(",","[","]"));
System.out.println(arr+"\n"+almostIncreasingSequence(s1)+"\n");
int s2[] = {1,2,3};
arr=Arrays.stream(s2).mapToObj(t->String.valueOf(t)).
collect(Collectors.joining(",","[","]"));
System.out.println(arr+"\n"+almostIncreasingSequence(s2)+"\n");
int s3[] = {1,2,3,1,2};
arr=Arrays.stream(s3).mapToObj(t->String.valueOf(t)).
collect(Collectors.joining(",","[","]"));
System.out.println(arr+"\n"+almostIncreasingSequence(s3)+"\n");
int s4[] = {1};
arr=Arrays.stream(s4).mapToObj(t->String.valueOf(t)).
collect(Collectors.joining(",","[","]"));
System.out.println(arr+"\n"+almostIncreasingSequence(s4)+"\n");
int s5[] = {1,1};
arr=Arrays.stream(s5).mapToObj(t->String.valueOf(t)).
collect(Collectors.joining(",","[","]"));
System.out.println(arr+"\n"+almostIncreasingSequence(s5)+"\n");
int s6[] = null;
arr="null";
System.out.println(arr+"\n"+almostIncreasingSequence(s6)+"\n");
}
}
Output
[1,2,3,1]
true
[1,2,3]
false
[1,2,3,1,2]
false
[1]
false
[1,1]
true
null
false
Note: The implementation have a case when the result is wrong [1,5,2,3], just update with one more branch with removed element=the previous one(not the current) and check both branched (one true means true)
This should fix the case
//method name is misguided, removePrev is better
public static boolean removeCurrent(int[] sequence)
{
if(sequence==null) return false;
//mandatory to remove just 1 element, if no one remove then false
boolean flag_removed=false;
for(int i=1, prev=sequence[0];i<sequence.length;i++)
{
if(prev>=sequence[i] && flag_removed==false)
{
//mark removed
flag_removed=true;
}
//if element was removed then false
else if(prev>=sequence[i] && flag_removed==true)
{
return false;
}
//compared element will be the current one
prev=sequence[i];
//System.out.println(prev);
}
//could have a strictly increased arr by default which will return false [1,2,3]
return flag_removed;
}
and use
int s1[] = {1,5,2,3};
arr=Arrays.stream(s1).mapToObj(t->String.valueOf(t)).
collect(Collectors.joining(",","[","]"));
boolean result= (almostIncreasingSequence(s1)==false) ? removeCurrent(s1) : true;
System.out.println(arr+"\n"+result +"\n");
Output
[1,5,2,3]
true (from removeCurrent_branch)
Seems one more case is wrong [5,6,3,4], means need to see if element[i-2](only after remove element) is not greater then current and 'prev' on last branch.
6>3 remove 6 (prev=3, 3<4 but [5>4 or 5>3] so false)
public static boolean removeCurrent(int[] sequence)
{
if(sequence==null) return false;
//mandatory to remove just 1 element, if no one remove then false
boolean flag_removed=false;
for(int i=1, prev=sequence[0], twoprev=Integer.MIN_VALUE;i<sequence.length;i++)
{
if(prev>=sequence[i] && flag_removed==false)
{
//mark removed
flag_removed=true;
if(i>=2) twoprev=sequence[i-2];
}
//if element was removed then false
else if(prev>=sequence[i] && flag_removed==true)
{
return false;
}
else if(twoprev>=sequence[i] || twoprev>=prev)
{
return false;
}
//compared element will be the current one
prev=sequence[i];
//System.out.println(prev);
}
//could have a strictly increased arr by default which will return false [1,2,3]
return flag_removed;
}
Output
[5,6,3,4]
false
Now, as far as I see all cases seems covered.
Brute force can also generate a solution but will be less optimal.(use a loop to remove an element, sort the result and compare with base)
public class TestInc {
public static void main(String[] args)
{
int s1[] = {1,1,2,3};
System.out.println(checkInc(s1));
}
public static boolean checkInc(int[] arr)
{
if(arr==null || arr.length==1) return false;
List<Integer> lst = Arrays.stream(arr).boxed().collect(Collectors.toList());
//remove this check if requirement is other(or return true)
if(checkIfAlreadySortedAsc(lst))
{
return false;
}
for(int i=0;i<lst.size();i++)
{
List<Integer> auxLst = new ArrayList<Integer>(lst);
auxLst.remove(i);
List<Integer> sorted = new ArrayList<Integer>(auxLst);
sorted = sorted.stream().distinct().sorted().collect(Collectors.toList());
if(auxLst.equals(sorted))
{
// System.out.println("=");
return true;
}
else
{
// System.out.println("!=");
}
}
return false;
}
//any ascending sorted list will be the same type if remove one element
//but as requirement on this case will return false
//(or don't use method in want other)
public static boolean checkIfAlreadySortedAsc(List<Integer> lst)
{
List<Integer> auxLst = new ArrayList<Integer>(lst);
auxLst = auxLst.stream().distinct().sorted().collect(Collectors.toList());
if(auxLst.equals(lst))
{
return true;
}
return false;
}
}
Output
[1,1,2,3]
true

This line would produce an ArrayIndexOutOfBoundsException when i == 0 because it will attempt to access sequence[-1]
if (sequence[i] <= sequence[i-1]){

Related

returning a boolean value from a recursive method

this is a supplementary question aligned to a question I asked recently. I have the following recursive code that will give me the largest number from a List of integers
static int maximum (List<Integer> a)
{
if ((a.getTail().isEmpty()))
return 0;
else {
int n = maximum(a.getTail());
System.out.println(n);
if (a.getHead() > n) {
return (a.getHead());
} else {
return m;
}}
}
This is helpful. But what I really want to do is to be able to return a Boolean value true or false depending on where the list increases in value or decreases. So my method would become:
static boolean maximum (List<Integer> a)
{
if ((a.getTail().isEmpty()))
return true;
else {
int n = maximum(a.getTail());
System.out.println(n);
if (a.getHead() > n) {
return true;
} else {
return false;
}}
}
But this will not run. The challenge I am faced with is that the recursive call as I have written returns an integer so that I can compare the previous maximum with the current maximum ----- if (a.getHead() > m).
What I want to do is to try and complete the assessment of the current verses previous max within the recursive call so that I only have to return a Boolean, true or false.
So for example if as the recursion occurs the list continually increases then the Boolean stays true but if at any point it decreases then it will give a false:
1,2,3,4 = true
1,2,4,3 = false
Thank you for your help I am really struggling with the whole concept of recursion.....
Some things you might have missed:
in a function, a return statement terminates (break) the function immediatly. So in
if(...) { return ...; }
else {...}
→ else is redundant, as if the condition is true, the function is already terminated (break)
Something like a==0 has a boolean value (true or false). So
if(i==0) { return true; }
else { return false; }
can be shortened to return count==0;
I recommend to always use braces, because something like if(i==0) ++i; break;, means if(i==0) {++i;}. break; will be called in any case.
what you want, is something like this:
static boolean is_sorted(List<Integer> list)
{
return is_sorted_from(0, list);
}
static boolean is_sorted_from(int index, List<Integer> list)
{
if(index+1 >= a.size()) { return true };
return list.get(index) < list.get(index+1)
&& is_next_sorted(index+1, list);
}
static boolean maximum (List<Integer> a, boolean cont){
if(cont){
if ((a.getTail().isEmpty())){
cont = false;
}else {
int n = maximum(a.getTail());
System.out.println(n);
if (a.getHead() > n) {
maximum(a.getHead(), cont);
} else {
maximum(n, cont);
}
}
}
return cont;
}
I'd say to make the method void or return the List, but I left it as boolean since that is technically what your question asked for.
You would just call the method with cont having the value of true. By using two parameters, you can continue comparing your max function while simultaneously using a boolean as your recursion flag. You would not be able to return your maximum however, but you could work around this by setting the maximum to either a class instance or to an object that you have as your third parameter (Double, Integer, etc.).

Java Stacks/Cannot Find Logic Error

For my CS class, I had to create a boolean function isBalanced(String x) that takes a string and evaluates the amount of brackets/parentheses and returns true if the brackets match up to its pair (e.g; { is a pair of }, ( is a pair of ), [ is a pair of ], etc.). The function would return true if the brackets correctly matched up, false if otherwise. For clarification, MyStack() is my own implementation of the Java stack interface if you are wondering what that Object was.
Examples of how the code would work and return:
{A(B[C])D} would return true.
{A(B[C)]D} would return false.
The problem in my code is a logic error. For some reason, my function is returning true if there is a missing bracket, which should return false.
{A(B)C would return false, but my code reads it as true. Do you have any solutions that would help my code work properly? Thanks!
Balancer.java
public static boolean isBalanced(String x) {
MyStack<String> stack = new MyStack();
if (x.substring(0,1).equals("}") || x.substring(0,1).equals(")") || x.substring(0,1).equals("]")) {
return false;
}
for (int i=0; i<x.length(); i++) {
if (x.substring(i,i+1).equals("{") || x.substring(i,i+1).equals("(") || x.substring(i,i+1).equals("[")) {
stack.add(x.substring(i,i+1));
}
if (x.substring(i,i+1).equals("}") || x.substring(i,i+1).equals(")") || x.substring(i,i+1).equals("]")) {
if (x.substring(i,i+1).equals("}") && stack.peek().equals("{")) {
stack.pop();
} else if (x.substring(i,i+1).equals(")") && stack.peek().equals("(")) {
stack.pop();
} else if (x.substring(i,i+1).equals("]") && stack.peek().equals("[")) {
stack.pop();
} else {
return false;
}
}
}
return true;
}
This file, labeled Main.java, is just a tester. I have omitted the other cases where the code works. The reason why the function should return false is that there is a missing } which should be at the end, but there is none, yet my function returns true for some reason.
Main.java
public static void main(String[] args) {
...
String test4 = "{AA[B(CDE{FG()T})V]";
System.out.println("Missing final close (empty stack case)");
System.out.println("Should be false, is: " + Balancer.isBalanced(test4)); // does not work
}
You have a series of conditions that only pop the stack if a matching pair of brackets are found. I think you're overcomplicating things - if an opening bracket is found, push it to the stack. If a closing parenthesis is found, pop the stack and make sure that they match. E.g.:
private static final Map<Character, Character> CLODSE_TO_OPEN = new HashMap<>();
static {
CLODSE_TO_OPEN.put(')', '(');
CLODSE_TO_OPEN.put(']', '[');
CLODSE_TO_OPEN.put('}', '{');
}
public static boolean isBalanced(String x) {
Stack<Character> stack = new Stack<>();
for (int i = 0; i < x.length(); ++i) {
char c = x.charAt(i);
if (CLODSE_TO_OPEN.containsValue(c)) {
stack.push(c);
} else if (CLODSE_TO_OPEN.containsKey(c)) {
try {
if (!CLODSE_TO_OPEN.get(c).equals(stack.pop())) {
return false;
}
} catch (EmptyStackException e) {
return false;
}
}
}
return stack.isEmpty();
}

Trying to compare the contents two Iterators, how?

EDIT: With your help I managed to fix my problem. I have edited my code to now show how I had to have it set up to get it working.
Currently I am having trouble coding a part which compares the content of two iterators. As part of the requirements for my assignment, I need to use a linkedlist to store the individual characters of the entered String. I have gotten to the point where I have two iterators which would contain the input one way and the reverse way.
String palindrom = input.getText();
String [] chara = palindrom.split (""); //this is successfully splitting them, tested.
int length = palindrom.length( ); // length == 8
System.out.println (length); //can use this for how many checks to do?
LinkedList ll = new LinkedList(Arrays.asList(chara));
Iterator iterator = ll.iterator();
Iterator desIterator = ll.descendingIterator();
/*while(iterator.hasNext() ){
System.out.println(iterator.next() );
}
while(desIterator.hasNext() ){
System.out.println(desIterator.next() );
}*/
boolean same = true;
while(iterator.hasNext()){
if(!iterator.next().equals(desIterator.next())){
same = false;
break;
}
}
And using the System.out I can see that they are being stored correctly, but I don't know how to check if the iterators store the same contents. What would be one of the simplest methods to compare the two iterators or convert them into something I can compare? To clarify I want to verify they contain the same elements in the same order.
boolean same = true;
while(iterator.hasNext()){
if(!desIterator.hasNext() || !iterator.next().equals(desIterator.next())){
same = false;
break;
}
}
System.out.println(same);
You need to iterate over both iterators simultaneously, i.e. with one loop. Here is a general comparison function (0 when equal, < 0 when A < B, > 0 when A > B):
static <T extends Comparable<S>, S> int compare(Iterator<T> a, Iterator<S> b) {
while (a.hasNext() && b.hasNext()) {
int comparison = a.next().compareTo(b.next());
if (comparison != 0) {
return comparison;
}
}
if (a.hasNext())
return 1;
if (b.hasNext())
return -1;
return 0;
}
To just check if they are equal, this can be simplified:
static <T, S> boolean equals(Iterator<T> a, Iterator<S> b) {
while (a.hasNext() && b.hasNext()) {
if (!a.next().equals(b.next())) {
return false;
}
}
if (a.hasNext() || b.hasNext()) {
// one of the iterators has more elements than the other
return false;
}
return true;
}
Guava implements this as Iterators.elementsEqual.
In both answers throw NullPointerException, if iterator.next() == null. This method is more optimal.
public static boolean equals(Iterator i1, Iterator i2) {
if (i1 == i2) {
return true;
}
while (i1.hasNext()) {
if (!i2.hasNext()) {
return false;
}
if (!Objects.equals(i1.next(), i2.next())) {
return false;
}
}
if (i2.hasNext()) {
return false;
}
return true;
}

Determines if the array list is sorted

I need to estimate if the array list is sorted (don't sort).
When Strings are sorted, they are in alphabetical order.
I try to use compareTo() method to determine which string comes first
And return true if the array list is sorted, else false.
Code:
public boolean isSorted()
{
boolean sorted = true;
for (int i = 1; i < list.size(); i++) {
if (list.get(i-1).compareTo(list.get(i)) != 1) sorted = false;
}
return sorted;
}
Easy test:
ArrayList<String> animals = new ArrayList<String>();
ArrayListMethods zoo = new ArrayListMethods(animals);
animals.add("ape");
animals.add("dog");
animals.add("zebra");
//test isSorted
System.out.println(zoo.isSorted());
System.out.println("Expected: true");
animals.add("cat");
System.out.println(zoo.isSorted());
System.out.println("Expected: false");
animals.remove("cat");
animals.add(0,"cat");
System.out.println(zoo.isSorted());
System.out.println("Expected: false");
**Output:**
false
Expected: true
false
Expected: false
false
Expected: false
This easy test shows only 1/3 coverage.
How to solve this issue.
You have a small bug in your method. Should be :
public boolean isSorted()
{
boolean sorted = true;
for (int i = 1; i < list.size(); i++) {
if (list.get(i-1).compareTo(list.get(i)) > 0) sorted = false;
}
return sorted;
}
>0 instead of !=1, you can't be sure that 1 is returned..
Change the condition :
if (list.get(i - 1).compareTo(list.get(i)) >0)
You should check for >0 instead of !=-1 .
Go through the documentation of compareTo()
the value 0 if the argument string is equal to this string; a value less than 0 if this string is lexicographically less than the string argument; and a value greater than 0 if this string is lexicographically greater than the string argument.
Try this
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class Sort {
public static void main(String []args) {
List<String> l1=new ArrayList<String>();
List<String> l2=new ArrayList<String>();
l1.add("a");
l1.add("b");
l1.add("c");
l2.add("b");
l2.add("c");
l2.add("a");
if(isSorted(l1)){
System.out.println("already sorted");
}
else{
Collections.sort(l1);
}
}
public static boolean isSorted(List<String> list){
String previous = "";
for (String current: list) {
if (current.compareTo(previous) < 0)
return false;
previous = current;
}
return true;
}
}
You can write a utily method like isSortedList(List list).
public static boolean isSortedList(List<? extends Comparable> list)
{
if(list == null || list.isEmpty())
return false;
if(list.size() == 1)
return true;
for(int i=1; i<list.size();i++)
{
if(list.get(i).compareTo(list.get(i-1)) < 0 )
return false;
}
return true;
}
As as utility method, you can use it anywhere.
you have to change the compareTo expresion to any positive number, which indicates that the previous element is alphabetically after the current element, hence the list is not ordered
public boolean isSorted()
{
boolean sorted = true;
for (int i = 1; i < list.size(); i++) {
if (list.get(i-1).compareTo(list.get(i)) > 0) sorted = false;
}
return sorted;
}
You need to check for unsorted case.
This means that if you are assuming sorting ascending, the unsorted case will be finding an element at index i being out of order from index i-1
where element[i] < element[i-1].

getting concurrent modification exception just for trying to read an element of an ArrayList

I know i will get this exception when i try to modify or remove from the list, but just for reading from it ?! What is the solution here ?
public boolean recieveHello(Neighbor N, HelloMsg H) {
Iterator<Neighbor> I = NTable.iterator();
Iterator<Neighbor> J = NTable.iterator();
if(!J.hasNext()) {
this.NTable.add(N);
}
while(I.hasNext()) {
if(I.next().nid == N.getnid()) { /*EXCEPTION IS HERE*/
//case where the node is already present in the NTable
}
else {
N.setnhrc(0);
this.NTable.add(N);
//case where the node is to be added to the NTable
}
}
return true;
}
By the way, I must mention that NTable is an arrayList and is a member of the class whose method this is
EDIT
I solved the problem using ::
public boolean recieveHello(Neighbor N, HelloMsg H) {
Iterator<Neighbor> I = NTable.iterator();
Iterator<Neighbor> J = NTable.iterator();
if(!J.hasNext()) {
this.NTable.add(N);
}
boolean flag = false;
for (int i=0; i<NTable.size(); i++) {
if(NTable.get(i).nid == N.getnid()) {
//case where the node is already present in the NTable
}
else {
flag = true;
N.setnhrc(0);
this.NTable.add(N);
//case where the node is to be added to the NTable
}
}
if(flag == true) {
}
return true;
}
Well you're changing the size of the list while iterating over it when you say
this.NTable.add(N);
So, instead keep track of which ones to add in a separate list, then append the items after the first iteration.

Categories