LeetCode: TwoSum Solution - c++

I'm trying to use a map in order to make the algorithm for this answer https://leetcode.com/problems/two-sum/#/description O(n), but for some reason i'm getting the improper indices for a lot of test cases i'm trying
From what I can tell, I'm doing the checks properly for the iterators, however these are kind of new to me, and i'm not entirely sure if i'm returning the correct indices that I want.
//My Code:
#include <iostream>
#include <cstdio>
#include <array>
#include <vector>
#include <map>
std::vector<int> twoSum(int nums[], int size, int target)
{
std::vector<int> answer;
std::map<int, int> myMap;
std::map<int, int>::iterator it;
std::cout << size << std::endl;
for (int i = 0; i < size; i++)
{
myMap.insert(std::pair<int, int>(nums[i], i));
int indexItOne = distance(myMap.begin(), myMap.find(nums[i]));
int indexItTwo = distance(myMap.begin(), myMap.find(target-nums[i]));
it = myMap.find(target - nums[i]);
if (it != myMap.begin() || indexItOne != indexItTwo)
{
answer.push_back(i);
answer.push_back(distance(myMap.begin(), myMap.find(target - nums[i])));
return answer;
}
}//for
}//twoSum

You are correct in that the map should be a mapping from num to the index of that num, but it should not be inserted into the map right away. This is due to the constraint of the problem that
you may not use the same element twice.
Therefore, the algorithm would go something more like this:
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
// Create a mapping from num -> index of num
unordered_map<int, int> m;
for(int i = 0; i < nums.size(); i++) {
// Check if we have seen our buddy
int buddy = target - nums[i];
auto buddyIt = m.find(buddy);
if(buddyIt != m.end()) {
// Buddy found, return answer
return vector<int>{ buddyIt->second, i };
}
// Buddy not found, insert current num into buddy map
m[nums[i]] = i;
}
}
};

Related

Why make_heap() is not making minimum heap?

I am trying to make_heap() a vector of integers with a comparator function for minimum integer ordering, but when I am trying to check front value of the vector (which should be the lowest among the heap values), it is not 1. Even after debugging my code, I can't figure out why. Basically, I want to extract lowest integer data for n no. of times from the heap where n = no. of data in the vector. Thank you.
The final data of result variable must be {1,2}.
This is my code
#include <vector>
#include <algorithm>
#include <iostream>
std::vector<int> targetIndices(std::vector<int>& nums, int target) {
int i = 0, j = nums.size() - 1;
std::vector<int> result;
std::make_heap(nums.begin(),nums.end(),std::greater<int>());
while(nums.size()) {
std::pop_heap(nums.begin(), nums.end(),std::greater<int>());
int data = nums.front();
nums.pop_back();
if(data > target) return result;
if(data == target) result.push_back(i);
i++;
}
return result;
}
int main() {
std::vector<int> nums = {2,5,2,3,1};
std::vector<int> result = targetIndices(nums, 2);
for(int i : result)
std::cout << i <<std::endl;
}

Select all elements but one with given index from std::vector?

Given a std::vector, for example of ints
std::vector vec{10, 20, 30}
how to select all items except of with given index, for example int i=1 resulting
std::vector {10, 30}?
If you just want to "select" values from the original vector, I would create another vector with all the new values.
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> vect{ 10, 20, 30 };
vector<int> selected;
int i = 1;
for (int j = 0; j < vect.size(); j++) {
if (j != i) {
selected.push_back(vect[j]);
}
}
// Added so you can check the new values
for (int z = 0; z < selected.size(); z++) {
cout << selected[z] << " ";
}
return 0;
}
However, if you want to erase values from your original vector I would recommend using the vector.erase method (research the documentation).
Here is a function for it where you can pass the vector and index and it will return you the new vector without that index element.
#include <iostream>
#include <vector>
using namespace std;
// returns a new vector without the v[index]
vector<int> getElementsExceptIndex(vector<int> v, int index){
vector<int> newVector;
for(auto &x:v ){
if(( &x - &v[0]) != index)
newVector.push_back(x);
}
return newVector;
}
int main() {
vector<int> originalVector{ 10, 20, 30 ,33,53};
int index=1;
auto RemovedIndexVector = getElementsExceptIndex(originalVector,index);
for(auto item:RemovedIndexVector)
cout<<item<<" ";
return 0;
}
// Output - 10 30 33 53
Hope this helps

Deleting both an element and its duplicates in a Vector in C++

