Consider a zero-indexed array A of N integers. Indices of this array are integers from 0 to N−1. Take an index K.
Index J is called an ascender of K if A[J] > A[K]. Note that if A[K] is a maximal value in the array A, then K has no ascenders.
Ascender J of K is called the closest ascender of K if abs(K−J) is the smallest possible value (that is, if the distance between J and K is minimal).
Note that K can have at most two closest ascenders: one smaller and one larger than K.
Here is a C++ solution where complexity is O(n).
Note that there are two loops however each iteration the number of element goes by a factor of 1/2 or the search range goes up by a factor of x2.
For example the first iteration take N time, but the second iteration is already N/2.
vector<long> ascender(vector <long> A)
{
long N = A.size();
vector<long> R(N,0);
vector<long> IndexVector(N,0); //This vector contains the index of elements with R=0
vector<long> RangeVector(N,0); //This vector define the loop range for each element
IndexVector[N-1]=N-1;
unsigned long CompxTest = 0;
for (long counter=0;counter<N;counter++)
{
IndexVector[counter] = counter; // we start that all elements needs to be consider
RangeVector[counter] = 1; // we start by looking only and neighbors
}
long Length = N;
long range;
while (Length>1)
{
long index = 0;
cout<<endl<<Length;
long J;
for (long counter=0;counter<Length;counter++)
{
CompxTest++; // Just to test complexity
J = IndexVector[counter]; // Get the index that need to be consider
range = RangeVector[J];
//cout<<" ("<<A[J]<<","<<J<<")";
if (range > N)
{
cout<<endl<<"Mini assert "<<range<<" N "<<N;
break;
}
if (J<(N-range) && A[J+range] > A[J])
{
R[J] = range;
}
if (J<(N-range) && A[J+range] < A[J] && R[J+range]==0)
{
R[J+range] = range;
}
if (J<(N-range) && A[J] == A[J+range] && R[J+range]==0)
{
R[J+range] = - range;
}
if (R[J]==0) // Didn't find ascender for this element - need to consider in next iteration
{
if (R[J+range]>2) //We can increase the range because the current element is smaller
RangeVector[J] += R[J+range]-2;
if (R[J+range]<-2)
RangeVector[J] += -R[J+range]-2;
RangeVector[J]++;
IndexVector[index] = J;
index++;
}
}
Length = index;
}
for (long counter=0;counter<N;counter++)
{
if (R[counter] < 0)
{
unsigned Value = abs(R[counter]);
if (counter+Value<N && A[counter]<A[counter+Value])
R[counter] = Value;
if (counter > Value && R[counter-Value]==0)
R[counter] = 0;
R[counter] = Value + R[counter-Value];
if (counter > Value && Value < R[counter - Value])
{
long PossibleSolution = R[counter - Value] + Value;
if (PossibleSolution <N && A[PossibleSolution]>A[counter])
R[counter] = abs(counter - PossibleSolution);
}
}
}
cout<<endl<<"Complex "<<CompxTest;
return R;
}
//
// C++ using multimap. -- INCOMPLETE
// The multimap MM is effectively the "inverse" of the input array AA
// since it is ordered by pair(value, index), where index refers to the index in
// input array AA, and value is the value in AA at that index.
// Input AA is of course ordered as (index, value).
// So when we read out of MM in value order, (a sorted set of values), each value
// is mapped to the index in the original array AA.
//
int ascender(int AA[], int N, int RR[]) {
multimap<int, int> MM;
// simply place the AA array into the multimap
int i;
for (i = 0; i < N; i++) {
int value = AA[i];
int index = i;
MM.insert(make_pair(value, index));
}
// simply read the multimap in order,
// and set output RR as the distance from one value's
// original index to the next value's original index.
//
// THIS code is incomplete, since it is wrong for duplicate values.
//
multimap<int, int>::iterator pos;
for (pos = MM.begin(); pos != MM.end(); ++pos) {
int value = pos->first;
int index = pos->second;
++pos;//temporarily move ahead to next item
// NEED to FURTHER CONSIDER repeat values in setting RR
RR[index] = (pos)->second - index;
--pos;
}
return 1;
}
1. Sort the array (if not pre-sorted)
2. Subtract every element with its adjacent element and store result in another
array.
Example: 1 3 5 6 8 -----> (after subtraction) 2 2 1 2
3. Find the minimal element in the new array.
4. Device a logic which would relate the minimal element in the new array to the
two elements in the original one.
public class Solution {
final static int MAX_INTEGER = 2147483647;
public static int maximal(int[] A) {
int max = A[0];
int length = A.length;
for (int i = 1; i < length; i++) {
if (A[i] > max) {
max = A[i];
}
}
return max;
}
public static int ascender(int[] a,int length, int k) {
int smallest = MAX_INTEGER;
int index = 0;
if (k<0 || k>length-1) {
return -1;
}
for (int i = 0; i < length; i++) {
// Index J is called an ascender of K if A[J] > A[K].
if(a[i] > a[k]) {
int abs = Math.abs(i-k);
if ( abs < smallest) {
smallest = abs;
index = i;
}
}
}
return index;
}
public static int[] array_closest_ascenders(int[] A) {
int length = A.length;
int[] R = new int[length];
for (int K = 0; K < length; K++) {
// Note that if A[K] is a maximal value in the array A,
// then K has no ascenders.
// if K has no ascenders then R[K] = 0.
if (A[K] == maximal(A)) {
R[K] = 0;
break;
}
// if K has the closest ascender J, then R[K] = abs(K-J);
// that is, R[K] is equal to the distance between J and K
int J = ascender(A, A.length, K);
if (J != -1) {
R[K] = Math.abs(K - J);
}
}
return R;
}
public static void main(String[] args) {
int[] a = { 4, 3, 1, 4, -1, 2, 1, 5, 7 };
/* int[] a = {-589630174, 806785750, -495838474, -648898313,
149290786, -798171892, 584782920, -288181260, -252589640,
133741336, -174886978, -897913872 }; */
int[] R = array_closest_ascenders(a);
for (int element : R) {
System.out.print(element + " ");
}
}
}
Some notes about the code. I guess break in array_closest_ascenders method should be replaced by continue so that all elements are analyzed for their ascenders.
And, surely, maximal(A) have to be moved out of a loop; instead assign maximal value to some variable before entering the loop and use it within the loop, thus avoiding redundant calculation of max value.
Here is C# Solution
class Program
{
static void Main(string[] args)
{
int[] A = new int[] { 4, 3, 1, 4, -1, 2, 1, 5, 7 };
int[] B = new int[A.Length];
int[] R = new int[A.Length];
Program obj = new Program();
obj.ABC(A,B, R);
}
public void ABC(int[] A,int[]B, int[] R)
{
int i, j, m,k;
// int temp = 0;
int n = A.Length - 1;
for (i = 0; i < n; i++)
{
for (j = 0; j <= n; j++)
{
if (A[i] < A[j])
{
m = Math.Abs(j - i);
R[i] = m;
break;
}
}
for (j = i-1; j > 0; j--)
{
if (A[i] < A[j])
{
k = Math.Abs(j - i);
B[i] = k;
break;
}
}
}
for (i = 0; i < n; i++)
{
if (R[i] > B[i] && (B[i] == 0))
{
R[i] = R[i];
//Console.WriteLine(R[i]);
//Console.ReadLine();
}
else { R[i] = B[i]; }
}
}
}
Basically in the search function I compare the first element of the array with the one immediately right, if it's bigger this means it is the first closest ascendant. For the other elements I compare the one immediately at left and afterward the one immediately right his first right element. The first one which is bigger is the closest ascendant, and I keep iterate this way until I don't find an element bigger than one I am considering or I return 0.
class ArrayClosestAscendent {
public int[] solution(int[] A) {
int i;
int r[] = new int[A.length];
for(i=0;i<A.length;i++){
r[i] = search(A, i);
}
return r;
}
public int search(int[] A, int i) {
int j,k;
j=i+1;
k=i-1;
int result = 0;
if(j <= A.length-1 && (A[j]>A[i]))
return Math.abs(j-i);
j++;
while(k>=0 || j < A.length){
if(k >= 0 && A[k] > A[i]){
return Math.abs(i-k);
}else if(j < A.length && A[j] > A[i]){
return Math.abs(i-j);
}else{
j++;
k--;
}
}
return result;
}
}
Related
Except 0, how to find a min. number in array :
myMethod()
{
for (i - 0 to i - length)
{
int currentMin = value_at_first_Index;
if(currentMin > value_at_first_Index)
currentMin = value_at_first_Index;
}
return currentMin;
}
Correct solution:
int FindFirstMinIndex(array)
{
int minIndex = 0;
for (int i = 1; i<array.length; i++)
if(array.elementAt(i) < array.elementAt(minIndex))
minIndex=i;
return minIndex;
}
How it works:
Start with the assumption that the first element (index 0) is the minimum:
int minIndex = 0;
Loop from the second element through the rest of the array:
for (int i = 1; i<array.length; i++)
Start from the second (index 1) element instead of the first (index 0) because we already assume the first will be the minimum if we find nothing with a lower value, and there is no need to compare it with itself inside the loop.
If the value of the element at the loop's current index (i) is less than the value of the element at the recorded minimum's index so far:
if(array.elementAt(i) < array.elementAt(minIndex))
Then a new minimum value has been found. Assign it's index as the new minimum's index:
minIndex=i;
After the loop, whatever index is recorded to the minIndex variable, is guaranteed to be the first index (in case of duplicate values) of the minimum value found throughout the array. So return that index:
return minIndex;
int a[]={5,2,4,5,1,7,9};
int lowestIndex=0;
for(int b=1; b<7; b++)
{
if(a[b]<a[lowestIndex]) lowestIndex=b;
}
return lowestIndex;
Solution
public int getMin (int[] arr) { int currentMin = arr[0]; for (int i = 0; i < arr.length; i++){ if (arr[i] != 0){ currentMin = Math.min(arr[i], currentMin); }}return currentMin; }
Move currentMin out of the for loop
public int myMethod (int[] array) {
int currentMin = array[0];
for (int i = 0; i < array.length; i++){
if (array[i] != 0 && array[i]>currentMin)
currentMin=array[i];
}
return currentMin;
}
I'm practicing the cracking the code interview on my spare time.
The question states: Is Unique: Implement an algorithm to determine if a string has all unique character. What if you cannot use additional data structures?
The solution I found is: https://github.com/careercup/CtCI-6th-Edition-cpp/blob/master/Ch%201.Arrays%20And%20Strings/1.Is%20Unique/1.%20Is_unique.cpp
My implementation is:
bool UniqueCharsHash(string word) {
map<char, bool> uniqueChar; //keyType, valueType
for (int i = 0; i < word.length(); i++) {
char letter = tolower(word[i]);
if (!uniqueChar[letter]) {
uniqueChar[letter] = true;
} else {
return false;
}
}
return true;
}
//O(n^2) run time using a two loops (1 outer and 1 inner)
bool UniqueCharNoDS(string word) {
for (int i = 0; i < word.length() - 1; i++) {
for (int j = i + 1; j < word.length(); j++) {
if (word[i] == word[j]) {
return false;
}
}
}
return true;
}
but in the hint portion of the book it states:
try a hash table
could a bit vector be useful
can you solve it in O(Nlogn) time
I was wondering in the 3 methods shown, are any of those NlogN time?
As has often been pointed out, this question is solvable in O(1) because the longest string made up of unique characters is 256 characters long.
So when/if your algorithm hits the 257th character, it can stop and report "no".
Even if you use the naive algorithm of searching each character in the prefix up to that point, there are a maximum of 255*128 comparisons before the limit is reached. (No adjustment to the algorithm is necessary; it must report "no" on the 257th character if there is one.)
The below code (in Java) will determine if a string has all unique character.
Time complexity --> O(n)
final static int LETTERS_LEN = 256;
public static boolean isUnique(String str){
int[] letters = new int[LETTERS_LEN];
for (int i = 0; i < str.length(); i++) {
letters[str.charAt(i)]++;
}
for (int i = 0; i < LETTERS_LEN; i++) {
if (letters[i] > 1) {
return false;
}
}
return true;
}
This code solves it in O(NlogN) time, it is a modification of merge sort
boolean isUnique(char[] arr){
return sort(arr,0,arr.length-1);
}
// Merges two subarrays of arr[].
// First subarray is arr[l..m]
// Second subarray is arr[m+1..r]
boolean merge(char arr[], int l, int m, int r)
{
// Find sizes of two subarrays to be merged
int n1 = m - l + 1;
int n2 = r - m;
/* Create temp arrays */
char L[] = new char [n1];
char R[] = new char [n2];
/*Copy data to temp arrays*/
for (int i=0; i<n1; ++i)
L[i] = arr[l + i];
for (int j=0; j<n2; ++j)
R[j] = arr[m + 1+ j];
/* Merge the temp arrays */
// Initial indexes of first and second subarrays
int i = 0, j = 0;
// Initial index of merged subarry array
int k = l;
while (i < n1 && j < n2)
{
if (L[i] < R[j])
{
arr[k] = L[i];
i++;
}
else if(L[i] > R[j])
{
arr[k] = R[j];
j++;
}
else{
return false;
}
k++;
}
while (i < n1)
{
arr[k] = L[i];
i++;
k++;
}
/* Copy remaining elements of L[] if any */
while (j < n2)
{
arr[k] = R[j];
j++;
k++;
}
return true;
}
// Main function that sorts arr[l..r] using
// merge()
boolean sort(char arr[], int l, int r)
{
if (l < r)
{
// Find the middle point
int m = (l+r)/2;
// Sort first and second halves
boolean left= sort(arr, l, m);
boolean right = sort(arr , m+1, r);
// Merge the sorted halves
return left&&right&&merge(arr, l, m, r);
}
return true;
}
An O(n) time could be used with the hint (#2) provided. Where you shift bits and flip if a letter has already been seen.
static boolean isUniqueNoStruct(String input) {
// Length check
if (input.length() > 256)
return false;
// Assuming only lowercase 32 bit characters
int checkVal = 0;
for (int i = 0; i < input.length(); i++) {
int bit = input.charAt(i) - 'a';
// If the bit at the index has been flipped return false
if ((checkVal & ( 1 << bit)) > 0) {
return false;
}
checkVal |= (1 << bit);
}
return true;
}
I am trying to create a C function that takes an array, finds the smallest element, and sets the value of that element to zero.
This is my function so far.
void find_minimum(double a[], int n) {
int i, smallest = 0;
smallest = a[0];
for (i = 0; i < n; i++) {
if (a[i] < smallest) {
smallest = a[i];
}
a[i] = 0;
}
}
When I run it, every index except the last one is zero, but I want only the smallest element to be zero.
There's a few issues with your code, I'm surprised your compiler didn't explode on you.
void find_minimum(double a[], size_t n) {
size_t i, index;
double smallest;
// sanity check to make sure we're not accessing outside allocated memory
if (n > 0) {
smallest = a[0];
index = 0;
} else {
// nothing left to do here
return;
}
// start at 1 because 0 is initial default
for (i = 1; i < n; i++) {
if (a[i] < smallest) {
smallest = a[i];
index = i;
}
}
// assign only the smallest index
a[index] = 0.0;
}
Feel free to post comments if you have any questions.
If we're assuming only one smallest like the OP and some answers, we can also keep track of just the index of the smallest, instead of the value of the smallest, to keep things simple:
void find_minimum(double a[], size_t n) {
if (n <= 0) {
return;
}
size_t smallest = 0;
for (size_t i = 1; i < n; i++) {
if (a[i] < a[smallest]) {
smallest = i;
}
}
a[smallest] = 0.0;
}
I'd like to address the case where there are more then one unique smallest value.
In such a case, two loops are needed. One to find out the smallest value over the entire array and the other to set to zero all the elements with that value.
I'll keep track of the minimum and maximum index where this value appears in the array to minimize the range of the second loop:
void set_smallest_to_zero(double a[], size_t n) {
if ( !a || !n ) {
return;
}
double smallest = a[0];
size_t min_index = 0,
max_index = 0,
i;
// find the smallest values
for ( i = 1; i < n; ++i ) {
if ( a[i] > smallest ) {
continue;
} else if ( a[i] < smallest ) {
smallest = a[i];
min_index = i;
max_index = i;
} else { // a[i] == smallest
max_index = i;
}
}
// set to zero all the the minimum values
for ( i = min_index; i <= max_index; ++i ) {
if ( a[i] == smallest ) {
a[i] = 0.0;
}
}
}
HERE there is a live example.
So I am trying to write this function where the input parameter array will be taken and copied into another array but in a sorted way. For example: an input parameter of 3, 1, 9, 8 will copy into the target array 1, 3, 8, 9.
This is what I have so far but it only copies the smallest element in every time. I'm looking for a way to "blacklist" smallest values that are discovered in each pass.
void sort_another_array(int *param, int *target, int size){
int i, j, lowest = param[0];
for(i = 0; i < size; i++){
for(j = 0; j < size; j++){
if(param[j] < lowest){
lowest = param[j]
}
}
target[i] = lowest;
}
}
Of course I could have another array of already found lowest values but that's more unnecessary looping and checking and adds to the already terrible n^2 complexity. Is there an easier way to do this?
I'm completely new to C, so please do restrict it to simple programming concepts of logic statements, using some flag variables etc..
The probably most straight-forward way to do this is to first copy the whole array and then sort the new array in-place using a standard sorting algorithm.
However, if you want to keep the current structure, the following would be an alternative when all elements are unique:
void sort_another_array(int *param, int *target, int size) {
int i, j, past_min = INT_MAX, current_min = INT_MAX;
for (i = 0; i < size; ++i) {
for (j = 0; j < size; ++j) {
if (i == 0 || param[j] > past_min) {
if (past_min == current_min || param[j] < current_min) {
current_min = param[j];
}
}
}
target[i] = current_min;
past_min = current_min;
}
}
What this does is keeping track of the previously lowest element found (past_min). The next element to find is lowest among all elements greater than past_min. I.e., we want both param[j] > past_min and param[j] < current_min to be true. However, the first element to add to target (i.e., when i == 0) will not have a lower element before it, so we add an exception for that. Similar, the first element satisfying param[j] > past_min in a pass will not have any element to compare with so we add another exception using past_min == current_min (this is true only for the first element found in a pass).
If you have duplicates in the array, this might work:
void sort_another_array(int *param, int *target, int size) {
int j, past_min, current_min, write = 0, round_write = 0;
while (round_write != size) {
for (j = 0; j < size; ++j) {
if (round_write == 0 || param[j] > past_min) {
if (write == round_write || param[j] < current_min) {
current_min = param[j];
write = round_write;
target[write] = current_min;
++write;
} else if (param[j] == current_min) {
target[write] = current_min;
++write;
}
}
}
round_write = write;
past_min = current_min;
}
}
Basically it's the same idea, but it writes all elements of the minimum value in the same pass.
You can use a modified insertion sort algorithm to solve this problem:
#include <stdio.h>
void sort_another_array(int *param, int *target, int size)
{
for ( int i = 0; i < size; i ++ ) // do for all elements in param
{
int j = i - 1;
while ( j >= 0 && target[j] > param[i] ) // find index of element in target which is samler or equal than param[i]
{
target[j+1] = target[j]; // shift forward element of target which is greater than param[i]
j --;
}
target[j+1] = param[i]; // insert param[i] into target
}
}
#define SIZE 10
int main( void )
{
int a[SIZE] = { 9, 8, 0, 2, 1, 3, 4, 5, 7, 6 };
int b[SIZE];
sort_another_array( a, b, SIZE );
for ( int i = 0; i < SIZE; i ++ )
printf( "%2d", b[i] );
return 0;
}
The solution I am providing, has a limitation that: If there are no duplicates in the array, then this will work:
void sort_another_array(int *param, int *target, int size)
{
int i, j, lowest;
for(i = 0; i < size; i++)
{
int k = 0;
if( i > 0) // for all except first iteration
{
while(param[k] <= target[i-1]) // find the one greater than the last one added
k++;
}
lowest = param[k];
for(j = 1; j < size; j++)
{
if( ( i==0 && param[j] < lowest ) || ( i > 0 && param[j] < lowest && param[j] > target[i-1])) // for all except first iteration the min found should be greater than the last one found
{
lowest = param[j];
}
}
target[i] = lowest;
}
}
Given a very large integer array, I need to find the maximum value of a4, such that:
a4 = a1 + a2 + a3
Where the ai's are all values in the array.
How would I do this?
Note: Using 4 for loops is not the ideal solution.
There is a simple (expected) O(n^2) solution:
Iterate through all pairs of array elements (a, b) and store their sum in a hash table.
Iterate through all candidate pairs (a4, a1) and check whether a4 - a1 is in the table. The maximum over all valid a4 is the solution. Of course you should process a4 from largest to smallest, but that doesn't affect the asymptotics.
If you want to avoid using an element more than once, you need some additional information stored in the hash table so that you can filter out pairs that colide with a1 or a4 fast.
If the integers in the array are bounded (max - min <= C), it might be useful to know that you can achieve O(n + C log C) using a discrete fourier transform (solvable using FFT).
First of all you should ascending sort your array. then start from the last (biggest) member of the array.
For example, for [1,2,3,777,999,111,665] you'll have sortedArray = {1,2,3,111,665, 777, 999}
then select 999 as a4 and try to create it with other members. So you should select as a3 and try to create (999 - 777) = 222 as a1+a2 since your array is sorted you only need to consider subarray {1,2,3,111}. if there is no pair satisfying this condition, try next biggest member (777) and retry above scenario to find the solution
Based on #Niklas answer, I wrote the following program in Java.
public static int sumOfThree(int [] arr) {
int arrlen = arr.length;
int arrijv [][] = new int [arrlen * (arrlen - 1) / 2][3];
int arrijvlen = 0;
quickSortInDescendingOrder(arr, 0, arrlen - 1); // sorts array into descending order
System.out.println(Arrays.toString(arr));
// populates array with sum of all pair values
for (int i = 0; i < arrlen - 1; i++) {
for (int j = i + 1; j < arrlen; j++) {
// if ((arr[i] + arr[j]) < arr[0]) { // can be added if no negative values
arrijv[arrijvlen][0] = i;
arrijv[arrijvlen][1] = j;
arrijv[arrijvlen][2] = arr[i] + arr[j];
arrijvlen++;
// }
}
}
System.out.print('[');
for (int i = 0; i < arrijvlen; i++) {
System.out.print(arrijv[i][2] + " ");
}
System.out.print("]\n");
// checks for a match of difference of other pair in the populated array
for (int i = 0; i < arrlen - 1; i++) {
for (int j = i + 1; j < arrlen; j++) {
int couldBeA4 = arr[i];
if(isAvailable(arrijv, arrijvlen, couldBeA4 - arr[j], i, j)){
System.out.println(" i3-" + j + " i4-" + i);
return couldBeA4;
}
}
}
return -1;
}
private static boolean isAvailable(int[][] arrijv, int len, int diff, int i, int j) {
boolean output = false;
// returns true if the difference is matched with other combination of i,j
for (int k = 0; k < len; k++) {
if (arrijv[k][2] == diff) {
int pi = arrijv[k][0];
int pj = arrijv[k][1];
if (pi != i && pi != j && pj != i && pj != j) {
System.out.print("i1-" + pj + " i2-" + pi);
output = true;
break;
}
}
}
return output;
}
private static void quickSortInDescendingOrder(int[] array, int low, int high) { // solely used for sorting input array into descending array
if (low < high) {
int partition = getPartitionIndex(array, low, high);
quickSortInDescendingOrder(array, low, partition);
quickSortInDescendingOrder(array, partition + 1, high);
}
}
private static int getPartitionIndex(int[] arr, int lo, int hi) {
int pivot = arr[(lo + hi) / 2];
while (true) {
while (arr[lo] > pivot) {
lo++;
}
while (arr[hi] < pivot) {
hi--;
}
if (arr[lo] == arr[hi]) { // can be removed if no duplicate values
return lo;
} else if (lo < hi) {
int temp = arr[lo];
arr[lo] = arr[hi];
arr[hi] = temp;
} else {
return hi;
}
}
}
Please verify that it works and suggest for further improvements.