Find the 1 non-repeating element in a given array without XOR or Map in O(n) - data-structures

How can I find the one non repeating element in an array that all other elements appear exactly twice, when I'm not allowed to use a hash map or the operator XOR?
In O(n) time complexity
Examples:
Input
arr[] = {14, 1, 14, 4, 12, 2, 1, 2, 3, 3}
Output
4

If you want to do it in java Script then inside a for loop you can check if the first index and the last index of that item are same then return that item else return -1.
function getFirstDistinctNumber() {
arr = [14, 1, 14, 4, 12, 2, 1, 2, 3, 3];
for (let i=0; i<arr.length; i++) {
if(arr.indexOf(arr[i]) == arr.lastIndexOf(arr[i])) {
return arr[i];
}
}
return -1;
}
console.log(getFirstDistinctNumber());
And also in java, you can do the same but lastIndexOf() is not present for array. so you can do it by creating an array list
import java.util.*;
class FindDistinct {
public static void main(String[] args) {
// create an empty array list with an initial capacity
ArrayList<Integer> inputList = new ArrayList<Integer>();
// use add() method to add values in the list
inputList.add(14);
inputList.add(1);
inputList.add(14);
inputList.add(4);
inputList.add(12);
inputList.add(2);
inputList.add(1);
inputList.add(2);
inputList.add(3);
inputList.add(3);
for(int i=0; i< inputList.size(); i++) {
if(inputList.indexOf(inputList.get(i)) == inputList.lastIndexOf(inputList.get(i))) {
System.out.println(inputList.get(i));
break;
}
}
}
}

sorting the array and then using stack, you can find the required element
# code is in python
arr = [14, 1, 14, 4, 12, 2, 1, 2, 3, 3,12]
# sort the array
arr = sorted(arr)
# use a stack to find out the required element
stack = []
for ele in arr:
if len(stack) == 0:
stack.append(ele)
elif stack[-1]==ele:
stack.pop()
else:
stack.append(ele)
print(stack[-1]) # item with one occuerence
# output : 4

