making run-time-complexity shorter (c++) - c++

The remove_dup function has a run-time complexity of O(n^2) since there are two nested repetitive loops inside. My task is to get the same results with O(n).
I don't really have a clue how that could look like.
int add_without_dup (char x, vector<char>& r)
{// pre-condition:
assert (true) ;
// post-condition: x is added to the end of r if it is not yet present in r
// the result is the number of comparisons performed in this function
int i = 0 ;
while ( i < size(r) && r[i] != x )
i++ ;
if ( i == size(r))
r.push_back (x) ;
return i ;
}
int remove_dup (vector<char>& source, vector<char>& dest)
{// pre-condition:
assert (size (dest) == 0) ;
// post-condition: dest is a copy of source without duplicate elements
// the result is the number of comparisons performed in this function
int nr_of_comparisons = 0 ;
for (int i = 0 ; i < size (source) ; i++)
nr_of_comparisons += add_without_dup (source[i], dest) ;
return nr_of_comparisons ;
}

Because your char can only have 256 possible values, you can keep an bool array[256]. When you insert something in you set the value to true. When you want to check if it is in you check if the value is set to true or not.
The complexity is O(N + S) where S is the number of possible values you want to have in your vector.Usually, for char, N >> S, so S will not matter.

Related

Equality test function

Below is a function which aims to perform an equality test between adjacent numbers in a one dimensional vector.
This 1D vector will have values which will represent an nxn grid. [ v is the vector]
When they are equal it returns false.
For example consider this 3x3 grid:
i\j| 0 | 1 | 2
0 | 1 | 2 | 3
1 | 4 | 5 | 6
2 | 7 | 8 | 9
The issue with the code I wrote is that not all of the numbers in the grid will have 4 other adjacent numbers and testing for indexes which don't exist e.g when trying to compare the number above the top left number in the grid (1 in the example) might lead to some inaccurate outcomes.
In addition to this what I wrote seems not to be the most efficient way to go about it. Surely there could be a simpler way to do this than having to list 5 new variables?
for( int i= 0; i < n ; i++ ){
for( int j = 0; j < n; j++){
int x = v[convert(i, j, n)];
int c = v[convert(i-1, j, n)];
int s = v[convert(i+1, j, n)];
int b = v[convert(i, j+1, n)];
int n = v[convert(i, j-1, n)];
if (x == c || x == s || x == b || x == n ) {
return false;
}
}
}
//another function used to convert 2d into 1D index
int convert(int row, int col, int rowlen){
return row*rowlen+col;
}
I would appreciate any help.
If you want an efficient way to do this, you should consider the cache locality of your values, how much index conversion you do, how many bounds tests you do, and how many comparisons are needed.
First thing to note is that you do not need to compare to the left and above when you're already comparing to the right and below. This is because the left/up test will happen when testing to the right/down on the next iteration. So immediately, that halves the amount of testing.
A first optimization would be to split the operation into row tests and column tests:
// Test adjacency in rows
for (const int *rowptr = v, *end = v + n * n;
rowptr != end;
rowptr += n)
{
for (int col = 1; col < n; col++) {
if (rowptr[col-1] == rowptr[col]) return false;
}
}
// Test adjacency in columns
for (const int *row0ptr = v, *row1ptr = v + n, *end = v + n * n;
row1ptr != end;
row0ptr = row1ptr, row1ptr += n)
{
for (int col = 0; col < n; col++) {
if (row0ptr[col] == row1ptr[col]) return false;
}
}
To avoid making two passes through the entire array, you'd need to combine these, but it starts getting a bit messy. Notice how the two separate passes currently have different bounds (the row-tests loop from column 1 to n, whereas the column tests loop from row 0 to n-1).
Combining the loops would only make sense if n is quite large and if it's absolutely critical that this piece of code is fast. The idea is to perform a single pass through the entire array, avoiding any issues with stuff like L1 cache misses on the second pass.
It would look something like this:
const int *row0ptr = v, *row1ptr = v + n, *end = v + n * n
for ( ; row1ptr != end; row0ptr = row1ptr, row1ptr += n)
{
// Test first column
if (row0ptr[0] == row1ptr[0]) return false;
// Test row0 and remaining columns
for (int col = 1; col < n; col++) {
if (row0ptr[col-1] == row0ptr[col]) return false;
if (row0ptr[col] == row1ptr[col]) return false;
}
}
// Test last row
for (int col = 1; col < n; col++) {
if (row0ptr[col-1] == row0ptr[col]) return false;
}
First I'd recommend breaking up the logic because it's getting quite convoluted. But something like this works, it avoids going outside the grid by adding extra checks on i and j and it may avoid unnecessary calls to convert since if one of the earlier tests is true the later tests aren't performed.
int x = v[convert(i, j, n)];
if (i > 0 && x == v[convert(i-1, j, n)])
return false;
if (i < n - 1 && x == v[convert(i+1, j, n)])
return false;
if (j > 0 && x == v[convert(i, j-1, n)])
return false;
if (j < n - 1 && x == v[convert(i, j+1, n)])
return false;

