-2

I have given the following problem where I am stuck right now. I am not having the perfect logic for this. Here is the problem below :

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.

Example 1:

For sequence = [1, 3, 2, 1], the output should be false. 
There is no one element that can be removed to get a strictly an increasing sequence

Example 2:

For sequence = [1, 3, 2], the output should be true.
You can remove 3 or 2 to get the strictly increasing sequence [1, 2] or [1,3] respectively

I have tried as follows :

boolean almostIncreasingSequence(int[] sequence) {
    ArrayList<Integer> list = new ArrayList<>();

    for(int i=0; i<sequence.length;i++) {
        list.add(sequence[i]);
    }

    int omittedCounter = 0;

    boolean status = true;

    for(int i=1; i<list.size();i++) {
        if(list.get(i-1) >= list.get(i)) {
            omittedCounter ++;
            list.remove(i-1);
            break;
        }
    }

    if (omittedCounter > 0) {
        for(int i=1; i<list.size();i++) {
            if(list.get(i-1) >= list.get(i)) {
                omittedCounter ++;
                list.remove(i-1);
                break;
            }
        }
    }

    if (omittedCounter > 1) {
        status = false;
    }

    return status;
}

But I am having trouble when I am given this sequence: [1, 2, 3, 4, 3, 6]

Output:           false
Expected Output:  true
Yahya
  • 13,349
  • 6
  • 30
  • 42