There's a way compute that in O(1) space and O(n log n) time. Simply binary search the value. For a given number x count the number of elements that less or equal to x - if this value is odd then the number you're looking for is less or equal to x, otherwise if it's even, then it's greater.
(technically the running time is O(n log k) where k is max_value - min_value from the elements in the array, but there's a way to modify it to work in O(n log n) if needed.)

I found the answer to the problem, using this video: https://www.youtube.com/watch?v=aZneq1PWFkg
You can get the median in O(n) time, then you can sort all of the numbers which are greater or equal to the median to the right of it and the ones that are less than it, to be on the left in O(n) time. now everything is sorted in a way that everything that's bigger than the median is on the left and bigger is on the right.
Then You search the array once more to see if the median has a twin, if it doesn’t, you’re done that’s your lonely number, if you’ve found the twin on the left side and the index of the median is odd then you take everything that’s on the left side of the median including it (and throw the others away), same for if you’ve found it in the right side. If the medians index is even you take the opposite side that you find the twin on without including the median. You keep doing the same algo from beginning until you’ve found it.
Then you can get T(n) = T(n/2) + Θ(n)
And with masters theorem you get Θ(n).

In c++ using O(n) compexity.
int arrayUnique(int *arr, int size)
{
int count;
for(int i=0;i<size;i++)
{
count=0;
for(int j=0;j<size;j++)
{
if(i==j){
continue;
}
if(arr[i] == arr[j]){
count=1;
}
}
if(count==0){
return arr[i];
}
}
}

Related

Sorted squares of numbers in a list in O(n)?

Given a list of integers in sorted order, say, [-9, -2, 0, 2, 3], we have to square each element and return the result in a sorted order. So, the output would be: [0, 4, 4, 9, 81].
I could figure out two approaches:
O(NlogN) approach - We insert the square of each element in a hashset. Then copy the elements into a list, sort it and then return it.
O(n) approach - If there is a bound for the input elements (say -100 to -100), then we create a boolean list of size 20000 (to store -10000 to 10000). For each of the input elements, we mark the corresponding square number as true. For e.g., for 9 in the input, I will mark 81 in the boolean array as true. Then traverse this boolean list and insert all the true elements into a return list. Note that in this we make an assumption - that there is a bound for the input elements.
Is there some way in which we could do it in O(n) time even without assuming any bounds for the input?
Well I can think of an O(n) approach
Split the input into 2 lists. One with negative numbers, let's call this list A. And one with positive numbers and 0, list B. This is done while preserving the input order, which is trivial : O(n)
Reverse list A. We do this because once squared, the greater than relation between the elements if flipped
Square every item of both list in place : O(n)
Run a merge operation not unlike that of a merge sort. : O(n)
Total: O(n)
Done :)
Is there some way in which we could do it in O(n) time even without assuming any bounds for the input?
Absolutely.
Since the original list is already sorted you are in luck!
given two numbers x and y
if |x| > |y| then x^2 > y^2
So all you have to do is to split the list into two parts, one for all the negative numbers and the other one for all the positive ones
Reverse the negative one and make them positive
Then you merge those two lists into one using insertion. This runs in O(n) since both lists are sorted.
From there you can just calculate the square and put them into the new list.
We can achieve it by 2 pointer technique. 1 pointer at the start and other at the end. Compare the squares and move the pointers accordingly and start allocating the max element at the end of the new list.
Time = O(n)
Space = O(n)
Can you do it inplace ? To reduce space complexity.
This can be done with O(n) time and space. We need two pointers. The following is the Java code:
public int[] sortedSquares(int[] A) {
int i = 0;
int j = A.length - 1;
int[] result = new int[A.length];
int count = A.length - 1;
while(count >= 0) {
if(Math.abs(A[i]) > Math.abs(A[j])) {
result[count] = A[i]*A[i];
i++;
}
else {
result[count] = A[j]*A[j];
j--;
}
count--;
}
return result;
}
Start from the end ad compare the absolute values. And then create the answer.
class Solution {
public int[] sortedSquares(int[] nums) {
int left = 0;
int right = nums.length -1;
int index = nums.length- 1;
int result[] = new int [nums.length];
while(left<=right)
{
if(Math.abs(nums[left])>Math.abs(nums[right]))
{
result[index] = nums[left] * nums[left];
left++;
}
else
{
result[index] = nums[right] * nums[right];
right--;
}
index--;
}
return result;
}
}
By using the naive approach this question will be very easy but it will require O(nlogn) complexity
To solve this question in O(n), two pointer method is the best approach.
Create a new result array with the same length as the given array, and store it pointer as array length
Assign a pointer at the start of the array and then assign another pointer at the last of the array, as we know the last element from either side will be highest
[-9, -2, 0, 2, 3]
compare -9 and 3 absolute value
if the left value then store the value to the resultant array and decrease its index value and increase the left, otherwise decrease the right.
Python3 solution. time complexity - O(N) and space complexity O(1).
def sorted_squArrres(Arr:list) ->list:
i = 0
j = len(Arr)-1
while i<len(Arr):
if Arr[i]*Arr[i]<Arr[j]*Arr[j]:
Arr.insert(0,Arr[j]*Arr[j])
Arr.pop(j+1)
i+=1
continue
if Arr[i]*Arr[i]>Arr[j]*Arr[j]:
Arr.insert(0,Arr[i]*Arr[i])
Arr.pop(i+1)
i+=1
continue
else:
if i!=j:
Arr.insert(0,Arr[j]*Arr[j])
Arr.insert(0,Arr[j+1]*Arr[j+1])
Arr.pop(j+2)
Arr.pop(i+2)
i+=2
else:
Arr.insert(0,Arr[j]*Arr[j])
Arr.pop(j+1)
i+=1
return Arr
X = [[-4,-3,-2,0,3,5,6],[1,2,3,4,5],[-5,-4,-3,-2,-1],[-9,-2,0,2,3]]
for i in X:
# looping differnt kinds of inputs
print(sorted_squArrres(i))
# outputs
'''
[0, 4, 9, 9, 16, 25, 36]
[1, 4, 9, 16, 25]
[1, 4, 9, 16, 25]
[0, 4, 4, 9, 81]
'''

