Group duplicate items in vector - c++ [closed] - c++

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
INPUT : [3,3,3,2,2,2,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0]
OUTPUT : [[3,3,3],[2,2,2],[1,1,1,1,1],[0,0,0,0,0,0,0,0,0,0]]
The Input is a vector of int while the Output is a vector of vectors of ints. The aim is to do this in the most efficient possible way in terms of time-taken.
The solution I am currently using is this :
vector<vector<int> results;
vector<int> result;
for(int i = 0 ; i < list.size() - 1 ; i++ ){
result.push_back(list[i]);
if ( list[i] != list[i+1]){
results.push_back(result);
result.clear();
}
}
result.push_back(list[list.size()-1]);
results.push_back(result);
credit to : #kabanus

You should use the standard algorithm library as much as possible
This is a possible implementation:
template <class T>
auto make_clusters(std::vector<T>& v) -> std::vector<std::vector<T>>
{
std::vector<std::vector<T>> clusters;
auto cluster_begin = v.begin();
while (cluster_begin != v.end())
{
auto elem = *cluster_begin;
auto cluster_end = std::find_if(cluster_begin, v.end(),
[&](int e) { return e != elem; });
clusters.emplace_back(std::distance(cluster_begin, cluster_end), elem);
cluster_begin = cluster_end;
}
return clusters;
}

You're close. You already figured out your bounds problem, but consider what happens at the interface of clusters:
..2,2,3,3...
^ ^
i i+1
You are going to enter the else (else if is unnecessary if the condition is the exact opposite of the original if) and forget to add that last 2. If there are no duplicates in the vector, such as
`{1,2,3,4}`
You are not going to add anything but empty clusters! So, you always want to add the number, rather you're in a cluster or ending it. If you're ending a cluster you also want to add it and clear.
for(int i = 0 ; i < sorted.size()-1 ; i++ ){
cluster.push_back(sorted[i]);
if ( sorted[i] != sorted[i+1]){
clusters.push_back(cluster);
cluster.clear();
}
}
Finally, as #tobi303 mentioned the last element is missing. This is especially obvious with a list with a single element ({3}). Note the last cluster is not added in any case, whether if it's a new single element at the end or just a final cluster.
So, once we exit the for we need one more check (not really) - if the cluster is empty that means the last element is not a part of it, and is a new one. Otherwise, the last cluster wasn't added yet and you need to append the last element to it, and then add the cluster. I'm leaving this one up to you.

Related