I've searched the Internet and known how to delete an element (with std::erase) and finding duplicates of an element to then delete it (vec.erase(std::unique(vec.begin(), vec.end()),vec.end());). But all methods only delete either an element or its duplicates.
I want to delete both.
For example, using this vector:
std::vector<int> vec = {2,3,1,5,2,2,5,1};
I want output to be:
{3}
My initial idea was:
void removeDuplicatesandElement(std::vector<int> &vec)
{
std::sort(vec.begin(), vec.end());
int passedNumber = 0; //To tell amount of number not deleted (since not duplicated)
for (int i = 0; i != vec.size(); i = passedNumber) //This is not best practice, but I tried
{
if (vec[i] == vec[i+1])
{
int ctr = 1;
for(int j = i+1; j != vec.size(); j++)
{
if (vec[j] == vec[i]) ctr++;
else break;
}
vec.erase(vec.begin()+i, vec.begin()+i+ctr);
}
else passedNumber++;
}
}
And it worked. But this code is redundant and runs at O(n^2), so I'm trying to find other ways to solve the problem (maybe an STL function that I've never heard of, or just improve the code).
Something like this, perhaps:
void removeDuplicatesandElement(std::vector<int> &vec) {
if (vec.size() <= 1) return;
std::sort(vec.begin(), vec.end());
int cur_val = vec.front() - 1;
auto pred = [&](const int& val) {
if (val == cur_val) return true;
cur_val = val;
// Look ahead to the next element to see if it's a duplicate.
return &val != &vec.back() && (&val)[1] == val;
};
vec.erase(std::remove_if(vec.begin(), vec.end(), pred), vec.end());
}
Demo
This relies heavily on the fact that std::vector is guaranteed to have contiguous storage. It won't work with any other container.
You can do it using STL maps as follows:
#include <iostream>
#include <vector>
#include <unordered_map>
using namespace std;
void retainUniqueElements(vector<int> &A){
unordered_map<int, int> Cnt;
for(auto element:A) Cnt[element]++;
A.clear(); //removes all the elements of A
for(auto i:Cnt){
if(i.second == 1){ // that if the element occurs once
A.push_back(i.first); //then add it in our vector
}
}
}
int main() {
vector<int> vec = {2,3,1,5,2,2,5,1};
retainUniqueElements(vec);
for(auto i:vec){
cout << i << " ";
}
cout << "\n";
return 0;
}
Output:
3
Time Complexity of the above approach: O(n)
Space Complexity of the above approach: O(n)
From what you have searched, we can look in the vector for duplicated values, then use the Erase–remove idiom to clean up the vector.
#include <vector>
#include <algorithm>
#include <iostream>
void removeDuplicatesandElement(std::vector<int> &vec)
{
std::sort(vec.begin(), vec.end());
if (vec.size() < 2)
return;
for (int i = 0; i < vec.size() - 1;)
{
// This is for the case we emptied our vector
if (vec.size() < 2)
return;
// This heavily relies on the fact that this vector is sorted
if (vec[i] == vec[i + 1])
vec.erase(std::remove(vec.begin(), vec.end(), (int)vec[i]), vec.end());
else
i += 1;
}
// Since all duplicates are removed, the remaining elements in the vector are unique, thus the size of the vector
// But we are not returning anything or any reference, so I'm just gonna leave this here
// return vec.size()
}
int main()
{
std::vector<int> vec = {2, 3, 1, 5, 2, 2, 5, 1};
removeDuplicatesandElement(vec);
for (auto i : vec)
{
std::cout << i << " ";
}
std::cout << "\n";
return 0;
}
Output: 3
Time complexity: O(n)

Finding maximum clique with node count and nonadjacent edge list given