Any faster way to find the number of "lucky triples"?

I am working on a code challenge problem -- "find lucky triples". "Lucky triple" is defined as "In a list lst, for any combination of triple like (lst[i], lst[j], lst[k]) where i < j < k, where lst[i] divides lst[j] and lst[j] divides lst[k].
My task is to find the number of lucky triples in a given list. The brute force way is to use three loops but it takes too much time to solve the problem. I wrote this one and the system respond "time exceed". The problems looks silly and easy but the array is unsorted so general methods like binary search do not work. I am stun in the problem for one day and hope someone can give me a hint. I am seeking a way to solve the problem faster, at least the time complexity should be lower than O(N^3).
A simple dynamic programming-like algorithm will do this in quadratic time and linear space. You just have to maintain a counter c[i] for each item in the list, that represents the number of previous integers that divides L[i].
Then, as you go through the list and test each integer L[k] with all previous item L[j], if L[j] divides L[k], you just add c[j] (which could be 0) to your global counter of triples, because that also implies that there exist exactly c[j] items L[i] such that L[i] divides L[j] and i < j.
int c[] = {0}
int nbTriples = 0
for k=0 to n-1
for j=0 to k-1
if (L[k] % L[j] == 0)
c[k]++
nbTriples += c[j]
return nbTriples
There may be some better algorithm that uses fancy discrete maths to do it faster, but if O(n^2) is ok, this will do just fine.
In regard to your comment:
Why DP? We have something that can clearly be modeled as having a left to right order (DP orange flag), and it feels like reusing previously computed values could be interesting, because the brute force algorithm does the exact same computations a lot of times.
How to get from that to a solution? Run a simple example (hint: it should better be by treating input from left to right). At step i, compute what you can compute from this particular point (ignoring everything on the right of i), and try to pinpoint what you compute over and over again for different i's: this is what you want to cache. Here, when you see a potential triple at step k (L[k] % L[j] == 0), you have to consider what happens on L[j]: "does it have some divisors on its left too? Each of these would give us a new triple. Let's see... But wait! We already computed that on step j! Let's cache this value!" And this is when you jump on your seat.
Full working solution in python:
c = [0] * len(l)
print c
count = 0
for i in range(0,len(l)):
j=0
for j in range(0, i):
if l[i] % l[j] == 0:
c[i] = c[i] + 1
count = count + c[j]
print j
print c
print count
Read up on the Sieve of Eratosthenes, a common technique for finding prime numbers, which could be adapted to find your 'lucky triples'. Essentially, you would need to iterate your list in increasing value order, and for each value, multiply it by an increasing factor until it is larger than the largest list element, and each time one of these multiples equals another value in the list, the multiple is divisible by the base number. If the list is sorted when given to you, then the i < j < k requirement would also be satisfied.
e.g. Given the list [3, 4, 8, 15, 16, 20, 40]:
Start at 3, which has multiples [6, 9, 12, 15, 18 ... 39] within the range of the list. Of those multiples, only 15 is contained in the list, so record under 15 that it has a factor 3.
Proceed to 4, which has multiples [8, 12, 16, 20, 24, 28, 32, 36, 40]. Mark those as having a factor 4.
Continue through the list. When you reach an element that has an existing known factor, then if you find any multiples of that number in the list, then you have a triple. In this case, for 16, this has a multiple 32 which is in the list. So now you know that 32 is divisible by 16, which is divisible by 4. Whereas for 15, that has no multiples in the list, so there is no value that can form a triplet with 3 and 15.
A precomputation step to the problem can help reduce time complexity.
Precomputation Step:
For every element(i), iterate the array to find which are the elements(j) such that lst[j]%lst[i]==0
for(i=0;i<n;i++)
{
for(j=i+1;j<n;j++)
{
if(a[j]%a[i] == 0)
// mark those j's. You decide how to store this data
}
}
This Precomputation Step will take O(n^2) time.
In the Ultimate Step, use the details of the Precomputation Step, to help find the triplets..
Forming a graph - an array of the indices which are multiples ahead of the current index. Then calculating the collective sum of multiples of these indices, referred from the graph. It has a complexity of O(n^2)
For example, for a list {1,2,3,4,5,6} there will be an array of the multiples. The graph will look like
{ 0:[1,2,3,4,5], 1:[3,5], 2: [5], 3:[],4:[], 5:[]}
So, total triplets will be {0->1 ->3/5} and {0->2 ->5} ie., 3
package com.welldyne.mx.dao.core;
import java.util.LinkedList;
import java.util.List;
public class LuckyTriplets {
public static void main(String[] args) {
int[] integers = new int[2000];
for (int i = 1; i < 2001; i++) {
integers[i - 1] = i;
}
long start = System.currentTimeMillis();
int n = findLuckyTriplets(integers);
long end = System.currentTimeMillis();
System.out.println((end - start) + " ms");
System.out.println(n);
}
private static int findLuckyTriplets(int[] integers) {
List<Integer>[] indexMultiples = new LinkedList[integers.length];
for (int i = 0; i < integers.length; i++) {
indexMultiples[i] = getMultiples(integers, i);
}
int luckyTriplets = 0;
for (int i = 0; i < integers.length - 1; i++) {
luckyTriplets += getLuckyTripletsFromMultiplesMap(indexMultiples, i);
}
return luckyTriplets;
}
private static int getLuckyTripletsFromMultiplesMap(List<Integer>[] indexMultiples, int n) {
int sum = 0;
for (int i = 0; i < indexMultiples[n].size(); i++) {
sum += indexMultiples[(indexMultiples[n].get(i))].size();
}
return sum;
}
private static List<Integer> getMultiples(int[] integers, int n) {
List<Integer> multiples = new LinkedList<>();
for (int i = n + 1; i < integers.length; i++) {
if (isMultiple(integers[n], integers[i])) {
multiples.add(i);
}
}
return multiples;
}
/*
* if b is the multiple of a
*/
private static boolean isMultiple(int a, int b) {
return b % a == 0;
}
}
I just wanted to share my solution, which passed. Basically, the problem can be condensed to a tree problem. You need to pay attention to the wording of the question, it only treats numbers different on basis of the index not value. so {1,1,1} will have only 1 triple, but {1,1,1,1} will have 4. the constraint is {li,lj,lk} such that the divide and i<j<k
def solution(l):
count = 0
data = l
max_element = max(data)
tree_list = []
for p,element in enumerate(data):
if element == 0:
tree_list.append([])
else:
temp = []
for el in data[p+1:]:
if el%element == 0:
temp.append(el)
tree_list.append(temp)
for p,element_list in enumerate(tree_list):
data[p] = 0
temp = data[:]
for element in element_list:
pos_element = temp.index(element)
count += len(tree_list[pos_element])
temp[pos_element] = 0
return count

