Cartesian Product of multiple array - arrays

I think it is basically an easy problem, but I'm stuck. My brain is blocked by this problem, so I hope you can help me.
I have 2 to N arrays of integers, like
{1,2,3,4,5}
{1,2,3,4,5,6}
{1,3,5}
.....
Now i want to have a list containing arrays of int[N] with every posibillity like
{1,1,1}
{1,1,3}
{1,1,5}
{1,2,1}
....
{1,3,1}
....
{2,1,1}
{2,1,3}
....
{5,6,5}
so there are 6*5*3 (90) elements in it.
Is there a simple algorithm to do it? I think the language didn't matter but I prefer Java.

Thx for the help!
I add a valid answer with the implementation in java for the next guy, who has the same problem. I also do it generic so u can have any CartesianProduct on any Object, not just ints:
public class Product {
#SuppressWarnings("unchecked")
public static <T> List<T[]> getCartesianProduct(T[]... objects){
List<T[]> ret = null;
if (objects != null){
//saves length from first dimension. its the size of T[] of the returned list
int len = objects.length;
//saves all lengthes from second dimension
int[] lenghtes = new int[len];
// arrayIndex
int array = 0;
// saves the sum of returned T[]'s
int lenSum = 1;
for (T[] t: objects){
lenSum *= t.length;
lenghtes[array++] = t.length;
}
//initalize the List with the correct lenght to avoid internal array-copies
ret = new ArrayList<T[]>(lenSum);
//reusable class for instatiation of T[]
Class<T> clazz = (Class<T>) objects[0][0].getClass();
T[] tArray;
//values stores arrayIndexes to get correct values from objects
int[] values = new int[len];
for (int i = 0; i < lenSum; i++){
tArray = (T[])Array.newInstance(clazz, len);
for (int j = 0; j < len; j++){
tArray[j] = objects[j][values[j]];
}
ret.add(tArray);
//value counting:
//increment first value
values[0]++;
for (int v = 0; v < len; v++){
//check if values[v] doesn't exceed array length
if (values[v] == lenghtes[v]){
//set it to null and increment the next one, if not the last
values[v] = 0;
if (v+1 < len){
values[v+1]++;
}
}
}
}
}
return ret;
}
}

As i understand what you want, you need to get all permutations.
Use recursive algorithm, detailed here.