C++: Use recursion to find the POSITION of the smallest value in a string?

How can I use recursion to find the POSITION of the smallest value in a string? The only 2 parameters I'm allowed to have are the array and its size.
The two-parameter restriction requires you to use a little trick: since you are not allowed to add the index as a third parameter, use length instead. You will be comparing the result of recursive run to the last element of the range 0..length-1.
The reasoning goes like this:
If the array has length of 1, return the index of the initial element
Otherwise, run the algorithm for length-1, and compare the value at the index returned from the recursive invocation to the value of the last element (i.e. at index length-1)
If the last element is smaller, return length-1
Otherwise, return the index obtained from the recursive invocation
If it is a plain array, you can modify the pointer (and decrese the size accordingly ) to get "sub-arrays" to pass to the next recursion level. Something like this:
size_t minpos(int *arr, size_t length)
{
if(length < 2) return 0;
size_t pos1 = minpos(arr + 1, length - 1);
if(arr[pos1] < arr[0]) return pos1 + 1;
else return 0;
}
If you are required to find the smallest character in a character array that contains a string then it is entirely unclear why the function must have two parameters. Usually such algorithms that deal with strings have to have only one parameter.
So I have written a function that has only one parameter and returns the smallest character excluding the terminating zero.
Here is the function
#include <iostream>
size_t min_character( const char *s )
{
if ( s[0] == '\0' ) return 0;
size_t n = min_character( s + 1 ) + 1;
return ( s[n] == '\0' ) || !( s[n] < s[0] ) ? 0 : n;
}
int main()
{
const char *s = "anon123";
size_t n = min_character( s );
std::cout << n << ": \'" << s[n] << '\'' << std::endl;
return 0;
}
The program output is
4: '1'
because the smallest character in the given string is character '1' and it has poistion 4 starting from 0.
With two parameters the function can look like
size_t min_character( const char *s, size_t n )
{
if ( n == 0 ) return 0;
size_t i = min_character( s + 1, n - 1 ) + 1;
return ( i == n ) || !( s[i] < s[0] ) ? 0 : i;
}

Find an element in an array with limited comparisons?

Given X, M, N where X = element to be searched in an array and N = access only first N elements in an array and M = array size, how do we find an element in an array with maximum (N+1) comparisons?
For example,
A = [3,5,2,9,8,4,1,6,7] here M = 9
Let's have N = 6 and X = 5 => So for this case, access only first 6 elements of an array and try to find whether X is present in it or not? Here answer will return true. But for X = 6 answer will be false.
This problem is not about time complexity. it's about number of comparisons you make. For example, Brute force method looks like this.
void search(vector<int> A){
for(int i=0; i<N; i++){ // [i < N is also comparison which is N times]
if(A[i] != X) continue; // [N comparisons ]
else return true;
}
return false;
}
Time complexity is O(n) but number of comparisons will be 2*N. Reduce this comparisons to (N+1). I tried to solve it but did not get solution. Is there any solution actually for this?
Idea
Modify N+1-th element to have X value and eliminate range check. Then once you have found element with X value (which is going to be true if M < N), check it's index (this is a last check that you can perform). If it's equal to N+1 then you haven't found one.
Analysis
Despite that the approach eliminates comparisons duplication, it's still has one "extra" comparison:
bool search(int* a, int n, int x)
{
a[n] = x;
int idx = 0;
while (a[idx] != x) // n + 1 comparisons in case if value hasn't been found
++idx;
return idx < n; // (n + 2)-th comparison in case if value hasn't been found
}
Solution (not perfect, though)
I can see only one way to cut that extra comparison with this approach: is to use the fact that zero integer value converts to false and any integer value not equal to zero converts to true. Using this the code is going to look like this:
bool search(int* a, int n, int x)
{
a[n] = x;
int idx = 0;
while (a[idx] != x) // n + 1 comparisons in case if value hasn't been found
++idx;
return idx - n; // returns 0 only when idx == n, which means that value is not found
}

bug in c++ program count no of 1's in vector