Find an element in an infinite length sorted array

Given an infinite length sorted array having both positive and negative integers. Find an element in it.
EDIT
All the elements in the array are unique and the array in infinite in right direction.
There are two approaches:
Approach 1:
Set the index at position 100, if the element to be found is less, binary search in the previous 100 items, else set the next index at position 200. In this way, keep on increasing the index by 100 until the item is greater.
Approach 2:
Set the index in power of 2. First set the index at position 2, then 4, then 8, then 16 and so on. Again do the binary search from position 2^K to 2^(K + 1) where item is in between.
Which of the two approaches will be better both in best case and worst case?
The first approach will be linear in the index of the element (O(k) where k is the index of the element). Actually, you are going to need k/100 iterations to find the element which is greater than the searched element, which is O(k).
The second approach will be logarithmic in the same index. O(logk). (where k is the index of the element). In here, you are going to need log(k) iterations until you find the higher element. Then binary search between 2^(i-1), 2^i (where i is the iteration number), will be logarithmic as well, totaling in O(logk)
Thus, the second is more efficient.
You can apply binary search more or less directly with a small modification. This will roughly correspond to your Approach 2.
Basically, pick some number B and set A to 0, then check if the element you're looking for is between A and B. If it is, perform the usual kind of binary search in these boundaries, otherwise set B=A and A=2*A and repeat. This will take O(log(M)), where M is the position of the element you're looking for in the array.
If the array is well-founded, i.e. has a smallest element (i.e. you have elements x0, x1, ...), and all ele­ments are unique, then here's a simple approach: If you're looking for the number n, you can do a bi­na­ry search over the indices 0, ..., n − x0. Note that we always have the basic inequality xi ≥ i + x0 for all i ≥ 0.
Thus you can find the value n in log2(n − x0) steps.
Since the array is infinite, the indexes are necessarily variable-length. That means that doing math on them is not O(1), which in turn means that "binary search with first a search for an endpoint" has a slightly different time complexity than O(log(k)).
The index math done in the search for the endpoint is just a left shift by one, which takes O(log(k)) because indexes up to k need up to log(k) bits and shifting left by one is linear in the number of bits.
The index math done in the binary search is all O(log(k)) as well.
So the actual complexity of both algorithms is O(log(k)^2). The complexity of a linear search would be O(k log k), so it still loses.
Just my 2 cents. We have an infinite array thus lets imagine that we are looking for very big number. Did you imagine? Well it's ever much more bigger. Note that length of interval to binary search in is 2^i = 2^(i+1)-2^i thus it should take log(2^i)=i time to find the number. On the other hand it takes i time to reach the target interval. So the total time complexity is O(n) again. What I'm missing?
Here is another implementation which use 2^n to search occurrence of element itself, and then gives this sub-array to binary search
e.g.
arr = 1,2,3,4,5,6,7,8,9,-1,-1,-1,-1,-1,-1...........
num = 8;
efficiency = 2logn
--Complete Solution-- takes O(logn) time complexity
public class B {
public static void main(String[] args) {
// Assuming sorted array of infinite length
int a[] = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 };
int elementToFind = 12;
int finalIndex = getFinalIndex(a, elementToFind);
if (finalIndex == -1) {
System.out.println("Element not found");
}
System.out.println("Found element:" + a[finalIndex]);
}
private static int getFinalIndex(int[] a, int elementToFind) {
int power = 2;
int finalIndex = (int) Math.pow(2, power);
for (int i = 0; i < finalIndex;) {
if (elementToFind == a[finalIndex]) {
return finalIndex;
}
else if (elementToFind < a[finalIndex]) {
System.out.println("search through binary search algo");
// taking i as starting index in binary search call
int searchedIndex = callToBinarySearch(a, i, finalIndex);
return searchedIndex;
}
else {
i = finalIndex + 1;
power = power * 2;
finalIndex = (int) Math.pow(2, power);
}
}
return -1;
}
}
package com.population.app;
import java.io.;
import java.util.;
class Demo {
public static void main(String args[]) {
int arr[] = { 1, 2, 4, 6, 8, 9, 12, 14, 17, 21, 45 };
int index = findPos(arr, 45);
if (index == -1)
System.out.println("Element not found!");
else
System.out.println("Element found! index = " + index);
}
static int findPos(int arr[], int value) {
int start = 0, end = 1;
while (arr[end] < value) {
start = end;
end = 2 * end;
// we know it is infinite but if it has finite elements it will reduce the
// overflow of legth to n-1 element other wise the code will fail has array
// index out of bound exception
if (end > arr.length) {
end = arr.length - 1;
}
}
return binarySearch(arr, start, end, value);
}
static int binarySearch(int arr[], int start, int end, int ele) {
if (end >= start) {
int mid = start + (end - start) / 2;
if (arr[mid] == ele)
return mid;
if (arr[mid] > ele)
return binarySearch(arr, start, mid - 1, ele);
return binarySearch(arr, mid + 1, end, ele);
}
return -1;
}
}