Sumon Bappi
  • 1,937
  • 8
  • 38
  • 82
  • Why don't you try validateArray(), if false then remove element @ index i, then validate(). If you pop/push all elements from the array and all are false, return false. Otherwise return true if validate passed at any point. – ZeldaZach Jul 04 '17 at 21:59
  • My hint: go backwards. Try writing down some increasing sequences, then _adding_ one element to make it non-increasing. Look over the results and see if you can spot some way to detect when that happened. Make sure you include cases where you add an element at the beginning, and where you add an element at the end. If you can start to see a method that you could use by hand to detect this, then start translating it into code. – ajb Jul 04 '17 at 22:05
  • That's a very vague hint, but I think doing anything more than that to help you avoid a 5000-point penalty would be helping you cheat. – ajb Jul 04 '17 at 22:06
  • Possible duplicate of [(Java) Check array for increasing elements](https://stackoverflow.com/questions/7143118/java-check-array-for-increasing-elements) – DevilsHnd - 退職した Jul 05 '17 at 00:46

4 Answers4

3

This is possible in linear time O(n) and constant space O(1).

public static boolean analyse(int[] sequence) {
    if (sequence.length <= 2) return true;
    int a = sequence[0];
    int b = sequence[1];
    int drops = 0;
    if (a >= b) {
        drops++;
        a = b - 1; //drop a, keeping the smallest, fake a value for the first loop
    }
    // consider 3 items at a time, a, b & c
    for (int i = 2; i < sequence.length; i++) {
        int c = sequence[i];
        if (a < b && b < c) {
            // all good, move on
            a = b;
            b = c;
            continue;
        }
        // we'll have to drop one of them
        drops++;
        if (drops > 1) return false;
        // which one will we drop, b or c?
        if (a < c) {
            // drop b (a,b -> a,c)
            b = c;
        } // else drop c (a,b -> a,b)
    }
    return true;
}
weston
  • 54,145
  • 21
  • 145
  • 203
  • Good approach though! BTW, even if ya edit your answer, I will not withdraw the upvote, If ya got what I mean! – Yahya Jul 06 '17 at 17:24
  • I took vote away when someone spotted the failing case. I forgot to give back when you fixed it. Sorry – weston Jul 06 '17 at 17:28
1

One way to achieve that is doing something like this (approx. O(n*2) in worst scenario):

static boolean analyse(int[] sequence){
    int counter =0;
    //LinkedHashSet Keep Order But Remove Duplicates
    Set<Integer> set = new LinkedHashSet<>();
    //Copy Array To The Set
    for(int i=0; i<sequence.length; i++){
        set.add(sequence[i]);
    }
    //Count How Many Duplicates Found
    counter+=(sequence.length-set.size());

    if(counter>1){return false;}
    Integer[] seq = set.toArray(new Integer[set.size()]);

    // Loop Through The Array
    // If Any Breaks The Rule -> Increment Counter
    for(int i=0; i<seq.length-1; i++){
       if(i==0 && seq[i]>seq[i+1]) {counter++;}
       if(i!=0 && !(seq[i]<seq[i+1]&&seq[i-1]<seq[i])){counter++;}
       if(counter>1){return false;}
    }
    return true;
}

Test

int [] s  = {1,2,3,4,3,5};
int [] s1 = {1,2,3,4,3,6,1};
int [] s2 = {1,2,3,4,3,6};
int [] s3 = {1,2,3,10,10,6};
int [] s4 = {1,2,3,10,3,6};
System.out.println(analyse(s));
System.out.println(analyse(s1));
System.out.println(analyse(s2));
System.out.println(analyse(s3));
System.out.println(analyse(s4));

Output

true
false
true
false
false
Yahya
  • 13,349
  • 6
  • 30
  • 42
  • That's great, I like the set use. You're missing opportunities to finish early though. And that also makes the LinkedHashSet overkill. https://ideone.com/cp73AB – weston Jul 05 '17 at 03:01
  • So use of a set means it uses O(n) space. I'm actually sure this can be solved in constant space, O(1). When you're considering 1000th item, why does it matter if it duplicates the 10th? – weston Jul 05 '17 at 10:23
  • @Yahya thanks for your reply. But it does not behave properly for the following : `Input: sequence: [40, 50, 60, 10, 20, 30] Output: true Expected Output: false` – Sumon Bappi Jul 05 '17 at 14:02
  • There are both time and space considerations. Timewise it's O(n), but also space wise, the solution takes O(n) memory. It should be possible in constant space O(1). i.e. if I increase the size of the input, no more memory should be required to solve it. – weston Jul 05 '17 at 14:13
  • @SumonBappi It's a bug, ... I fixed.. check now. – Yahya Jul 05 '17 at 14:22
  • Yes, they are both taken into consideration. I think there must be a solution that's O(n) time, and O(1) space. – weston Jul 05 '17 at 14:25
  • @weston [Big Notation Definition](https://xlinux.nist.gov/dads/HTML/bigOnotation.html) A theoretical measure of the execution of an algorithm, usually the ***time*** or memory needed, given the problem size n, which is usually the number of items. I'm pretty sure it's not `O(1)` though! – Yahya Jul 05 '17 at 14:25
  • exactly "...usually the time or **memory** needed." I am saying that there is a solution that takes O(1) memory (space). I am not saying yours *is* O(1) but that there *could* be a solution that is. – weston Jul 05 '17 at 14:27
  • @weston what made me laugh really is your saying "*There should be ...*" almost in all comments, because usually in this case, ya should probably provide the solution and not only a suggestion or a guessing!. Have a nice day man! – Yahya Jul 05 '17 at 14:54
  • That's fair enough. Just a theory, sorry to pollute your comments with it. I am trying to think of a solution, I will let you know if I post one. – weston Jul 05 '17 at 15:08
  • Now the problem is for this : `Input: sequence: [10, 1, 2, 3, 4, 5] Output: true Expected Output: false` – Sumon Bappi Jul 05 '17 at 15:09
  • @SumonBappi How come the *Expected Output is false*?! If we remove one element which is `10` it will be strictly in a ascending order though! According to this sequence, it's giving the correct output as what should be expected ! – Yahya Jul 05 '17 at 15:12
0

I have one answer of it which have time complexity of N*Log(N). We will find out longest almost increasing sequence and check if it is equal to or greater than (N-1) , Then we will return true else false.

Checkout :

public int FindIndex(int A[], int l, int r, int key) {
    while (r - l > 1) {
        int m = l + (r - l) / 2;
        if (A[m] >= key) r = m;
        else l = m;
    }
    return r;
}

public boolean LongestIncreasingSubsequenceLength(int A[], int size) 
{
    int[] Seq = new int[size];
    int len;
    Seq[0] = A[0];
    len = 1;
    for (int i = 1; i < size; i++) {
        if (A[i] < Seq[0]) Seq[0] = A[i];
        else if (A[i] > Seq[len - 1]) Seq[len++] = A[i];
        else Seq[FindIndex(Seq, -1, len - 1, A[i])] = A[i];
    }
    return len >= size - 1;
}
NIKUNJ KHOKHAR
  • 791
  • 6
  • 17
-2

In Python3,

def almostIncreasingSequence(sequence): # checking whether there are more than one repeated element, this is to decrease complexity! As we need strictly increasing order after removal of one item, there cannot be more than one repeated item if only removing that is to give us the strictly increasing order. if len(sequence) - len(set(sequence)) > 1: return False # delete/pop one element from the both copies of list, sort one list and compare with the other copy to check whether both copies are equal for i, n in enumerate(sequence): temp = sequence.copy() temp2 = sequence.copy() temp.pop(i) temp2.pop(i) temp.sort() if temp == temp2: return True return False

Tatshini
  • 11
  • 2
  • OP may not know python. If you cannot produce java code, please add a description of your algorithm in pseudo code. – Sirion Mar 26 '20 at 08:32
  • @Sirion, Added comments - Python has no Array.. Hence list is used. – Tatshini Apr 03 '20 at 08:33
  • Thanks for the effort, but... your code may still be not understandable by people how don't know Python. E.g., take the line `if len(sequence) - len(set(sequence)) > 1` why does it fit its goal? (rhetorical question, I know Python). On the other hand comments like `checking whether there are more than one repeated element` are not enough detailed since the question of the OP concerns exactly how to implement the algorithm he needs. – Sirion Apr 03 '20 at 09:12
  • @Sirion is it better/clearer now? Sorry I am very new here! – Tatshini May 08 '20 at 07:32
  • It's better, but there still could be some pretty obscure points for non Python users (e.g. one may not imagine that `set(sequence)` eliminates all duplicated entries). In general, you should avoid answering a question on a specific programming language using another one. As the question already has an accepted answer, there is no point to further revise your answer, just keep these hints in mind next time. – Sirion May 08 '20 at 13:08