I have a task which I have been trying to solve for the last week. It's driving me crazy. The task is:
Given a node count N(1 <= N <= 10`000),
nonadjacent node pair count M(1 <= M <= 200`000)
and the nonadjacent node pairs themselves
M0A, M0B,
M1A, M1B,
...
MM-1A, MM-1B,
find the maximum clique.
I am currently trying all kinds of bron-kerbosch algorithm variations.
But every time I get a time limit on the testing site. I posted the only code that doesn't have a time limit BUT it has a wrong answer. The code is kind of optimized by not creating a new set every recursion.
Anyways, PLEASE help me. I am a desperate latvian teen programmer. I know this problem can be solved, because many people have solved it on the testing site.
#include <set>
#include <vector>
std::map<int, std::set<int> > NotAdjacent;
unsigned int MaxCliqueSize = 0;
void PrintSet(std::set<int> &s){
for(auto it = s.begin(); it!=s.end(); it++){
printf("%d ",*it);
}
printf("\n");
}
void Check(std::set<int> &clique, std::set<int> &left){
//printf("printing clique: \n");
//PrintSet(clique);
//printf("printing left: \n");
//PrintSet(left);
if(left.empty()){
//PrintSet(clique);
if(clique.size()>MaxCliqueSize){
MaxCliqueSize = clique.size();
}
return;
}
while(left.empty()==false){
std::vector<int> removed;
int v = *left.begin();
left.erase(left.begin());
for(auto it2=NotAdjacent[v].begin();it2!=NotAdjacent[v].end();it2++){
auto findResult = left.find(*it2);
if(findResult!=left.end()){
removed.push_back(*it2);
left.erase(findResult);
}
}
clique.insert(v);
Check(clique, left);
clique.erase(v);
for(unsigned int i=0;i<removed.size();i++){
left.insert(removed[i]);
}
}
}
int main(){
int n, m;
scanf("%d%d",&n,&m);
int a, b;
for(int i=0;i<m;i++){
scanf("%d%d",&a,&b);
NotAdjacent[a].insert(b);
NotAdjacent[b].insert(a);
}
std::set<int> clique, left;
for(int i=1;i<=n;i++){
left.insert(i);
}
Check(clique, left);
printf("%d",MaxCliqueSize);
}
For what it's worth, this code seems to pass 5 tests and I think all the rest exceed either time or memory limits (submitted as C++11). This idea is to find a maximum independent set in the graph complement, for which we readily receive the edges for. The algorithm is what I could understand of the standard greedy one. Perhaps this can give you or others more ideas? I believe there are some improved algorithms for MIS.
#include <iostream>
using namespace std;
#include <map>
#include <set>
#include <vector>
#include <algorithm>
std::map<int, std::set<int> > NotAdjacent;
vector<int> Order;
unsigned int NumConnectedToAll = 0;
unsigned int MaxCliqueSize = 0;
bool sortbyN(int a, int b){
return (NotAdjacent[a].size() > NotAdjacent[b].size());
}
void mis(std::set<int> &g, unsigned int i, unsigned int size){
if (g.empty() || i == Order.size()){
if (size + NumConnectedToAll > MaxCliqueSize)
MaxCliqueSize = size + NumConnectedToAll;
return;
}
if (g.size() + size + NumConnectedToAll <= MaxCliqueSize)
return;
while (i < Order.size() && g.find(Order[i]) == g.end())
i++;
int v = Order[i];
std::set<int> _g;
_g = g;
_g.erase(v);
for (auto elem : NotAdjacent[v])
_g.erase(elem);
mis(_g, i + 1, size + 1);
}
int main(){
int n, m;
scanf("%d%d",&n,&m);
int a, b;
for(int i=0;i<m;i++){
scanf("%d%d",&a,&b);
NotAdjacent[a].insert(b);
NotAdjacent[b].insert(a);
}
std::set<int> g;
Order.reserve(NotAdjacent.size());
for (auto const& imap: NotAdjacent){
Order.push_back(imap.first);
g.insert(imap.first);
}
sort(Order.begin(), Order.end(), sortbyN);
for (int i=1; i<=n; i++)
if (NotAdjacent.find(i) == NotAdjacent.end())
NumConnectedToAll++;
for (unsigned int i=0; i<Order.size(); i++){
mis(g, i, 0);
g.erase(Order[i]);
}
printf ("%d", MaxCliqueSize);
return 0;
}

C++ - Randomly select strings without selecting it more than once

I have a hand full of objects each containing several strings each. Right now its set up as structures each containing a map with keys 1...n, one for each string (map<int,string> strs), this can be changed if a better way exists. I need to randomly access all of these str ings without overlapping and know that i'm done. How can I do this, either with the maps or another data structure? Thanks.
Here's some code for a Fisher-Yates shuffle:
template <class T>
std::vector<T> shuffle(std::vector<T> &vect)
{
std::vector<T> shuffled = vect;
for(int i = shuffled.size()-1; i >= 1; i--) {
int idx = rand() % (i+1);
T tmp = shuffled[idx];
shuffled[idx] = shuffled[i];
shuffled[i] = tmp;
}
return shuffled;
}
This will take in a vector, and return a copy of it in a random order. If you have a vector of strings, you can use it like this (I'm using c++11 here):
int main()
{
srand(time(NULL));
std::vector<std::string> strs = {"foo", "bar", "baz", "stack", "overflow"};
for(auto &str : shuffle(strs)) {
std::cout << str << std::endl;
}
return 0;
}
Of course, if you're lazy, like me, there's always the random_shuffle() function in <algorithm>:
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
int main()
{
std::vector<std::string> strs = {"foo", "bar", "baz", "stack", "overflow"};
std::random_device rd;
std::mt19937 g(rd()); // Use a good random number generaor
std::random_shuffle(strs.begin(), strs.end(), g); // this does the shuffle
for(auto &str : strs) {
std::cout << str << std::endl;
}
return 0;
}
Hope this helps!
A horrible solution, don't do this. Very slow for large candidate vectors, this has n-squared complexity. Shuffling is better, it has linear complexity.
std::vector<int> RandomThing(int number, int min, int max)
{
assert(!"RandomThing" && min < max);
std::vector<int> candidates;
for(int i=min; i<max; i++)
candidates.push_back(i);
std::vector<int> result;
for(int i=0; i<number;)
{
int candidate_index = rand() % candidates.size();
result.push_back(candidates[candidate_index]);
std::vector<int>::iterator it = candidates.begin();
std::advance(it, candidate_index);
candidates.erase(it);
}
return result;
}