Issue with leet code problem 3 Longest substring [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 months ago.
Improve this question
Essentially we are asked to find, given a string, the longest substring with no repeating characters, below I am using the sliding window approach.
Examples:
Input: s = "abcabcbb"
Output: 3
Explanation: The answer is "abc", with the length of 3.
Input: s = "bbbbb"
Output: 1
Explanation: The answer is "b", with the length of 1.
Input: s = "pwwkew"
Output: 3
Explanation: The answer is "wke", with the length of 3.
Notice that the answer must be a substring, "pwke" is a subsequence and not a substring.
My attempt:
class Solution {
public:
int lengthOfLongestSubstring(std::string s){
int count{0};
std::map<char,int> char_map;
std::vector<char> char_vec;
auto left{char_vec.begin()};
auto right{char_vec.begin()};
for(int i = 0; i < s.length(); i++){
char_vec.push_back(s[i]);
if(char_map.find(s[i]) != char_map.end()){
char_map[s[i]]++;
}
else{
char_map.insert(std::pair<char,int>{s[i],1});
}
while(++right != char_vec.end() && char_map[*(right)] > 1){
char_map[*(left++)]--;
}
count = (count < std::distance(left,right)) ? std::distance(left,right) : count;
}
return count;
}
};
However, there is an issue in the while loop near the end of the code block that is causing
compiler error and am very confused about how to solve it.
So your code is suffering from iterator invalidation. Here you have a vector
std::vector<char> char_vec;
and here you create two iterators to that vector
auto left{char_vec.begin()};
auto right{char_vec.begin()};
and then here you add an item to that vector
char_vec.push_back(s[i]);
When you add an item to a vector you may invalidate any iterators to that vector, and any use of such iterators causes your program to have undefined behaviour.
Instead of using iterators you could try using offsets (i.e. integer variables which you use to index the vector). These have the advantage that they are not invalidated as the vector grows.
For more information on iterator invalidation see the table on this page. Different containers have different behaviour wrt iterator invalidation.

Range updation of values in c++ vectors [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
Given a vector of integers v, whose size is n and stores all 0's initially. If I want to update some elements of a range, say from index l to r, where (0<=l<r<n). Is there any efficient way instead of running loop from l to r?
For example,
v = {0,0,0,0,0,0,0}.
I want to update elements from l=2 to r=5.
Update refers to v[i] += k, where k is some known value. If k=1, then final updated vector in above case would be-
v = {0,0,1,1,1,1,0}.
Thanks:)
You can use for_each (ccpreference.com) or for_each_n
std::vector<int> data{0, 0, 0, 0, 0, 0, 0, 0};
std::for_each(data.begin() + 2, data.begin() + 6, [](int& i) { i += 1;});
// or with for_each_n
// std::for_each_n(data.begin() + 2, 4, [](int& i) { i += 1;});
for (const auto i : data) {
std::cout << i << ' ';
}
But as the comment above mentioned there will be a for loop in there, even though you don't explicitly write one.
Here a short explanation what the code does:
From the reference page we learn:
Applies the given function object f to the result of dereferencing every iterator in the range [first, last), in order.
In our case we provide for first data.begin() + 2 which is the 3rd element of the vector and for last we provide data.begin() + 6. This element is not included in the application of the function (this is what [first, last) means).
The last part is the function f that we have to provide. Here we use a lambda function that simply increases the parameter by 1. It's important that the function paramter of the lambda takes a reference (int& i) and not just a copy, otherwise the vector remain the same as we only change copies of the elements.

How to iterate over unique elements in an array in c++ [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
Suppose I have the following array:
int arr[7] = {18,16,5,5,18,16,4}
How can I iterate over unique elements(18, 16, 5 and 4) in a loop in the same order in which they occur?
I could use a set but then the order of the iteration would change(set stores elements in ascending order).
What is the fastest solution to this problem?
Iterate over the array and store the numbers you have already seen in a set. For each iteration you check whether the number is already in the set or not. If yes, skip the current element. If not, process it and insert it into the set.
Also note that you want an std::unordered_set and not a std::set which is ordered. Order doesn't matter for your filtering set.
If the values are in a known limited range, you can use a lookup table. Create an array with bool elements, sized to maximum value + 1. Use the values of the first array as index into the bool array.
#include <iostream>
int main() {
int arr[7] = {18,16,5,5,18,16,4};
constexpr int maxValue = 18;
bool lookup[maxValue + 1]{};
for( auto i : arr )
{
if( ! lookup[ i ] )
{
std::cout << i << ' ';
lookup[ i ] = true;
}
}
}
Live Demo
A std::bitset would be more space efficient but also slower, because individual bits cannot be directly addressed by the CPU.
Simply replace the bool array like so:
std::bitset<maxValue + 1> lookup;
The remaining code stays the same.
Live Demo

Middle node of Singly linked List [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I found this code to print the middle node of a list in C++ but I don't understand the code...Someone can explain me this?
Type& findMiddleNode()
{
int check = 0;
nodeType *current;
nodeType *mid;
current = first;
mid = first;
while (current != NULL)
{
current = current->link;
check = (check + 1) % 2;
if (check == 0)
mid = mid->link;
}
return mid->info;
}
PD: This code works perfect, but I dont understand! Someone help me to understand this. Thanks!
The basic idea is to move two pointers B and A through the list, but with B moving at only half the speed of A.
The statement
check = (check + 1) % 2;
… gives check the values 0, 1, 0, 1 and so on, which is used to move B only every second time A is moved.
The same idea is one possible (and expected) answer to a question about checking whether a singly linked list contains a loop. In this case the fast moving pointer will catch up with the slow one after both have entered the loop.
A simpler way to do the same, with just about the same work expended by the program, is to (1) count the number of nodes n, and (2) starting at the start again, go to node number n/2.
Step (1) moves a pointer n times, like A above, and step (2) moves a pointer n/2 times, like B above.

Counting Occurrences of integers in map c++ [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
I am trying to see if there are any duplicates of integers as I am inserting them using map because it`s auto sorting them when the numbers are inserted.
For example when I insert integers in the following order : 2 3 2 4 5
I want an output like : at least a number is duplicated , ` I have tried many things but no success, any ideas?
The problems I am facing is this: You have a array of type integers and you have to find if there are any duplicates using map .
Use map::find
int keyToInsert = 2;
std::map<int, int>::iterator it;
it = yourMap.find(key);
if(it != yourMap.end()){
//alert user key exists
}
else {
//key doesn't exist
}
See docs: http://www.cplusplus.com/reference/map/map/find/
The way you are approaching the problem seems fundamentally wrong. std::map is a data structure used to "map" logical entities in a container.
for example it can be used to map names to phone numbers. like this:
{ ("Tom", 2344556), ("Amanda", 545654), ...}
that would be an example of std::map<std::string,int> .
a map is NOT used for keeping seperate int values together. if you want that functionality you should look into other containers.
If you want to use a container that keeps values in order (and keeps duplicates) you can use std::list or std::vector, if you want a data structure where order is not guaranteed but access is fast and duplicates are generally avoided, you can use std::set
I think you want something like (untested code):
bool check_for_duplicate(const std::map<my_key_type, int>& my_map)
{
std::set<int> my_set;
for (auto& i : my_map)
{
if (!my_set.insert(i.second).second) // If it failed to insert
return true;
}
return false;
}
Idea is to take "integers" as key and "number of repetition " as value of map .By doing so , you will not only able to figure out whether it a number was repeated but you would also figure out "how many times was it actually repeated " .I am sharing below code snippet .
#include <iostream>
#include <map>
using namespace std;
int main ()
{
int arr[10] = {1,2,3,4,1,2,2,1,4,5};
std::map<int,int> dup_map;
for(int i=0;i<=9;i++)
{
if(dup_map.find(arr[i])!=dup_map.end())
{
//key exist and hence update the dulpicate count;
dup_map[arr[i]]++;
}
else{
//it doesn't exist in map
dup_map.insert(std::pair<int,int>(arr[i],1));//single count of current number
}
}
for(std::map<int,int>::iterator it =dup_map.begin();it!=dup_map.end();it++)
{
cout<<"\n Number "<<it->first<<" is repeated "<<it->second<<" times ";
}
}
Output of the program is as below :
Number 1 is repeated 3 times
Number 2 is repeated 3 times
Number 3 is repeated 1 times
Number 4 is repeated 2 times
Number 5 is repeated 1 times