Time complexity of this unique permutations algorithm - algorithm

What is the time complexity on the following algorithm?
I am aware that permutations without checking duplicates take O(n!), but I am specifically interested in the shoudSwap function, which is shown below:
// Returns true if str[curr] does not match with any of the
// characters after str[start]
bool shouldSwap(char str[], int start, int curr)
{
for (int i = start; i < curr; i++)
if (str[i] == str[curr])
return 0;
return 1;
}

If n is the size of the char array str[], then the time complexity of shouldSwap() is O(n) because it will iterate at most once over every element in the str array.

Related

(with example) Why is KMP string matching O(n). Shouldn't it be O(n*m)?

Why is KMP O(n + m)?
I know this question has probably been asked a million times on here but I haven't find a solution that convinced me/I understood or a question that matched my example.
/**
* KMP algorithm of pattern matching.
*/
public boolean KMP(char []text, char []pattern){
int lps[] = computeTemporaryArray(pattern);
int i=0;
int j=0;
while(i < text.length && j < pattern.length){
if(text[i] == pattern[j]){
i++;
j++;
}else{
if(j!=0){
j = lps[j-1];
}else{
i++;
}
}
}
if(j == pattern.length){
return true;
}
return false;
}
n = size of text
m = size of pattern
I know why its + m, thats the runtime it takes to create the lsp array to do lookups. I'm not sure why the code I passed above is O(n).
I see that above "i" always progresses forwards EXCEPT when it doesn't match and j!= 0. In that case, we can do iterations of the while loop where i doesn't move forward, so its not exactly O(n)
If the lps array is incrementing like [1,2,3,4,5,6,0]. If we fail to match at index 6, j gets updated to 5, and then 4, and then 3.... and etc and we effectively go through m extra iterations (assuming all mismatch). This can occur at every step.
so it would look like
for (int i = 0; i < n; i++) {
for (int j = i; j >=0; j--) {
}
}
and to put all the possible i j combinations aka states would require a nm array so wouldn't the runtime be O(nm).
So is my reading of the code wrong, or the runtime analysis of the for loop wrong, or my example is impossible?
Actually, now that I think about it. It is O(n+m). Just visualized it as two windows shifting.

how to check if an array contains only distinct elements with time complexity n logn