finding the sum of smaller elements on left

i came across a problem of finding the number of smaller elements on left of each element in an array of integers, which can be solved in O(nlgn) by using Binary Indexed trees(like AVL, etc) or Merge Sort. Using an AVL tree one can calculate the size of left sub-tree for each element and this would be the required answer. However I can't come up how to calculate the sum of the smaller elements left to each element efficiently. For each element , do i have to traverse the left sub-tree and sum the values at nodes or is there any better way(using Merge Sort etc)?
E.g for the array: 4,7,1,3,2 the required ans would be: 0,4,0,1,1
Thanks.
In Binary Indexed trees you store the number of child nodes for every node of the binary search tree. This allows you to find number of nodes, preceding each node (number of smaller elements).
For this task, you can store the sum of child node values for every node of the binary search tree. This allows you to find the sum of values for preceding nodes (sum of smaller elements). Also in O(n*log(n)).
Check this tutorial on Binary Indexed Tree. This is a structure, that uses O(n) memory and can proceed such tasks:
1. Change value of a[i] by(to) x, call this add(i,x);
2. Return sum all of a[i], i<=m, call this get(x).
in O(log n).
Now, how to use this to your task. You can do this in 2 steps.
Step one. Copy, sort and remove duplicates from original array. Now you can remap numbers, so they are in range [1...n].
Step 2. Now walk through the array from left to right. Let A[i] - be the value in original array, new[i] - mapped value. (if A = [2, 7, 11, -3, 7] then new = [2, 3, 4, 1, 2]).
The answer is get(new[i]-1).
Update the values: add(new[i], 1) for counting, add(new[i], A[i]) for sum.
All in all. Sorting and remapping is O(n logn). Working on array is n * O(log n) = O(n log n). So total complexity is O(n logn)
Alternatively, use treap (in russian).
EDIT: Building new array.
Suppose the original array A = [2, 7, 11,-3, 7]
Copy it to B and sort, B = [-3, 2, 7, 7, 11]
Do a unique B = [-3, 2, 7, 11].
Now to get new, you can
add all of elements to map in increasing order, e.g. (-3 -> 1, 2->2, 7->3, 11->4)
for each element in A, do a binary search over B
The following code has a complexity of O(nlogn).
It uses a binary indexed tree to solve the problem.
#include <cstdio>
using namespace std;
const int MX_RANGE = 100000, MX_SIZE = 100000;
int tree[MX_RANGE] = {0}, a[MX_SIZE];
int main() {
int n, mn = MX_RANGE, shift = 0;
scanf("%d", &n);
for(int i = 0; i < n; i++) {
scanf("%d", &a[i]);
if(a[i] < mn) mn = a[i];
}
shift = 1-mn; // we need to remap all values to start from 1
for(int i = 0; i < n; i++) {
// Read answer
int sum = 0, idx = a[i]+shift-1;
while(idx>0) {
sum += tree[idx];
idx -= (idx&-idx);
}
printf("%d ", sum);
// Update tree
idx = a[i]+shift;
while(idx<=MX_RANGE) {
tree[idx] += a[i];
idx += (idx&-idx);
}
}
printf("\n");
}

