Remove element from a list in C++ - c++

I am working on an exercise in C++ and I am trying to understand how to remove an element from a list and shift the rest to the left. I wonder if there is a neat solution. Here is my version, it seems to do the job, but I have a feeling there is a better way:
Account AccountList::remove(int i){
if(i>=0 && i<size()) {
for (int n = i; n < size(); n++) {
if(i+1!=size()) {
aList[n]=aList[n+1];
}
}
sz--;
return aList[i];
} else {
return Account();
}
}

You have two issues in this.
You are not returning the removed element, instead overwriting it with the next element and returning that one. I don't think this is your intention.
Your loop range is not right. With this loop, you will go past the array bounds with the index n+1 when n = size() - 1
The corrected one is given below.
Account AccountList::remove(int i)
{
if(i>=0 && i<size())
{
Account a = aList[i]
for (int n = i; n < size() - 1; n++)
{
if(i+1!=size())
{
aList[n]=aList[n+1];
}
}
sz--;
return a;
} else
{
return Account();
}
}

If you're doing this, you're not implementing the list correctly. A list should have complexity O(1) for removing an element. That looks more like an array or a vector.
A list typically consists of nodes linked to each other, in which case you'd only need to delete the node in question and make the previous node point to the node after the one you're deleting.

Related

deleting multiple elements in an array

i am trying to write a code that will delete all the elements if an array has same element at different index . it works fine for one element deletion or elements at odd index i.e 1,3,5 etc but it neglects one element if the consecutive index have same element.
i have just tried this to get my hands on arrays
for(int i=0;i<n;i++) //for deletion
{
if(arr[i]==_delete)
{
arr[i]=arr[i+1];
--n;
}
}
I suggest you use std::vector as a container for your objects.
std::vector<TYPE> vec ;
// initialise vector
You can use
vec.erase(std::remove_if(vec.begin(), vec.end(),
[](const auto & item){return item == _delete;}), vec.end());
Alternatively, you can use std::list. Its list::erase has linear time complexity.
As an additional solution, if you want to deal with built-in C++ arrays, the standard std::remove algorithm can be rewritten like this:
void remove(int _delete) {
int j = 0;
for (int i = 0; i < n; ++i) {
if (arr[i] != _delete) {
arr[j++] = arr[i];
}
}
// update the size!
n = j;
}
It's quite pretty:
We keep in the array the elements we only need, and override the ones in which we are not interested (they can be either equal or not to _delete and start at position j till the end)

How to remake an existing random array to have unique elements (with restrictions)

The question ask for a function that takes an array of integers pre-filled with random elements. The function goes through the array linearly and if any element is equal to any of the preceding elements, regenerate that element. This goes on until the whole array is made of unique elements.
I know that this is very inefficient way of generating an array with unique elements but I wanted to give it a try. I wrote this code which falls into an infinite loop.
void makeUnique(int* const objArr, const int& size)
{
int i = 1,j = 0;
do {
j = 0;
while (j < i) {
if (objArr[j] == objArr[i]) {
objArr[i] = rand();
--i;
break;
}
++j;
}
++i;
} while (i<size);
}
Where am I going wrong?

Why does skips the "if stack not empty" conditional, when the stack still has elements?

I'm trying to make a program to solve the eight queens problem, however it keeps reaching the last return, when it should not, and tried putting it on an else, but then it never reached it, even if i initially give it an empty stack.
Also for whatever reasons the first time i call the top() function, it return a different element than the last i added, but if i call it again it return the correct element.
So i would like to know where the problem is?
bool search(stack<nodo>& board, int n) {
nodo queen;
queen=board.top();
queen=board.top();
if (queen.y == n)
return true;
bool valid;
if (!board.empty()) {
queen.y += 1;
for(int i; i<=n; i++) {
queen.x = i;
valid = isvalid(queen,board);
if (valid) {
board.push(queen);
search(board,n);
}
}
board.pop();
}
return false;
}
use while not if
while(!board.empty()) {
queen.y += 1;
for(int i; i<=n; i++){
queen.x = i;
valid = isvalid(queen,board);
if (valid) {
board.push(queen);
search(board,n);
}
}
board.pop();
}
if means check for one time only , but while mean do the samething till board.empty() == true.

operator [ ] recursion

