• + 0 comments

    My answer in Typescript, note idea and improvement in comment

    const YES = 'yes', NO = 'no'
    function almostSorted(arr: number[]): void {
        const check_is_sorted = (arr: number[]): boolean => {
            /**
             * idea: check over array, if is there any decrement, the array is not sorted
             * -> improve: can add [start] and [end] index to check in that range, small effectines
             */
            let start = 0
            let end = arr.length - 1;
            for (let i = start; i < end; i++) {
                if (arr[i] > arr[i + 1]) return false;
            }
            return true;
        }
        const check_can_swap = (arr: number[]): [number, number] | undefined => {
            /**
             * idea1: loop array with 2 param x, y. try swap and check_is_sorted on each
             * -> worked
             * -> improve: too many loop -> too many check -> too slow on large input -> check idea2
             * 
             * idea2: loop array once to find the point that decrement, then find the lowest
             * number in the rest of array, swap them once and check_is_sorted once
             * -> worked, just 1 loop and 1 check -> so fast
             */
            for (let i = 0; i < arr.length - 1; i++) {
                if (arr[i] > arr[i + 1]) {
                    let x = i
                    let y = arr.indexOf(Math.min(...arr.slice(x + 1)))
                    let arr_swaped = [...arr];[arr_swaped[x], arr_swaped[y]] = [arr_swaped[y], arr_swaped[x]];
                    if (check_is_sorted(arr_swaped)) return [x + 1, y + 1]
                    return
                }
            }
            return
        }
        const check_can_reserve = (arr: number[]): [number, number] | undefined => {
            /**
             * idea: check over array, find firsts decrement and then find firsts increment, that is 2 index
             * of sub-array that need to be reserve. reserve it and check_is_sorted
             * -> worked
             * -> improve: im not sure, it work well and fast, maybe don't create new array to save memory?
             */
            let x, y, i = 0
            while (true) {
                if (x != undefined && y != undefined) {
                    let arr_reserve = [...arr.slice(0, x), ...arr.slice(x, y + 1).reverse(), ...arr.slice(y + 1)]
                    if (check_is_sorted(arr_reserve)) return [x + 1, y + 1]
                    break;
                }
                if (i >= arr.length - 1) break;
                if (x == undefined) {
                    if (arr[i + 1] < arr[i]) x = i;
                } else {
                    if (arr[i + 1] > arr[i]) y = i;
                }
                i++
            }
            return
        }
    
        // array has already sorted -> YES
        const is_sorted = check_is_sorted(arr)
        if (is_sorted) { console.log(YES); return; }
    
        // try swap
        const can_swap = check_can_swap(arr)
        if (!!can_swap) { let [x, y] = can_swap; console.log(YES); console.log(`swap ${x} ${y}`); return; }
    
        // try reverse
        const can_reserve = check_can_reserve(arr)
        if (!!can_reserve) { let [x, y] = can_reserve; console.log(YES); console.log(`reverse ${x} ${y}`); return; }
    
        // array can't be sorted by any way -> NO
        console.log(NO)
    }