Find the x smallest integers in a list of length n

You have a list of n integers and you want the x smallest. For example,
x_smallest([1, 2, 5, 4, 3], 3) should return [1, 2, 3].
I'll vote up unique runtimes within reason and will give the green check to the best runtime.
I'll start with O(n * x): Create an array of length x. Iterate through the list x times, each time pulling out the next smallest integer.
Edits
You have no idea how big or small these numbers are ahead of time.
You don't care about the final order, you just want the x smallest.
This is already being handled in some solutions, but let's say that while you aren't guaranteed a unique list, you aren't going to get a degenerate list either such as [1, 1, 1, 1, 1] either.
You can find the k-th smallest element in O(n) time. This has been discussed on StackOverflow before. There are relatively simple randomized algorithms, such as QuickSelect, that run in O(n) expected time and more complicated algorithms that run in O(n) worst-case time.
Given the k-th smallest element you can make one pass over the list to find all elements less than the k-th smallest and you are done. (I assume that the result array does not need to be sorted.)
Overall run-time is O(n).
Maintain the list of the x highest so far in sorted order in a skip-list. Iterate through the array. For each element, find where it would be inserted in the skip list (log x time). If in the interior of the list, it is one of the smallest x so far, so insert it and remove the element at the end of the list. Otherwise do nothing.
Time O(n*log(x))
Alternative implementation: maintain the collection of x highest so far in a max-heap, compare each new element with top element of the heap, and pop + insert new element only if the new element is less than the top element. Since comparison to top element is O(1) and pop/insert O(log x), this is also O(nlog(x))
Add all n numbers to a heap and delete x of them. Complexity is O((n + x) log n). Since x is obviously less than n, it's O(n log n).
If the range of numbers (L) is known, you can do a modified counting sort.
given L, x, input[]
counts <- array[0..L]
for each number in input
increment counts[number]
next
#populate the output
index <- 0
xIndex <- 0
while xIndex < x and index <= L
if counts[index] > 0 then
decrement counts[index]
output[xIndex] = index
increment xIndex
else
increment index
end if
loop
This has a runtime of O(n + L) (with memory overhead of O(L)) which makes it pretty attractive if the range is small (L < n log n).
def x_smallest(items, x):
result = sorted(items[:x])
for i in items[x:]:
if i < result[-1]:
result[-1] = i
j = x - 1
while j > 0 and result[j] < result[j-1]:
result[j-1], result[j] = result[j], result[j-1]
j -= 1
return result
Worst case is O(x*n), but will typically be closer to O(n).
Psudocode:
def x_smallest(array<int> arr, int limit)
array<int> ret = new array[limit]
ret = {INT_MAX}
for i in arr
for j in range(0..limit)
if (i < ret[j])
ret[j] = i
endif
endfor
endfor
return ret
enddef
In pseudo code:
y = length of list / 2
if (x > y)
iterate and pop off the (length - x) largest
else
iterate and pop off the x smallest
O(n/2 * x) ?
sort array
slice array 0 x
Choose the best sort algorithm and you're done: http://en.wikipedia.org/wiki/Sorting_algorithm#Comparison_of_algorithms
You can sort then take the first x values?
Java: with QuickSort O(n log n)
import java.util.Arrays;
import java.util.Random;
public class Main {
public static void main(String[] args) {
Random random = new Random(); // Random number generator
int[] list = new int[1000];
int lenght = 3;
// Initialize array with positive random values
for (int i = 0; i < list.length; i++) {
list[i] = Math.abs(random.nextInt());
}
// Solution
int[] output = findSmallest(list, lenght);
// Display Results
for(int x : output)
System.out.println(x);
}
private static int[] findSmallest(int[] list, int lenght) {
// A tuned quicksort
Arrays.sort(list);
// Send back correct lenght
return Arrays.copyOf(list, lenght);
}
}
Its pretty fast.
private static int[] x_smallest(int[] input, int x)
{
int[] output = new int[x];
for (int i = 0; i < x; i++) { // O(x)
output[i] = input[i];
}
for (int i = x; i < input.Length; i++) { // + O(n-x)
int current = input[i];
int temp;
for (int j = 0; j < output.Length; j++) { // * O(x)
if (current < output[j]) {
temp = output[j];
output[j] = current;
current = temp;
}
}
}
return output;
}
Looking at the complexity:
O(x + (n-x) * x) -- assuming x is some constant, O(n)
What about using a splay tree? Because of the splay tree's unique approach to adaptive balancing it makes for a slick implementation of the algorithm with the added benefit of being able to enumerate the x items in order afterwards. Here is some psuedocode.
public SplayTree GetSmallest(int[] array, int x)
{
var tree = new SplayTree();
for (int i = 0; i < array.Length; i++)
{
int max = tree.GetLargest();
if (array[i] < max || tree.Count < x)
{
if (tree.Count >= x)
{
tree.Remove(max);
}
tree.Add(array[i]);
}
}
return tree;
}
The GetLargest and Remove operations have an amortized complexity of O(log(n)), but because the last accessed item bubbles to the top it would normally be O(1). So the space complexity is O(x) and the runtime complexity is O(n*log(x)). If the array happens to already be ordered then this algorithm would acheive its best case complexity of O(n) with either an ascending or descending ordered array. However, a very odd or peculiar ordering could result in a O(n^2) complexity. Can you guess how the array would have to be ordered for that to happen?
In scala, and probably other functional languages, a no brainer:
scala> List (1, 3, 6, 4, 5, 1, 2, 9, 4) sortWith ( _<_ ) take 5
res18: List[Int] = List(1, 1, 2, 3, 4)

Resources