/* 
1. If you sort array, then kth largest value will be n-k from beginning.
 eg: [3, 2, 1, 5, 6, 4], k=2 [1,2,3,4,5,6], n-k=4
2. Use quick sort to partition the array discarding one side of the partition after every partition. If n-k < pivot index, recurse on the left.
Otherwise recurse on right.
3. After each partition, check if pivot index === n - k and if it is return the pivot value
*/

function findKthLargest(arr, k) {
	const len = arr.length
	const kthFromlast = len - k

	if (len <= 0 || kthFromlast < 0 || kthFromlast > len) return null

	function recurse(start, end) {
		if (start === end && start === kthFromlast) {
			return arr[start]
		}

		if (start > end) return

		const randomIndex = getRandomIntInclusive(start, end)

		swap(arr, randomIndex, start)

		const pivot = arr[start]
		let smaller = start,
			bigger = start + 1

		for (bigger; bigger <= end; bigger++) {
			if (arr[bigger] < pivot) {
				smaller++
				swap(arr, smaller, bigger)
			}
		}

		swap(arr, start, smaller)

		if (smaller === kthFromlast) {
			return arr[smaller]
		} else if (kthFromlast < smaller) {
			return recurse(start, smaller - 1)
		} else {
			return recurse(smaller + 1, end)
		}
	}
	return recurse(0, arr.length - 1)
}

// Helper functions:
function getRandomIntInclusive(min, max) {
	min = Math.ceil(min)
	max = Math.floor(max)
	return Math.floor(Math.random() * (max - min + 1)) + min //The maximum is inclusive and the minimum is inclusive
}

function swap(array, i, j) {
	let temp = array[i]
	array[i] = array[j]
	array[j] = temp
}

/* 
Time Complexity - O(n)

For average case,consider that the pivot is always in middle. But since we're discarding one half

n + n/2 + n/4 + ..... n/n ==> O(2n)

Worst case: O(n^2)
*/
const arr = [3, 2, 1, 5, 6, 4]
console.log(findKthLargest(arr, 2))