As I see this should work fine:
concatMap (λa -> concatMap (λb -> concatMap (λc -> (a,b,c)) L3) L2) L1
where concatMap(called SelectMany in C#) is defined as
concatMap f l = concat (map f l).
and map maps a function over a list
and concat(sometimes called flatten) takes a List of List and turns it into a flat List

Related

identify recurring/duplicate patterns as sub-arrays from a parent array

I have a typical pattern searching problem where I need to identify where multiple patterns are appearing within an array and single them out.
ex: ['horse', 'camel', 'horse', 'camel', 'tiger', 'horse', 'camel', 'horse', 'camel']
function should return
['horse', 'camel'],
['horse', 'camel', 'horse'],
['camel', 'horse', 'camel'],
['horse', 'camel', 'horse', 'camel']
i.e. finding patterns that are repeating within an array which can become a sub-array,
Or the other way of defining is -> Find all the sub-arrays which are occurring more than 1 times in main array.
i.e. resulting arrays should have length > 1 ->
[1, 2, 3, 1, 2, 1, 4, 5] => [1,2,3] and [1,4,5] both are sub-arrays but [1,2,3] is recurring/repeating sub-array NOT [1,4,5]
Looking for a suitable efficient algorithm instead of brute-force looping solutions.
This probably isn't what you want but I don't know what you have tried yet so maybe it could be useful. Here's my direct approach which probably falls under your "brute-force looping solutions" but I figured give it a try since nobody has posted full answer.
In java:
// use this to not add duplicates to list
static boolean contains (List<String[]> patterns, String[] pattern){
for(String[] s: patterns)
if (Arrays.equals(pattern,s)) return true;
return false;
}
/**
*
* #param str String array containing all elements in your set
* #param start index of subarray
* #param end index of subarray
* #return if subarray is a recurring pattern
*/
static boolean search (String[] str,int start,int end) {
// length of pattern
int len = end - start + 1;
// how many times you want pattern to
// appear in text
int n = 1;
// increment m if pattern is matched
int m = 0;
// shift pattern down the array
for (int i = end+1; i <= str.length - len; i++) {
int j;
for (j = 0; j < len; j++) {
if (!str[i + j].equals(str[start + j]))
break;
}
// if pattern is matched at [i to i+len]
if (j == len) {
m++;
if (m == n) return true;
}
}
return false;
}
/**
*
* #param str String array containing all elements in your set
* #return a list of subsets of input set which are a recurring pattern
*/
static List<String[]> g (String[] str) {
// put patterns in here
List<String[]> patterns = new ArrayList<>();
// iterate through all possible subarrays in str
for(int i = 0; i < str.length-1; i++){
for(int j = i + 1; j < str.length; j++){
// if a pattern is found
if (search(str,i,j)) {
int len = j-i+1;
String[] subarray = new String[len];
System.arraycopy(str,i,subarray,0,len);
if (!contains(patterns,subarray))
patterns.add(subarray);
}
}
}
return patterns;
}
public static void main(String[] args) {
String[] str = {"horse", "camel", "horse", "camel", "tiger",
"horse", "camel", "horse", "camel"};
// print out
List<String[]> patterns = g(str);
for (String[] s: patterns)
System.out.println(Arrays.toString(s));
}
Output:
[horse, camel]
[horse, camel, horse]
[horse, camel, horse, camel]
[camel, horse]
[camel, horse, camel]
As mentioned in a comment i posted:
"would [camel, horse] be included in the output?"
The output I have goes with this as there are 2 instances of [camel, horse] at indices [1-2] and [6-7]. But maybe I am completely misunderstanding your question and I'm not understanding the constraints.
As for optimizing, the search(...) method for example is just a simple substring search there are some more optimized ways of doing this e.g. Knuth–Morris–Pratt. Sorry if this was exactly what you didn't want but maybe there's some use

Implement Array Random Shuffle

Prelude
I am writing a grid-based random-map generator.
Currently, I want to populate a 2D array with a variety of tiles.
Problem
In the parenthesis is a more concrete example.
Here is what you are given:
2D array and its dimensions. (i.e. 3x4 grid)
Integer Random(Range) (i.e. Range: 0-11, Output: integer from 0-11)
You do NOT have a function that randomly sorts an array, unless you implement it yourself.
Number of each type of tile (i.e. Desert: 2, Lake: 4, Forrest: 6)
How do I populate this array with the given tiles?
Example
3x4 map; 6 Forrest; 4 Lake; 2 Desert...
F F L
L D F
D F F
L F L
Attempt
I do have my own implementation, however its Big-O is... infinity, I think. :)
Of course, the chances that it will never finish are slim; however, this is part of a video game and I don't want to keep the player waiting.
Postscript
I don't really care what language that it is implemented in; pseudo-code will be satisfactory.
make sure the inputs are correct (e.g. total count of tiles equals
the count of slots in the grid)
put all give tiles into a queue Q, whose length is n(in your
example, n=12)
intialize a result array R[p], p is intialized as 0
get k=random(1->n), deque Q[k] into R[p], p++
repeat step 4 until p goes to n
Things can be much more easier if you use a language that has built-in sort functions:
verify input
put given tiles into an one demension array A[n]
sort A[n] randomly
Code in C#:
int m = 3;
int n = 4; //m*n grid
int forrests = 6;
int lakes = 4;
int deserts = 2;
if (m * n != forrests + lakes + deserts)
{
//invalid input!
}
char[] tiles = new char[m * n];
for (int i = 0; i < m * n; i++)
{
if (i < forrests)
{
tiles[i] = 'F';
}
else if (i < forrests + lakes)
{
tiles[i] = 'L';
}
else
{
tiles[i] = 'D';
}
}
//preparation completed, now tiles[] looks like
//F,F,F,F,F,F,L,L,L,L,D,D
char[] output = tiles.OrderBy(t => Guid.NewGuid()).ToArray();
//output is randomly sorted from tiles
//if you really need a two-demension array
char[][] map = new char[n][];
for (int i = 0; i < n; i++)
{
map[i] = output.Skip(m * i).Take(m).ToArray();
}
This could one of the way to do it.
#include<iostream>
#include <cstdlib>
#include <map>
using namespace std;
//Map which keeps the value for each key (2,4,6)
map<int,char> alphabet;
void initMap()
{
alphabet[2] = 'D';
alphabet[4] = 'L';
alphabet[6] = 'F';
}
int main()
{
char a[3][4];
// counter variables to keep track of d,f and l
int temp,d=0,f=0,l=0;
initMap();
for(int i=0;i<3;i++)
{
for(int j=0;j<4;j++)
{
//This determines if the generated random number is already entered in the grid. If no than breaks out. If yes than again a new random number is generated and process is iterated untill the new number is found to enter
while(1)
{
temp = rand()%4;
if(temp==0)
{
temp = 2;
}
else
{
temp = temp*2;
}
if(temp ==2 && d<2)
{
d++;
break;
}
else if(temp ==4 && l<4)
{
l++;
break;
}
else if(temp ==6 && f<6)
{
f++;
break;
}
else
{
continue;
}
}
//char value for the number temp is assigned from the alphabet map
a[i][j] = alphabet.at(temp);
cout<<a[i][j]<<" ";
}
cout<<endl;
}
return 0;
}
output:
D F L D
L L L F
F F F F
You can map the alphabet according the number when entering the value or accessing the value from array.

