Related
Is there any more efficient solution than this to remove some elements of the vector?
{
vector<int> v{1,2,3,4,5,6,7,8,9,10};
for (int i = 0; i < v.size(); i++)
{
if(v[i] % 2 == 0)
{
auto it2 = std::remove(v.begin(), v.end(), v[i]);
v.erase(it2);
}
}
for (auto it = v.begin(); it != v.end(); it++)
{
cout << *it;
}
return 0;
}
std::vector::erase invalidates iterators and references at or after the point of the erase, but the main issue with the posted code is that std::remove shifts the elements in the range, so that i may already be the next element and ++i will skip it.
The OP could use the erase-remove idiom (once!):
auto is_even = [](auto x){ return x % 2 == 0; };
v.erase( std::remove_if(v.begin(), v.end(), is_even)
, v.end() );
Since C++20, we can use std::erase_if:
std::erase_if(v, is_even);
Your code is wrong. Test with this input and you will see it break: {1,2,2,2,2,1}
When you remove, all elements are shifted so that the next element is the current one. Because of that you need to either skip the increment, or decrement i when you remove any element. You also need to resize the vector to remove the tail with the "removed" items. Something like:
if(v[i] % 2 == 0)
{
auto it2 = remove(v.begin(), v.end(), v[i]);
v.erase(it2);
v.resize(v.size()-1);
--i;
}
Having said that, this approach is not efficient and is very risky. You should use erase-remove idiom that "compacts" the elements matching the query to the beginning of the vector, before removing the remaining elements from the tail. This approach has the huge advantage of updating the whole vector only once.
On the Wikipedia page about Counting Sort, it states:
It is possible to modify the algorithm so that it places the items into sorted order within the same array that was given to it as the input, using only the count array as auxiliary storage; however, the modified in-place version of counting sort is not stable.
I am curious about how such algorithm is implemented, but I don't have access to the source cited. Could somebody explain how it works?
After counting, you have an array of counts for each value, say:
[4,3,1,2]
Shift it to the right:
[0,4,3,1]
With a cumulative sum, change this into an array of the start positions for each value in the sorted result:
[0,4,7,8]
Now you walk through the array, swapping each each item into place at the start position for its value, and incrementing the start position so the next one will go in the right place, but ONLY if the item belongs the same or earlier position. If it belongs in a later position, then just skip it, and the item that belongs there will be swapped in when we get to it (because it must belong in the earlier position).
Swapping will bring a new element into the target position, so repeat at the same position until you find one that isn't swapped.
Here's the algorithm in JavaScript, using values from 0 to 9:
const len = 25;
const array = [];
for (let i=0; i<len; ++i) {
array.push(Math.floor(Math.random()*10));
}
console.log("Original array:", String(array));
const cp = [0,0,0,0,0,0,0,0,0,0];
for (const val of array) {
++cp[val];
}
console.log("Counts:", String(cp));
for (let i=cp.length-1; i>0; --i) {
cp[i] = cp[i-1];
}
cp[0]=0;
for (let i=1; i<cp.length; ++i) {
cp[i]+=cp[i-1];
}
console.log("Start pointers: ", String(cp));
let pos=0;
while(pos < array.length) {
let v = array[pos];
let dest = cp[v];
if (dest <= pos) {
if (dest < pos) {
// v belongs at an earlier position. Swap it into place
array[pos] = array[dest];
array[dest] = v;
} else {
// v belongs at the same position. don't visit it again
++pos;
}
// increment the pointer for this value
cp[v] = dest+1;
} else {
// v belongs at a later position. Something later must belong here.
// Skip it and let the later item swap in when we get there
++pos;
}
}
console.log("Sorted array:", String(array));
Totally untested C++ code
#include <array>
#include <vector>
#include <algorithm>
#include <numeric>
void counting_sort(std::vector<uint8_t>& values) {
std::array<uint8_t , 256> count;
for(auto& value : values)
count[value]++; // count
std::partial_sum(count.begin(), count.end(), count.begin()); // sum
std::array<uint8_t , 256> position;
position[0] = 0; // first position of first value
std::copy_n(count.begin(), count.size()-1, std::next(position.begin())); // moved by one
int pos = 0;
while (pos < count.size()) {
while (count[pos] > position[pos]) {
auto& from = position[pos]; // current position
auto& to = position[values[from]]; // final position
if (to != from)
std::swap(values[from], // from current position
values[to]); // where the value needs to go
to++; // update destination position
}
pos++;
}
}
In the while with the swap you keep swapping until the value that should be place in the first position is swapped into that position.
0 // pos
[3,2,1] // values
[0,1,1,1] // count
[_0_,1,2,3] // count
[_0_,0,1,2] // position
1 // pos
[0,_1_,2,3] // count
[0,_0_,1,2] // position
values[position[pos]] -> 3
position[3] -> 2
position[pos] -> 0
[_3_,2,_1_]
swap
[1,2,3]
position[values[pos]]++
[0,0,1,_2_] // position
[0,0,1,_3_] // position
1 // pos
[0,_1_,2,3] // count
[0,_0_,1,3] // position
values[position[pos]] -> 1
position[1] -> 0
position[pos] -> 0
positions are the same so update to
[0,_0_,1,3] // position
[0,_1_,1,3] // position
[0,_1_,2,3] // count
[0,_1_,1,3] // position
update pos
pos = 2
[0,1,_2_,3] // count
[0,1,_1_,3] // position
positions are the same to update to
[0,1,_1_,3] // position
[0,1,_2_,3] // position
count&position are the same so update pos
pos = 3
count&position are the same so update pos
pos = 4
done
I want to pass an array from one object, store reference and then work with this array inside my function, but...
I have a terrible misunderstanding of passing an array process: In the class TreeType.
I’m facing with an error and I have tried to resolve that for 3 days, but I couldn’t.
Function:
void AddElements(TreeType& tree, int info[], int fromIndex, int toIndex)
{
int midIndex;
if (fromIndex <= toIndex)
{
midIndex = (fromIndex + toIndex) / 2;
tree.PutItem(info[midIndex]);
AddElements(tree, info, fromIndex, midIndex - 1);
// Complete the left subtree.
AddElements(tree, info, midIndex+1, toIndex);
// Complete the right subtree.
}
}
void MakeTree(TreeType& tree, int info[], int length)
// Creates a binary tree from a sorted array.
{
tree.MakeEmpty();
int arrayb[length];
for(int i = 0; i < length; i++)
{
cout << "Enter Value to make tree:" << endl;
cin >> arrayb[i];
}
AddElements(tree, info, 0, length-1);
}
And invoked in main.cpp.
else if (command == "MakeTree")
{
int length=25;
//int arrayb[length];
int arrayb[]={-1000,-967,-923,-844,-669,-567,-455,-267,-209,-183,-59,-23,68,132,159,170,222,228,233,241,389,479,824,939,985};
tree.MakeTree(tree,arrayb,length);
Error capture
Can someone give me an algorithm to count distinct elements of an array of integers in one pass.
for example i can try to traverse through the array using a for loop
I will store the first element in another array.And the subsequent elements will be compared with those in the second array and if it is distinct then i will store it in that array and increment counter.
can someone give me a better algorithm than this.
Using c and c++
Supposing that your elements are integers and their values are between 0 and MAXVAL-1.
#include <stdio.h>
#include <string.h>
#define MAXVAL 50
unsigned int CountDistinctsElements(unsigned int* iArray, unsigned int iNbElem) {
unsigned int ret = 0;
//this array will contains the count of each value
//for example, c[3] will contain the count of the value 3 in your original array
unsigned int c[MAXVAL];
memset(c, 0, MAXVAL*sizeof(unsigned int));
for (unsigned int i=0; i<iNbElem; i++) {
unsigned int elem = iArray[i];
if (elem < MAXVAL && c[elem] == 0) {
ret++;
}
c[elem]++;
}
return ret;
}
int main() {
unsigned int myElements[10] = {0, 25, 42, 42, 1, 2, 42, 0, 24, 24};
printf("Distincts elements : %d\n", CountDistinctsElements(myElements, 10));
return 0;
}
Output : (Ideone link)
Distincts elements : 6
Maintain a array of structures.
structure should have a value and a counter of that value.
As soon as you pass an new element in an array being tested create a structure with value and increment the counter by 1.if you pass an existing element in the array then simply access the related structure and increment its counter by 1.
Finally after you do a one complete pass of the array, you will have the required result in the array of structures.
Edit: I wasn't aware you wanted just to count the elements. Updated code below.
int countUnique()
{
uniqueArray[numElements];
myArray[numElements];
int counter = 0;
int uniqueElements = 0;
for(int i = 0; i < numElements; i++)
{
element tempElem = myArray[i];
if(!doesUniqueContain(tempElem, counter, uniqueArray)//If it doesn't contain it
{
uniqueArray[counter] = tempElem;
uniqueElements++;
}
}
return uniqueElements;
}
bool doesUniqueContain(element oneElement, int counter, array *uniqueArray)
{
if(counter == 0)
{
return false; //No elements, so it doesn't contain this element.
}
for(int i = 0; i < counter; i++)
{
if(uniqueArray[i] == oneElement)
return true;
}
return false;
}
This is only so you can see the logic
How about using a hash table (in the Java HashMap or C# Dictionary sense) to count the elements? Basically you create an empty hash table with the array element type as the key type and the count as values. Then you iterate over your list. If the element is not yet in the hash table, you add it with count 1, otherwise you increment the count for that element.
This is an interview question.
Given a string such as: 123456abcdef consisting of n/2 integers followed by n/2 characters. Reorder the string to contain as 1a2b3c4d5e6f . The algortithm should be in-place.
The solution I gave was trivial - O(n^2). Just shift the characters by n/2 places to the left.
I tried using recursion as -
a. Swap later half of the first half with the previous half of the 2nd part - eg
123 456 abc def
123 abc 456 def
b. Recurse on the two halves.
The pbm I am stuck is that the swapping varies with the number of elements - for eg.
What to do next?
123 abc
12ab 3c
And what to do for : 12345 abcde
123abc 45ab
This is a pretty old question and may be a duplicate. Please let me know.. :)
Another example:
Input: 38726zfgsa
Output: 3z8f7g2s6a
Here's how I would approach the problem:
1) Divide the string into two partitions, number part and letter part
2) Divide each of those partitions into two more (equal sized)
3) Swap the second the third partition (inner number and inner letter)
4) Recurse on the original two partitions (with their newly swapped bits)
5) Stop when the partition has a size of 2
For example:
123456abcdef -> 123456 abcdef -> 123 456 abc def -> 123 abc 456 def
123abc -> 123 abc -> 12 3 ab c -> 12 ab 3 c
12 ab -> 1 2 a b -> 1 a 2 b
... etc
And the same for the other half of the recursion..
All can be done in place with the only gotcha being swapping partitions that aren't the same size (but it'll be off by one, so not difficult to handle).
It is easy to permute an array in place by chasing elements round cycles if you have a bit-map to mark which elements have been moved. We don't have a separate bit-map, but IF your characters are letters (or at least have the high order bit clear) then we can use the top bit of each character to mark this. This produces the following program, which is not recursive and so does not use stack space.
class XX
{
/** new position given old position */
static int newFromOld(int x, int n)
{
if (x < n / 2)
{
return x * 2;
}
return (x - n / 2) * 2 + 1;
}
private static int HIGH_ORDER_BIT = 1 << 15; // 16-bit chars
public static void main(String[] s)
{
// input data - create an array so we can modify
// characters in place
char[] x = s[0].toCharArray();
if ((x.length & 1) != 0)
{
System.err.println("Only works with even length strings");
return;
}
// Character we have read but not yet written, if any
char holding = 0;
// where character in hand was read from
int holdingPos = 0;
// whether picked up a character in our hand
boolean isHolding = false;
int rpos = 0;
while (rpos < x.length)
{ // Here => moved out everything up to rpos
// and put in place with top bit set to mark new occupant
if (!isHolding)
{ // advance read pointer to read new character
char here = x[rpos];
holdingPos = rpos++;
if ((here & HIGH_ORDER_BIT) != 0)
{
// already dealt with
continue;
}
int targetPos = newFromOld(holdingPos, x.length);
// pick up char at target position
holding = x[targetPos];
// place new character, and mark as new
x[targetPos] = (char)(here | HIGH_ORDER_BIT);
// Now holding a character that needs to be put in its
// correct place
isHolding = true;
holdingPos = targetPos;
}
int targetPos = newFromOld(holdingPos, x.length);
char here = x[targetPos];
if ((here & HIGH_ORDER_BIT) != 0)
{ // back to where we picked up a character to hold
isHolding = false;
continue;
}
x[targetPos] = (char)(holding | HIGH_ORDER_BIT);
holding = here;
holdingPos = targetPos;
}
for (int i = 0; i < x.length; i++)
{
x[i] ^= HIGH_ORDER_BIT;
}
System.out.println("Result is " + new String(x));
}
}
These days, if I asked someone that question, what I'm looking for them to write on the whiteboard first is:
assertEquals("1a2b3c4d5e6f",funnySort("123456abcdef"));
...
and then maybe ask for more examples.
(And then, depending, if the task is to interleave numbers & letters, I think you can do it with two walking-pointers, indexLetter and indexDigit, and advance them across swapping as needed til you reach the end.)
In your recursive solution why don't you just make a test if n/2 % 2 == 0 (n%4 ==0 ) and treat the 2 situations differently
As templatetypedef commented your recursion cannot be in-place.
But here is a solution (not in place) using the way you wanted to make your recursion :
def f(s):
n=len(s)
if n==2: #initialisation
return s
elif n%4 == 0 : #if n%4 == 0 it's easy
return f(s[:n/4]+s[n/2:3*n/4])+f(s[n/4:n/2]+s[3*n/4:])
else: #otherwise, n-2 %4 == 0
return s[0]+s[n/2]+f(s[1:n/2]+s[n/2+1:])
Here we go. Recursive, cuts it in half each time, and in-place. Uses the approach outlined by #Chris Mennie. Getting the splitting right was tricky. A lot longer than Python, innit?
/* In-place, divide-and-conquer, recursive riffle-shuffle of strings;
* even length only. No wide characters or Unicode; old school. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void testrif(const char *s);
void riffle(char *s);
void rif_recur(char *s, size_t len);
void swap(char *s, size_t midpt, size_t len);
void flip(char *s, size_t len);
void if_odd_quit(const char *s);
int main(void)
{
testrif("");
testrif("a1");
testrif("ab12");
testrif("abc123");
testrif("abcd1234");
testrif("abcde12345");
testrif("abcdef123456");
return 0;
}
void testrif(const char *s)
{
char mutable[20];
strcpy(mutable, s);
printf("'%s'\n", mutable);
riffle(mutable);
printf("'%s'\n\n", mutable);
}
void riffle(char *s)
{
if_odd_quit(s);
rif_recur(s, strlen(s));
}
void rif_recur(char *s, size_t len)
{
/* Turn, e.g., "abcde12345" into "abc123de45", then recurse. */
size_t pivot = len / 2;
size_t half = (pivot + 1) / 2;
size_t twice = half * 2;
if (len < 4)
return;
swap(s + half, pivot - half, pivot);
rif_recur(s, twice);
rif_recur(s + twice, len - twice);
}
void swap(char *s, size_t midpt, size_t len)
{
/* Swap s[0..midpt] with s[midpt..len], in place. Algorithm from
* Programming Pearls, Chapter 2. */
flip(s, midpt);
flip(s + midpt, len - midpt);
flip(s, len);
}
void flip(char *s, size_t len)
{
/* Reverse order of characters in s, in place. */
char *p, *q, tmp;
if (len < 2)
return;
for (p = s, q = s + len - 1; p < q; p++, q--) {
tmp = *p;
*p = *q;
*q = tmp;
}
}
void if_odd_quit(const char *s)
{
if (strlen(s) % 2) {
fputs("String length is odd; aborting.\n", stderr);
exit(1);
}
}
By comparing 123456abcdef and 1a2b3c4d5e6f we can note that only the first and the last characters are in their correct position. We can also note that for each remaining n-2 characters we can compute their correct position directly from their original position. They will get there, and the element that was there surely was not in the correct position, so it will have to replace another one. By doing n-2 such steps all the elements will get to the correct positions:
void funny_sort(char* arr, int n){
int pos = 1; // first unordered element
char aux = arr[pos];
for (int iter = 0; iter < n-2; iter++) { // n-2 unordered elements
pos = (pos < n/2) ? pos*2 : (pos-n/2)*2+1;// correct pos for aux
swap(&aux, arr + pos);
}
}
Score each digit as its numerical value. Score each letter as a = 1.5, b = 2.5 c = 3.5 etc. Run an insertion sort of the string based on the score of each character.
[ETA] Simple scoring won't work so use two pointers and reverse the piece of the string between the two pointers. One pointer starts at the front of the string and advances one step each cycle. The other pointer starts in the middle of the string and advances every second cycle.
123456abcdef
^ ^
1a65432bcdef
^ ^
1a23456bcdef
^ ^
1a2b6543cdef
^ ^