I need help creating a recursive definition for operator [] for a linked list.
LN has a int value and a next pointer
int & operator[] (int i, LN*l, int &k){
int k = 0;
//check if list is empty
if(l == 0)
return -1;
//base case
if(k == i)
return l->value;
else
//I need to traverse through the linked list until I reach the ith position
return operator[](i, l->next, ++k);
}
Am I on the right track? Is there a way I could eliminate the k variable?
//make this a member function
Assuming that there is a private LN* head
int & operator[](int &i){
{
LN* temp = head;
if(i < 0 || temp ==0)
return -1;
if(i == 0)
return temp->value;
else{
temp = temp->next;
return operator[](--i);
}
}
You could get rid of k (both the parameter and the local variable), by passing i-1 in your recursive call along with l->next. Then when i is 0 you know you want the current item.
return operator[](i-1, l->next);
You should also add some checks to make sure i isn't less than zero.
Also note - recursion isn't really helping here, you could more easily do this in a loop.
I'd rewrite it as:
int & operator[] (int i, LN* l){
if(i == 0) return l->value;
else return operator[](i - 1, l->next);
}
that is: decrement the i variable until we reach 0 (that means we have moved to the next i times).
Also if you want the syntactic sugar that is list[i] you should make this a member function of your list class.
On a side note you should use std::list<int> or std::forward_list<int> instead of creating your own implementation.
Finally you should notice that linked-lists, in general, are really not meant to be randomly accessed. You should an array based container instead.

Finding the Unique Elements Among n Arrays

I'm trying to write an algorithm that takes a variable amount of generic arrays, stored in d_arrays, and gathers all the unique elements (elements which occur exactly once) among them and stores them in an array, called d_results. For example, the arrays:
int intA[] = { 12, 54, 42 };
int intB[] = { 54, 3, 42, 7 };
int intC[] = { 3, 42, 54, 57, 3 };
Would produce the array d_results with the contents { 12, 7, 57 }.
Here's my current algorithm for the process:
template <class T>
inline
void UniqueTableau<T>::run() {
T* uniqueElements = d_arrays[0];
int count = 0;
for (int i = 1; i < d_currentNumberOfArrays; ++i) {
if (count == 0) {
uniqueElements = getUnique(uniqueElements, d_arrays[i], d_sizes[i - 1], d_sizes[i]);
++count;
}
else {
uniqueElements = getUnique(uniqueElements, d_arrays[i], d_numberOfElementsInResult, d_sizes[i]);
}
}
d_results = uniqueElements;
}
template <class T>
inline
T* UniqueTableau<T>::getUnique(T* first, T* second, int sizeOfFirst, int sizeOfSecond) {
int i = 0;
int j = 0;
int k = 0;
T* uniqueElements = new T[sizeOfFirst + sizeOfSecond];
while (i < sizeOfFirst) { // checks the first against the second
while ((first[i] != second[j]) && (j < sizeOfSecond)) {
++j;
}
if (j == sizeOfSecond) {
uniqueElements[k] = first[i];
++i;
++k;
j = 0;
} else {
++i;
j = 0;
}
}
i = 0;
j = 0;
while (i < sizeOfSecond) { // checks the second against the first
while ((second[i] != first[j]) && (j < sizeOfFirst)) {
++j;
}
if (j == sizeOfFirst) {
uniqueElements[k] = second[i];
++i;
++k;
j = 0;
} else {
++i;
j = 0;
}
}
T* a = new T[k]; // properly sized result array
for (int x = 0; x < k; ++x) {
a[x] = uniqueElements[x];
}
d_numberOfElementsInResult = k;
return a;
}
Note that d_sizes is an array holding the sizes of each array in d_arrays, and d_numberOfElementsInResult is the number of elements in d_results.
Now, what this array is doing is comparing two at a time, getting the unique elements between those two, and comparing those elements with the next array and so on. The problem is, when I do this, sometimes there are elements that are, for example, unique between the third array and the unique elements of the first two, but not unique between the third and first. That is confusingly worded, so here's a visual example using the arrays from above:
First, the algorithm finds the unique elements of the first and second arrays.
{ 12, 3, 7 }
Now, it checks this against the third array, producing the unique elements between those.
{ 12, 7, 42, 54, 57 }
Right? Wrong. The problem here, is that since 42 and 54 don't appear in the unique array, they end up in the final product, even though they are common to all three arrays.
Can anyone think of a solution for this? Alterations to this algorithm are preferred, but if that's not possible, what's another way to approach this problem?
EDIT: As pointed out the algorithm is O(nlogn) time and O(n) space complexity.
Do a traversal of each element in all the arrays and form a map of the count of each item traversed.
Once the map is created, just iterate through it and form array of those elements for which count is one.
Memory is the problem and though I'd do this in a different way (due lack of experience?) -- Actually I was thinking of the answer that just got posted!
Anyways, do not throw away your duplicates and save them in a secondary array. Take this array and append it twice to each new array and this will allow little change to your algorithm. Only change is creating the duplicates and looking through a larger list each time. Though this adds time and memory. If that is a concern then go with the first posted answer!
solution 1:
Just put all the element of all the arrays in to one.
sort the array
remove duplicate.
solution 2:
create a map where key is the element and value is boolean
just traverse individual array. if the element is not present in the map than put key as the element and value as true. But if the element is already present than make the value as false.
Now just print the element from the map whose value part is true i.e. just occurred once.
Why i am putting value as boolean not an integer:
As we know that if an element in the form of key in the map is present, it shows the element is present in the array. So if we make false next time if we find the element again it shows duplicate. Hope you understand.