Merging two arraylists without creating third one

Here is one task, i was trying to solve. You must write the function
void merge(ArrayList a, ArrayList b) {
// code
}
The function recieves two ArrayLists with equal size as input parameters [a1, a2, ..., an], [b1, b2, ..., bn]. The execution result is the 1st ArrayList must contain elements of both lists, and they alternate consistently ([a1, b1, a2, b2, ..., an, bn]) Please read the bold text twice =)
Code must work as efficiently as possible.
Here is my solution
public static void merge(ArrayList a, ArrayList b) {
ArrayList result = new ArrayList();
int i = 0;
Iterator iter1 = a.iterator();
Iterator iter2 = b.iterator();
while ((iter1.hasNext() || iter2.hasNext()) && i < (a.size() + b.size())) {
if (i % 2 ==0) {
result.add(iter1.next());
} else {
result.add(iter2.next());
}
i++;
}
a = result;
}
I know it's not perfect at all. But I can't understand how to merge in the 1st list without creating tmp list.
Thanks in advance for taking part.
Double ArrayList a's size. Set last two elements of a to the last element of the old a and the last element of b. Keep going, backing up each time, until you reach the beginnings of a and b. You have to do it from the rear because otherwise you will write over the original a's values.
In the end i got this:
public static void merge(ArrayList<Integer> arr1, ArrayList<Integer> arr2) {
int indexForArr1 = arr1.size() - 1;
int oldSize = arr1.size();
int newSize = arr1.size() + arr2.size();
/*
decided not to create new arraylist with new size but just to fill up old one with nulls
*/
fillWithNulls(arr1, newSize);
for(int i = (newSize-1); i >= 0; i--) {
if (i%2 != 0) {
int indexForArr2 = i%oldSize;
arr1.set(i,arr2.get(indexForArr2));
oldSize--; // we reduce the size because we don't need tha last element any more
} else {
arr1.set(i, arr1.get(indexForArr1));
indexForArr1--;
}
}
}
private static void fillWithNulls(ArrayList<Integer> array, int newSize) {
int delta = newSize - array.size();
for(int i = 0; i < delta; i++) {
array.add(null);
}
}
Thanks John again for bright idea!

Generating All Permutations of Character Combinations when # of arrays and length of each array are unknown