A question was asked to me during an online interview.
They provided a piece of code and we have to find out a possible bug in the code.
The code is provided below as it is.
The function is provided with a non empty zero indexed vector of integers (which contains only 1 and 0).
The function will return the start position of longest sequence of 1's.
for example if the input values {0,0,0,1,1,1,1,1,0,0,1,1,1,0,1,1} it will return 3 because the longest sequence of 1's is from position 3 to 7 total five consecutive 1's.
if the input values are {0,0,1} then it will return 2 because there is only one 1 and length of longest sequence of 1 is one.
If there are no 1's then it will return -1.
The input vector can be changed so we can't change the signature of the vector to const.
I tested this function with variable no of inputs and I found out that it is working fine.
I am not able to find out any bug in the code. But the instruction says that there is a bug in the code and we can change maximum 2 lines of code to solve the bug.
int solution(vector<int>& A) {
int n = A.size();
int i = n - 1;
int result = -1;
int k = 0;
int maximal = 0;
while (i > 0) {
if (A[i] == 1) {
k = k + 1;
if (k >= maximal) {
maximal = k;
result = i;
}
} else {
k = 0;
}
i = i - 1;
}
if (A[i] == 1 && k + 1 > maximal)
result = 0;
return result;
}
To fix UB for empty case, I add check for !A.empty(),
and I profit of that to replace i by 0 (at that point i == 0)
and to replace the check with maximal value to have a coherent result for tie:
if (!A.empty() && A[0] == 1 && k + 1 >= maximal)
And as I may change an other line, I would fix the prototype as A is not modified.
int solution(const std::vector<int>& A) {
problem specifications are that
1.vector is immutable and
2.Input vector is not empty
I tried same problem in Java but different approach to see what is missing because i cant find any bug in above code.
package javaapplication7;
/**
*
* #author Owner
*/
public class JavaApplication7 {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
int[] A={0,1,0,1,1,1,1};
System.out.println(solution(A));
}
static int solution(int A[]){
int i=0,count=0,max=0,pos=-1;
while(i<=A.length-1)
{
if(A[i]==1)
{
count++;
i=i+1;
}
else
{
i=i+1;
count=0;
}
if(count>max)
{
pos=i-count;
max=count;
}
}
if(count==0)
return pos;
else
return pos;
}
}
the given code will favor a sequence closer to the left side if two sequences are of equal length. that doesn't happen for the checking of index 0
if (A[i] == 1 && k + 1 > maximal)
should be
if (A[i] == 1 && k + 1 >= maximal)

c++ check all array values at once

what I want to do is check an array of bools to see if 3 or more of them have been set to true. The only way I can think to do this is using a if statement for each possible combination of which there is lots because there are ten bools. Dose anybody have any suggestions on how best to do this.
This would be the easiest way:
std::count(bool_array, std::end(bool_array), true) >= 3
Only problem is it keeps counting even after it has found 3. If that is a problem, then I would use sharptooth's method.
side note
I've decided to fashion an algorithm in the style of std::all_of/any_of/none_of for my personal library, perhaps you will find it useful:
template<typename InIt, typename P>
bool n_or_more_of(InIt first, InIt last, P p, unsigned n)
{
while (n && first != last)
{
if (p(*first)) --n;
++first;
}
return n == 0;
}
For your purpose, you would use it like this:
n_or_more_of(bool_array, std::end(bool_array), [](bool b) { return b; }, 3);
The much easier way would be to loop through the array:
int numberOfSet = 0;
for( int i = 0; i < sizeOfArray; i++ ) {
if( array[i] ) {
numberOfSet++;
//early cut-off so that you don't loop further without need
// whether you need it depends on how typical it is to have
// long arrays that have three or more elements set in the beginning
if( numberOfSet >= 3 ) {
break;
}
}
}
bool result = numberOfSet >= 3;
Whenever you are setting an array element into TRUE value, you can increment a global counter. This will be the simplest way. At any point in your code, the global array will tell you the number of TRUE elements in the Array.
Another thing - if you are keeping upto 32 bool values, you can use a single int variable. int is 32 bits (in Win32) and you can store 32 bool.
char x = 0; // 00000000 // char is 8 bits
// TO SET TRUE
x = x | (1 << 4); // 00010000
x = x | (1 << 7); // 10010000
// TO SET FALSE
x = x & ~(1 << 4); // 10010000 & 11101111 => 10000000
// TO CHECK True/False
if( x & ~(1 << 4) )
If it's an array, what you do is loop over it and count the number of trues. But I'm afraid you mean a bitpattern of some kind, right?
Why not just count the number of trues and then do something if the number is 3 or higher:
int sum = 0;
for (int i = 0; i < length; i++){
if (arr[i]){
sum++;
}
}
if (sum >= 3){
// do something...
}
You can loop through and build a bit-mask representation of the array, then you can compare against up to CHAR_BIT * sizeof (unsigned long) in parallel:
unsigned long mask = 0;
for (std::vector<bool>::const_iterator it = flags.begin(), end_it = flags.end();
it != end_it;
++it)
{
if (*it)
mask |= (1 << (it - flags.begin()));
}
if (mask & (0xaa3)) // or whatever mask you want to check
{
}
This assumes that you're looking for patterns, not just want to count the number of true flags in the array.
Just loop through the array counting the number of bools set to true.
/**
* #param arr The array of booleans to check.
* #param n How many must be true for this function to return true.
* #param len The length of arr.
*/
bool hasNTrue(bool *arr, int n, int len) {
int boolCounter;
for(int i=0; i<len; i++) {
if (arr[i]) boolCounter++;
}
return boolCounter>=n;
}
Then call it like so
hasNTrue(myArray, 3, myArrayLength);
Store the bools as bits in an integer. Then apply one of the bit twiddling hacks.