So far i worked is on the above with time complexity n^2, can anyone helper increase the efficiency to nlogn or below?
bool checkDuplicates( int array[], int n)
{
int i,j;
for( i = 0; i < n; i++ )
{
for( j = i+1; j < n; j++ )
{
if( array[i] == array[j] )
return true;
}
}
return false;
}
you can quicksort the array (n log(n)), then finding duplicates becomes linear (only need to check consecutive elements).
Use a sorting algorithm (e.g. mergesort which has O(n log n)) and then check for consecutive elements that are equal.
Or modify the merge step of mergesort to detect equal elements.
Also, use size_t for indices, not int.
Assuming you can alter array, do that first (n log n provided you're using a good algorithm). Next, walk array and compare sequential elements (n).
If you use C++, then this is a way:
#include <set>
bool hasDuplicates(int array[], int n)
{
std::set<int> no_duplicates(array, array + n);
return no_duplicates.size() != n;
}
You can use Sorting, Set or even Unordered Map to achieve your task.
If you can alter the contents of the array, prefer sorting
If you can't alter the contents of the array, set is a good choice
If you can't alter the contents of the array & want to achieve O(N) complexity prefer unordered map
Using sorting
// Checking duplicates with Sorting, Complexity: O(nlog(n))
bool checkDuplicatesWithSorting(int array[], int n)
{
sort(array, array+n);
for(int i = 1; i < n; i++ )
{
if(array[i]==array[i-1])
return true;
}
return false;
}
Using Set
// Checking duplicates with a Set, Complexity: O(nlog(n))
bool checkDuplicatesWithSet(int array[], int n)
{
set <int> s(array, array+n);
return s.size() != n;
}
Using Unordered Map
// Checking duplicates with a Unordered Map, Complexity: O(n) (Average Case)
bool checkDuplicatesWithHashMap(int array[], int n)
{
unordered_map<int, bool>uo_map;
for(int i=0;i<n;i++){
if(uo_map.find(array[i]) == uo_map.end())
uo_map[array[i]] = true;
else return true;
}
return false;
}
Live Code

CodeFight firstDuplicate interview challenge

As per problem statement:
Write a solution with O(n) time complexity and O(1) additional space
complexity. Given an array a that contains only numbers in the range
from 1 to a.length, find the first duplicate number for which the
second occurrence has the minimal index. In other words, if there are
more than 1 duplicated numbers, return the number for which the second
occurrence has a smaller index than the second occurrence of the other
number does. If there are no such elements, return -1
I followed my code according to constraints and still I'm getting time complexity error. Here's my solution:
int firstDuplicate(std::vector<int> a)
{
long long int n = a.size();
int cnt=0;
for(long long int i=0;i<n;i++)
{
//cout<<a[i]<<" "<<cnt<<endl;
if(a[i]==n||a[i]==-n)
{ cnt++;
if(cnt>1)
return n;
}
else if(a[abs(a[i])]<0)
return -a[i];
else
a[a[i]] = -a[a[i]];
}
return -1;
}
Can anyone suggest me better algorithm or whats wrong with this algorithm?
The algorithm for this problem is as follows:
For each number in the array, a, each time we see that number, we make a[abs(a[i]) - 1] negative. While iterating through a, if at some point we find that a[abs(a[i] - 1] is negative, we return a[i]. If we reach the last item in the array without finding a negative number, we return -1.
I feel like, this is what you were trying to get at, but you might have overcomplicated things. In code this is:
int firstDuplicate(std::vector<int> a)
{
for (int i = 0; i < a.size(); i += 1)
{
if (a[abs(a[i]) - 1] < 0)
return abs(a[i]);
else
a[abs(a[i]) - 1] = -a[abs(a[i]) - 1];
}
return -1;
}
This runs in O(n) time, with O(1) space complexity.
You can use the indexes to mark whether an element has occured before or not, if the value at idx is negative then it has already occurred before
int firstDuplicate(std::vector<int> a)
{
long long int n = a.size();
int cnt=0;
for(long long int i=0;i<n;i++)
{
int idx = a[i] - 1;
if(a[idx] < 0){
return a[i];
}
a[idx] *= -1;
}
return -1;
}

Algorithm's Running Time Optimization

I'm trying to find a way to optimize my algorithm such that the running time is O(n²) (Big O Notation).
The input is an array with n elements, of only positive and negative integers. We can assume that the array is already sorted.
I have to determine: for each r (element of the array), whether r = s + t, where s and t are also elements of the array, and can be the same (s == t), or also zero.
I tried to reduce the number of elements I have to check by checking if the current number is positive or negative, but the running time is still too long. The problem is that I'm using 3 while loops which already means a running time of O(n³) for the worst case.
Here is my code:
public static void Checker(int[] array) {
List<Integer> testlist = new ArrayList<Integer>();
int i = 0;
while (i < array.length) {
int current = array[i];
if (attached(current, array)) {
testlist.add(current);
}
i++;
}
}
public static boolean attached(int current, int[] array) {
boolean result = false;
int i = 0;
while (i < array.length && !result) {
int number1 = array[i];
int j = 0;
while (j < array.length && !result) {
int number2 = array[j];
if (number1 + number2 == current) {
result = true;
}
j++;
}
i++;
}
return result;
}
You can start sorting the array O(nlogn) (if not), then for each element in the array you can check if there are two elements that the sum is equals to the number in O(n²).
The code is in C#:
public static bool Solve(int[] arr)
{
Array.Sort(arr); //If not already sorted
foreach (var num in arr)
if (!FindTwoThatSumN(arr, num))
return false;
return true;
}
public static bool FindTwoThatSumN(int[] arr, int num)
{
int min = 0;
int max = arr.Length - 1;
while (true)
{
if (min == max) break;
int sum = arr[min] + arr[max];
if (sum < num) min++;
if (sum > num) max--;
if (sum == num) return true;
}
return false;
}
The idea to check if there are two numbers in an array (must be sorted) that sum a specific value is start from the minimum (min = 0) and the maximum (max = arr.Length), then in each iteration:
If the sum is lower than the number, increase min index.
If the sum is greater than the number, decrease max index.
If the sum is equals to the number, then you find a solution.
If min index reach max then there are no solution.
You can refer to this question/answers for more details and proof.
Time complexity for overall solution is O(n²):
Sort the array: O(nlogn).
Iterate over the sorted array: O(n).
Find two numbers that sum the value: O(n).
So, is O(n²) due the nested calls to FindTwoThatSumN.
If you want you can pass the index instead of the number to FindTwoThatSumN method to avoid with an additional check use the number itself as part of the solution.
calculate all the possible sums of s+t and put the results in a set => O(n2)
iterate over each r and check if there is a sum that matches r => O(n) since set.contains runs in constant time.

Efficient algorithm for: Given an unsorted array of positive integers and an integer N, return N if N existed in array or the first number <N

I had this question:
Given an unsorted array of positive integers and an integer N, return N if N existed in the array or the first number that is smaller than N.
in an interview and wanted to know what would be the best efficient algorithm to solve it?
I had given two approaches using hash and sorting array but it was not correct and efficient approach. I would really appreciate if someone can give an optimal algorithm for this problem.
I'm assuming this is in a C-style language; if not, please update the question to reflect the language.
If the array isn't sorted, then you have no choice but a (potentially) full traversal of the array to look for N, as any sorting operation is going take longer than simply traversing the array (other than by finding the element by "blind luck"). Something akin to this would probably be the most efficient (unless I'm missing something)
int retVal = -1;
for(int i = 0; i < ARRAY_LENGTH; i++)
{
if(array[i] == N) return N;
if(retVal == -1 && array[i] < N) retVal = array[i];
}
return retVal;
As suggested elsewhere, you can modify
if(retVal == -1 && array[i] < N) retVal = array[i];
to
if(retVal < array[i] && array[i] < N) retVal = array[i];
In order to get the largest value that's smaller than N, rather than simply the first.
Scan through the list from beginning to end, if you see a value less than N, hold on to the first one until you reach the end, or find N. If you find N, return it, if you reach the end, return the value you've held on to. Presumably there'd have to be some value to return if all the values were greater than N, but the problem doesn't state that.
O(N) performance, O(1) space usage.
It's a little trickier if you're looking for the largest value smaller than N. In which case, instead of holding on to the first value smaller than N, you simply grab a new value every time you find a value smaller than N, but larger than the value you are currently holding on to.
Simply replace
if(array[i] < N && retVal == -1) retVal = array[i];
with
if(array[i] < N && retVal < array[i]) retVal = array[i];
in Adam's answer
Here is my code:
int getNindex(int a[],int n,int N)
{
int min=-99999,i=0,minindex=-1;
for(i=0;i<n;i++)
{
if(a[i]>min && a[i]<=N)
{
min=a[i];
minindex=i;
}
}
return minindex;
}
int main()
{
int a[]={5,75,20,50,100};
int Nindex=getNindex(a,5,60);
if(Nindex>=0)
printf("index= %d,N= %d\n",Nindex,a[Nindex]);
return 0;
}

Resources