I'm not sure how to ask my question in a succinct way, so I'll start with examples and expand from there. I am working with VBA, but I think this problem is non language specific and would only require a bright mind that can provide a pseudo code framework. Thanks in advance for the help!
Example:
I have 3 Character Arrays Like So:
Arr_1 = [X,Y,Z]
Arr_2 = [A,B]
Arr_3 = [1,2,3,4]
I would like to generate ALL possible permutations of the character arrays like so:
XA1
XA2
XA3
XA4
XB1
XB2
XB3
XB4
YA1
YA2
.
.
.
ZB3
ZB4
This can be easily solved using 3 while loops or for loops. My question is how do I solve for this if the # of arrays is unknown and the length of each array is unknown?
So as an example with 4 character arrays:
Arr_1 = [X,Y,Z]
Arr_2 = [A,B]
Arr_3 = [1,2,3,4]
Arr_4 = [a,b]
I would need to generate:
XA1a
XA1b
XA2a
XA2b
XA3a
XA3b
XA4a
XA4b
.
.
.
ZB4a
ZB4b
So the Generalized Example would be:
Arr_1 = [...]
Arr_2 = [...]
Arr_3 = [...]
.
.
.
Arr_x = [...]
Is there a way to structure a function that will generate an unknown number of loops and loop through the length of each array to generate the permutations? Or maybe there's a better way to think about the problem?
Thanks Everyone!
Recursive solution
This is actually the easiest, most straightforward solution. The following is in Java, but it should be instructive:
public class Main {
public static void main(String[] args) {
Object[][] arrs = {
{ "X", "Y", "Z" },
{ "A", "B" },
{ "1", "2" },
};
recurse("", arrs, 0);
}
static void recurse (String s, Object[][] arrs, int k) {
if (k == arrs.length) {
System.out.println(s);
} else {
for (Object o : arrs[k]) {
recurse(s + o, arrs, k + 1);
}
}
}
}
(see full output)
Note: Java arrays are 0-based, so k goes from 0..arrs.length-1 during the recursion, until k == arrs.length when it's the end of recursion.
Non-recursive solution
It's also possible to write a non-recursive solution, but frankly this is less intuitive. This is actually very similar to base conversion, e.g. from decimal to hexadecimal; it's a generalized form where each position have their own set of values.
public class Main {
public static void main(String[] args) {
Object[][] arrs = {
{ "X", "Y", "Z" },
{ "A", "B" },
{ "1", "2" },
};
int N = 1;
for (Object[] arr : arrs) {
N = N * arr.length;
}
for (int v = 0; v < N; v++) {
System.out.println(decode(arrs, v));
}
}
static String decode(Object[][] arrs, int v) {
String s = "";
for (Object[] arr : arrs) {
int M = arr.length;
s = s + arr[v % M];
v = v / M;
}
return s;
}
}
(see full output)
This produces the tuplets in a different order. If you want to generate them in the same order as the recursive solution, then you iterate through arrs "backward" during decode as follows:
static String decode(Object[][] arrs, int v) {
String s = "";
for (int i = arrs.length - 1; i >= 0; i--) {
int Ni = arrs[i].length;
s = arrs[i][v % Ni] + s;
v = v / Ni;
}
return s;
}
(see full output)
Thanks to #polygenelubricants for the excellent solution.
Here is the Javascript equivalent:
var a=['0'];
var b=['Auto', 'Home'];
var c=['Good'];
var d=['Tommy', 'Hilfiger', '*'];
var attrs = [a, b, c, d];
function recurse (s, attrs, k) {
if(k==attrs.length) {
console.log(s);
} else {
for(var i=0; i<attrs[k].length;i++) {
recurse(s+attrs[k][i], attrs, k+1);
}
}
}
recurse('', attrs, 0);
EDIT: Here's a ruby solution. Its pretty much the same as my other solution below, but assumes your input character arrays are words: So you can type:
% perm.rb ruby is cool
~/bin/perm.rb
#!/usr/bin/env ruby
def perm(args)
peg = Hash[args.collect {|v| [v,0]}]
nperms= 1
args.each { |a| nperms *= a.length }
perms = Array.new(nperms, "")
nperms.times do |p|
args.each { |a| perms[p] += a[peg[a]] }
args.each do |a|
peg[a] += 1
break if peg[a] < a.length
peg[a] = 0
end
end
perms
end
puts perm ARGV
OLD - I have a script to do this in MEL, (Maya's Embedded Language) - I'll try to translate to something C like, but don't expect it to run without a bit of fixing;) It works in Maya though.
First - throw all the arrays together in one long array with delimiters. (I'll leave that to you - because in my system it rips the values out of a UI). So, this means the delimiters will be taking up extra slots: To use your sample data above:
string delimitedArray[] = {"X","Y","Z","|","A","B","|","1","2","3","4","|"};
Of course you can concatenate as many arrays as you like.
string[] getPerms( string delimitedArray[]) {
string result[];
string delimiter("|");
string compactArray[]; // will be the same as delimitedArray, but without the "|" delimiters
int arraySizes[]; // will hold number of vals for each array
int offsets[]; // offsets will holds the indices where each new array starts.
int counters[]; // the values that will increment in the following loops, like pegs in each array
int nPemutations = 1;
int arrSize, offset, nArrays;
// do a prepass to find some information about the structure, and to build the compact array
for (s in delimitedArray) {
if (s == delimiter) {
nPemutations *= arrSize; // arrSize will have been counting elements
arraySizes[nArrays] = arrSize;
counters[nArrays] = 0; // reset the counter
nArrays ++; // nArrays goes up every time we find a new array
offsets.append(offset - arrSize) ; //its here, at the end of an array that we store the offset of this array
arrSize=0;
} else { // its one of the elements, not a delimiter
compactArray.append(s);
arrSize++;
offset++;
}
}
// put a bail out here if you like
if( nPemutations > 256) error("too many permutations " + nPemutations+". max is 256");
// now figure out the permutations
for (p=0;p<nPemutations;p++) {
string perm ="";
// In each array at the position of that array's counter
for (i=0;i<nArrays ;i++) {
int delimitedArrayIndex = counters[i] + offsets[i] ;
// build the string
perm += (compactArray[delimitedArrayIndex]);
}
result.append(perm);
// the interesting bit
// increment the array counters, but in fact the program
// will only get to increment a counter if the previous counter
// reached the end of its array, otherwise we break
for (i = 0; i < nArrays; ++i) {
counters[i] += 1;
if (counters[i] < arraySizes[i])
break;
counters[i] = 0;
}
}
return result;
}
If I understand the question correctly, I think you could put all your arrays into another array, thereby creating a jagged array.
Then, loop through all the arrays in your jagged array creating all the permutations you need.
Does that make sense?
it sounds like you've almost got it figured out already.
What if you put in there one more array, call it, say ArrayHolder , that holds all of your unknown number of arrays of unknown length. Then, you just need another loop, no?

Removing Duplicates in an array in C

The question is a little complex. The problem here is to get rid of duplicates and save the unique elements of array into another array with their original sequence.
For example :
If the input is entered b a c a d t
The result should be : b a c d t in the exact state that the input entered.
So, for sorting the array then checking couldn't work since I lost the original sequence. I was advised to use array of indices but I don't know how to do. So what is your advise to do that?
For those who are willing to answer the question I wanted to add some specific information.
char** finduni(char *words[100],int limit)
{
//
//Methods here
//
}
is the my function. The array whose duplicates should be removed and stored in a different array is words[100]. So, the process will be done on this. I firstly thought about getting all the elements of words into another array and sort that array but that doesn't work after some tests. Just a reminder for solvers :).
Well, here is a version for char types. Note it doesn't scale.
#include "stdio.h"
#include "string.h"
void removeDuplicates(unsigned char *string)
{
unsigned char allCharacters [256] = { 0 };
int lookAt;
int writeTo = 0;
for(lookAt = 0; lookAt < strlen(string); lookAt++)
{
if(allCharacters[ string[lookAt] ] == 0)
{
allCharacters[ string[lookAt] ] = 1; // mark it seen
string[writeTo++] = string[lookAt]; // copy it
}
}
string[writeTo] = '\0';
}
int main()
{
char word[] = "abbbcdefbbbghasdddaiouasdf";
removeDuplicates(word);
printf("Word is now [%s]\n", word);
return 0;
}
The following is the output:
Word is now [abcdefghsiou]
Is that something like what you want? You can modify the method if there are spaces between the letters, but if you use int, float, double or char * as the types, this method won't scale at all.
EDIT
I posted and then saw your clarification, where it's an array of char *. I'll update the method.
I hope this isn't too much code. I adapted this QuickSort algorithm and basically added index memory to it. The algorithm is O(n log n), as the 3 steps below are additive and that is the worst case complexity of 2 of them.
Sort the array of strings, but every swap should be reflected in the index array as well. After this stage, the i'th element of originalIndices holds the original index of the i'th element of the sorted array.
Remove duplicate elements in the sorted array by setting them to NULL, and setting the index value to elements, which is the highest any can be.
Sort the array of original indices, and make sure every swap is reflected in the array of strings. This gives us back the original array of strings, except the duplicates are at the end and they are all NULL.
For good measure, I return the new count of elements.
Code:
#include "stdio.h"
#include "string.h"
#include "stdlib.h"
void sortArrayAndSetCriteria(char **arr, int elements, int *originalIndices)
{
#define MAX_LEVELS 1000
char *piv;
int beg[MAX_LEVELS], end[MAX_LEVELS], i=0, L, R;
int idx, cidx;
for(idx = 0; idx < elements; idx++)
originalIndices[idx] = idx;
beg[0] = 0;
end[0] = elements;
while (i>=0)
{
L = beg[i];
R = end[i] - 1;
if (L<R)
{
piv = arr[L];
cidx = originalIndices[L];
if (i==MAX_LEVELS-1)
return;
while (L < R)
{
while (strcmp(arr[R], piv) >= 0 && L < R) R--;
if (L < R)
{
arr[L] = arr[R];
originalIndices[L++] = originalIndices[R];
}
while (strcmp(arr[L], piv) <= 0 && L < R) L++;
if (L < R)
{
arr[R] = arr[L];
originalIndices[R--] = originalIndices[L];
}
}
arr[L] = piv;
originalIndices[L] = cidx;
beg[i + 1] = L + 1;
end[i + 1] = end[i];
end[i++] = L;
}
else
{
i--;
}
}
}
int removeDuplicatesFromBoth(char **arr, int elements, int *originalIndices)
{
// now remove duplicates
int i = 1, newLimit = 1;
char *curr = arr[0];
while (i < elements)
{
if(strcmp(curr, arr[i]) == 0)
{
arr[i] = NULL; // free this if it was malloc'd
originalIndices[i] = elements; // place it at the end
}
else
{
curr = arr[i];
newLimit++;
}
i++;
}
return newLimit;
}
void sortArrayBasedOnCriteria(char **arr, int elements, int *originalIndices)
{
#define MAX_LEVELS 1000
int piv;
int beg[MAX_LEVELS], end[MAX_LEVELS], i=0, L, R;
int idx;
char *cidx;
beg[0] = 0;
end[0] = elements;
while (i>=0)
{
L = beg[i];
R = end[i] - 1;
if (L<R)
{
piv = originalIndices[L];
cidx = arr[L];
if (i==MAX_LEVELS-1)
return;
while (L < R)
{
while (originalIndices[R] >= piv && L < R) R--;
if (L < R)
{
arr[L] = arr[R];
originalIndices[L++] = originalIndices[R];
}
while (originalIndices[L] <= piv && L < R) L++;
if (L < R)
{
arr[R] = arr[L];
originalIndices[R--] = originalIndices[L];
}
}
arr[L] = cidx;
originalIndices[L] = piv;
beg[i + 1] = L + 1;
end[i + 1] = end[i];
end[i++] = L;
}
else
{
i--;
}
}
}
int removeDuplicateStrings(char *words[], int limit)
{
int *indices = (int *)malloc(limit * sizeof(int));
int newLimit;
sortArrayAndSetCriteria(words, limit, indices);
newLimit = removeDuplicatesFromBoth(words, limit, indices);
sortArrayBasedOnCriteria(words, limit, indices);
free(indices);
return newLimit;
}
int main()
{
char *words[] = { "abc", "def", "bad", "hello", "captain", "def", "abc", "goodbye" };
int newLimit = removeDuplicateStrings(words, 8);
int i = 0;
for(i = 0; i < newLimit; i++) printf(" Word # %d = %s\n", i, words[i]);
return 0;
}
Traverse through the items in the array - O(n) operation
For each item, add it to another sorted-array
Before adding it to the sorted array, check if the entry already exists - O(log n) operation
Finally, O(n log n) operation
i think that in C you can create a second array. then you copy the element from the original array only if this element is not already in the send array.
this also preserve the order of the element.
if you read the element one by one you can discard the element before insert in the original array, this could speedup the process.
As Thomas suggested in a comment, if each element of the array is guaranteed to be from a limited set of values (such as a char) you can achieve this in O(n) time.
Keep an array of 256 bool (or int if your compiler doesn't support bool) or however many different discrete values could possibly be in the array. Initialize all the values to false.
Scan the input array one-by-one.
For each element, if the corresponding value in the bool array is false, add it to the output array and set the bool array value to true. Otherwise, do nothing.
You know how to do it for char type, right?
You can do same thing with strings, but instead of using array of bools (which is technically an implementation of "set" object), you'll have to simulate the "set"(or array of bools) with a linear array of strings you already encountered. I.e. you have an array of strings you already saw, for each new string you check if it is in array of "seen" strings, if it is, then you ignore it (not unique), if it is not in array, you add it to both array of seen strings and output. If you have a small number of different strings (below 1000), you could ignore performance optimizations, and simply compare each new string with everything you already saw before.
With large number of strings (few thousands), however, you'll need to optimize things a bit:
1) Every time you add a new string to an array of strings you already saw, sort the array with insertion sort algorithm. Don't use quickSort, because insertion sort tends to be faster when data is almost sorted.
2) When checking if string is in array, use binary search.
If number of different strings is reasonable (i.e. you don't have billions of unique strings), this approach should be fast enough.

Resources