This question already has answers here:
How to remove all instances of a duplicate from a vector<int> [duplicate]
(6 answers)
Closed 2 years ago.
I am trying to get the sum of unique elements, however I am not meeting the requirements of the given output.
//Prompted Input: [1,2,3,2]
//Expected output: 4
//Explanation: The unique elements are [1,3]
Below is my relevant code. Some things I have tried was to set j to i for the nested loop, however that changed nothing. The next step I took was to take out the first if conditional and have the code do the sum after finding the unique numbers but the output was 10. I'd be grateful if someone could give me a direction of where I'm messing up because I know I am close.
int sumOfUnique(vector<int>& nums) {
int sum = 0;
for(int i = 0; i < nums.size(); i++){
for(int j = 0; j < nums.size(); j++){
if(j == i){
sum += nums[i];
}
if(nums[i] == nums[j]){
break;
}
}
}
return sum;
}
You're close in that you have nested loops, but the content of the loops is not correct. The key is that you need to identify the unique elements, that's not something that your current code does.
Use the inner loop to identify if an element is unique and then after the inner loop add it to the sum if it is. Like this
int sumOfUnique(vector<int>& nums) {
int sum = 0;
for (int i = 0; i < nums.size(); i++) {
// count how many times nums[i] occurs
int count = 0;
for (int j = 0; j < nums.size(); j++)
if (nums[i] == nums[j])
++count;
if (count == 1) // is nums[i] unique?
sum += nums[i]; // add it to the sum if it is
}
return sum;
}
The trick is the extra variable count to work out if a particular number is unique.
You can make this code clearer and more flexible by putting the uniqueness test into it's own function. Like this
bool isUnique(vector<int>& nums, int i) {
// count how many times nums[i] occurs
int count = 0;
for (int j = 0; j < nums.size(); j++)
if (nums[i] == nums[j])
++count;
// return true if it occurs once only
return count == 1;
}
int sumOfUnique(vector<int>& nums) {
int sum = 0;
for (int i = 0; i < nums.size(); i++) {
if (isUnique(nums, i)) // is nums[i] unique?
sum += nums[i]; // add it to the sum if it is
}
return sum;
}
It's good to split code into different functions, with each function solving one part of the puzzle. Now (for instance) you could replace isUnique with a different function and sum values in your vector based on some different criterion.
There are more efficient solutions that this using std::set but I expect that the point of this exercise is to get you practising with loops and algorithms.
You can use std::map to create a frequency counter. After that, iterate through the map and check if a number only occurred once. If that's true, add that number to the result and afterward print out the final result.
int uniqueSum(vector<int> numbers)
{
map<int, int> frequency;
for (auto it = numbers.begin(); it!=numbers.end(); it++)
{
int value = (*it);
if (frequency.find(value) == frequency.end()) {frequency[value] = 1;}
else {frequency[value]++;}
//if value already occur in map then add 1 to its counter,
//else set its counter to 1
}
int sum = 0;
for (auto it = frequency.begin(); it!=frequency.end(); it++)
{
if (it->second == 1) {sum += it->first; }
//if the element appear just once in the vector, add it to sum, else skip it
}
return sum;
}
You can read more about map here: https://www.cplusplus.com/reference/map/map/
And also the find() function: https://www.cplusplus.com/reference/map/map/find/
Use a map to store numbers you have seen, and if they repeat, mark as not-viable.
int sumOfUnique(std::vector<int>& nums)
{
std::map<int, bool> seen;
for (auto i : nums)
{
auto it = seen.find(i);
if (it != seen.end()) // If already exists, set viability to false
{
it->second = false;
}
else { seen.insert({ i, true }); } // Does not exist, is currently viable
}
int sum = 0;
for (auto pair : seen)
{
if (pair.second) // If viable
{
sum += pair.first;
}
}
}
Related
Is anybody there who has a code on how to compare values of two arrays ?
I have two vectors and I am looking for the biggest and equal value of the both list.
Here is the code:
void fractionInLowestTerm(int fNumerator, int fDenominator)
{
//let's get the dividers of fNumerator and fDenominator
std::vector<int> dividerOfNumerator;
std::vector<int> dividerOfDenominator;
for (int i = 1; i <= fNumerator; i++) {
if (fNumerator % i == 0) {
dividerOfNumerator.push_back(i);
}
}
for (int j = 1; fDenominator <= j; j++) {
if (fDenominator % j == 0) {
dividerOfDenominator.push_back(j);
}
}
// let's get the greatest common divider of a and b;
int pgcd = 1;
// I do not know how to compare the values of dividers to get the greatest common value on a and b there is the code I started writing to get that
for (int m = 0; m <= dividerOfNumerator.size() && m <= dividerOfDenominator.size(); m++) {
}
}
If I understand the problem correctly, you want to compare the elements in two arrays for each index and save the greater one into a third array. In this case, just use your favourite max function for each index. For example:
void compare(int* array1, int* array2, int* array3, int size)
{
for (int member = 0; member < size; ++member) {
array3[member] = std::max(array1[member], array2[member]);
}
}
or if you want to compare lists and write into third array that which array has bigger value in that index you can use following code
void compare(int* array1, int* array2, int* array3, int size)
{
for (int member = 0; member < size; ++member) {
if (array1[member] > array2[member]) {
array3[member] = 1;
}
else if (array1[member] < array2[member]) {
array3[member] = 2;
}
else if (array1[member] == array2[member]) {
array3[member] = 0;
}
}
}
Since the vectors containing the divisors are already sorted, you can use the std::set_intersection algorithm like this:
std::vector<int> commonDivisors;
std::set_intersection(dividerOfNumerator.begin(), dividerOfNumerator.end(),
dividerOfDenominator.begin(), dividerOfDenominator.end(),
std::back_inserter(commonDivisors));
int pgcd = commonDivisors.back(); // guaranteed to be non-empty since 1 is always a divisor
Here's a demo.
Hello as you can see on the function name I wanted to write a function which put a function on the lowest term. I wanted to go through the gcd but I saw that it would consumes too much memory so here is what I've done. If it can help any member of the forum.
void fractionInLowestTerm(int fNumerator, int fDenominator){
//let's get on the divider of the number
for (int i = 1; i < fNumerator and i <fDenominator; i++) {
if (fNumerator%i == 0 and fDenominator%i == 0) {
fNumerator /= i;
fDenominator /= i;
i = 1;
}
}
}
I have created a function that creates all the possible solutions for a game that I am creating... Maybe some of you know the bullcow game.
First I created a function that creates a combination of numbers of max four integers and the combination can't have any repeating number in it... like...
'1234' is a solution but not '1223' because the '2' is repeating in the number. In total there is 5040 numbers between '0123' and '9999' that haven't repeating numbers.
Here is my function:
std::vector <std::array<unsigned, 4>> HittaAllaLosningar(){
std::vector <std::array<unsigned, 4>> Losningar;
for (unsigned i = 0; i < 10; i++) {
for (unsigned j = 0; j < 10; j++) {
for (unsigned k = 0; k < 10; k++) {
for (unsigned l = 0; l < 10; l++) {
if (i != j && i != k && i != l && j != k && j != l && k != l) {
Losningar.push_back({i,j,k,l});
}
}
}
}
}
return Losningar;
}
Now let's say I have the number '1234' and that is not the solution I am trying to find, I want to remove the solution '1234' from the array since that isn't a solution... how do I do that? have been trying to find for hours and can't find it. I have tried vector.erase but I get errors about unsigned and stuff... also its worth to mention the guesses are in strings.
What I am trying to do is, to take a string that I get from my program and if it isn't a solution I want to remove it from the vector if it exists in the vector.
Here is the code that creates the guess:
std::string Gissning(){
int random = RandomGen();
int a = 0;
int b = 0;
int c = 0;
int d = 0;
for (unsigned i = random-1; i < random; i++) {
for (unsigned j = 0; j < 4; j++) {
if (j == 0) {
a = v[i][j];
}
if (j == 1) {
b = v[i][j];
}
if (j == 2) {
c = v[i][j];
}
if (j == 3) {
d = v[i][j];
}
}
std::cout << std::endl;
AntalTry++;
}
std::ostringstream test;
test << a << b << c << d;
funka = test.str();
return funka;
}
The randomgen function is just a function so I can get a random number and then I go in the loop so I can take the element of the vector and then I get the integers of the array.
Thank you very much for taking your time to help me, I am very grateful!
You need to find the position of the element to erase.
std::array<unsigned, 4> needle{1, 2, 3, 4};
auto it = std::find(Losningar.begin(), Losningar.end(), needle);
if (it != Losningar.end()) { Losningar.erase(it); }
If you want to remove all the values that match, or you don't like checking against end, you can use std::remove and the two iterator overload of erase. This is known as the "erase-remove" idiom.
std::array<unsigned, 4> needle{1, 2, 3, 4};
Losningar.erase(std::remove(Losningar.begin(), Losningar.end(), needle), Losningar.end());
To erase from a vector you just need to use erase and give it an iterator, like so:
std::vector<std::array<unsigned, 4>> vec;
vec.push_back({1,2,3,4});
vec.push_back({4,3,2,1});
auto it = vec.begin(); //Get an iterator to first elements
it++; //Increment iterator, it now points at second element
it = vec.erase(it); // This erases the {4,3,2,1} array
After you erase the element, it is invalid because the element it was pointing to has been deleted. Ti continue to use the iterator you can take the return value from the erase function, a valid iterator to the next element after the one erased, in this the case end iterator.
It is however not very efficient to remove elements in the middle of a vector, due to how it works internally. If it's not important in what order the different solution are stored, a small trick can simplify and make your code faster. Let's say we have this.
std::vector<std::array<unsigned, 4>> vec;
vec.push_back({1,2,3,4});
vec.push_back({4,3,2,1});
vec.push_back({3,2,1,4});
To remove the middle one we then do
vec[1] = vec.back(); // Replace the value we want to delete
// with the value in the last element of the vector.
vec.pop_back(); //Remove the last element
This is quite simple if you have ready other functions:
using TestNumber = std::array<unsigned, 4>;
struct TestResult {
int bulls;
int cows;
}
// function which is used to calculate bulls and cows for given secred and guess
TestResult TestSecretGuess(const TestNumber& secret,
const TestNumber& guess)
{
// do it your self
… … …
return result;
}
void RemoveNotMatchingSolutions(const TestNumber& guess, TestResult result)
{
auto iter =
std::remove_if(possibleSolutions.begin(),
possibleSolutions.end(),
[&guess, result](const TestNumber& possibility)
{
return result == TestSecretGuess(possibility, guess);
});
possibleSolutions.erase(iter, possibleSolutions.end());
}
Disclaimer: it is possible to improve performance (you do not care about order of elements).
This question already has answers here:
Number of all increasing subsequences in given sequence?
(7 answers)
Closed 8 years ago.
Given an array A of size N I need to count such triplets (i,j,k) such that:
Condition 1 : i < j < k
Condition 2 : A[i] > A[j] > A[k]
I know a O(N^3) solution to do it. Can their be something like O(N) or O(NlogN) solution to do this problem as N can be up to 100000
Example : Let N=4 and array be [4,3,2,1] then answer is 4 as {4,3,2},{4,3,1},{4,2,1} and {3,2,1} are all possible answers
How to find this count for given N and array A?
My Approach :
int n;
cin>>n;
vector<int> A(n);
for(int i=0;i<n;i++){
cin>>A[i];
}
int count=0;
for(int i=0;i<n;i++){
for(int j=i+1;j<n;j++){
for(int k=j+1;k<n;k++){
if(A[i]>A[j] && A[j]>A[k]){
count++;
}
}
}
}
cout<<count<<"\n";
First, sort the array, maintain the index of each element.
class Node{
int index, val;
}
For comparing two nodes, we first need to compare their values. If the values equals, we will compare their index, consider a node is greater if its index is smaller.
Now, process each node in sorted order, we try to add each node's index into a Fenwick tree. So, for each index i, we query the tree for the frequency of this index, which added previously in the tree. This is the number of index that has value greater than value of the current index.
Note for the case elements have equal value, by the sorting mechanism mentioned above, we will add those have greater index to the tree first, thus, doesn't affect the frequency value query from the tree.
Apply similar step to obtains those elements that smaller than i and has index j < i.
For example:
If we have an array
{0(1) ,1(2) , 2(2) ,3(4) , 4(4) ,5(4) ,6(1)} //index(value)
After sort -> {5(4), 4(4), 3(4), 2(2), 1(2), 6(1), 0(1) }
Pseudo code
Node[]data;
sort(data)
Fenwick tree;
int[]less;
int[]more;
for(int i = 0; i < data.length; i++){
less[data[i].index] = tree.query(data[i].index);
tree.add(data[i].index, 1);
}
tree.clear();
for(int i = data.length - 1; i >= 0; i--){
more[data[i].index] = tree.query(data.length) -tree.query(data[i].index);
tree.add(data[i].index, 1);
}
int result = 0;
for(int i = 0; i < data.length; i++)
result += more[i]*less[i];
Time complexity will be O(n logn).
Working Java code (FT is my Fenwick tree)
PrintWriter out;
Scanner in = new Scanner(System.in);
out = new PrintWriter(System.out);
int n = in.nextInt();
Node[] data = new Node[n];
for (int i = 0; i < n; i++) {
data[i] = new Node(i + 1, in.nextInt());
}
FT tree = new FT(n + 2);
Arrays.sort(data, new Comparator<Node>() {
#Override
public int compare(Node o1, Node o2) {
if (o1.val != o2.val) {
return o2.val - o1.val;
}
return o2.index - o1.index;
}
});
int[] less = new int[n];//Store all nodes with greater index and smaller value;
int[] greater = new int[n];//Store all nodes with smaller index and greater value
for (int i = 0; i < n; i++) {
greater[data[i].index - 1] = (int) tree.get(data[i].index);
tree.update(data[i].index, 1);
}
tree = new FT(n + 2);
for (int i = n - 1; i >= 0; i--) {
less[data[i].index - 1] = (int) (tree.get(n) - tree.get(data[i].index));
tree.update(data[i].index, 1);
}
long total = 0;
for (int i = 0; i < n; i++) {
total += less[i] * greater[i];
}
out.println(total);
out.close();
You can do this in O(n*n) pretty easily, you just need to keep track of how many smaller number each element had:
vector<int> smallerNumbers(A.size());
for (int i = A.size() - 2; i >= 0; --i){
for (int j = i + 1; j < A.size(); ++j){
if (A[i] > A[j]){
smallerNumbers[i]++;
count += smallerNumbers[j];
}
}
}
For an O(nklogn) solution see my answer here: https://stackoverflow.com/a/28379003/2642059
Note that is for an increasing sequence and you're asking for a decreasing sequence.
To accomplish that you will need to reverse the ranking created by mapIndex. So simply reverse temp before creating mapIndex by swapping the partial_sort_copy line with this one:
partial_sort_copy(values.cbegin(), values.cend(), temp.rbegin(), temp.rend());
This question already has answers here:
Find a pair of elements from an array whose sum equals a given number
(33 answers)
Closed 8 years ago.
So I'm trying to solve problem of finding two numbers from an array such that they add up to a specific target number.
The simplest way to solve it (it gives TimeLimit Error, because it takes O(n^2) time)
vector<int> res, temp = numbers;
sort(temp.begin(), temp.end());
for (int i = 0; i < numbers.size(); i++)
{
for (int j = i + 1; j < numbers.size(); j++)
{
if (numbers[i] + numbers[j] == target)
{
res.push_back(i + 1);
res.push_back(j + 1);
return res;
}
}
}
Also I've tried to sort array before find and then use two pointers (Now it takes O(n^2 log n) time but still gives me Time Limit Error)
vector<int> twoSum(vector<int> &numbers, int target) {
vector<int> res, temp = numbers;
sort(temp.begin(), temp.end());
int i = 0, j = numbers.size() - 1;
while (i < j)
{
if (temp[i] + temp[j] == target)
{
res.push_back(i);
res.push_back(j);
break;
}
if (temp[i] + temp[j] < target)
i++;
if (temp[i] + temp[j] > target)
j--;
}
for (int i = 0; i < numbers.size(); i++)
{
if (numbers[i] == temp[res[0]])
{
res[0] = i + 1;
break;
}
}
for (int i = 0; i < numbers.size(); i++)
{
if (numbers[i] == temp[res[1]])
{
res[1] = i + 1;
break;
}
}
return res;
}
So I would like to know how it is possible to solve this problem using only O(n) time?
I've heard somthing about hash and map but don't know what are they and how to use them.
The hash table approach is as follows: (using unordered_set in C++11)
Given a target sum S...
For each element x:
Check if S - x exists in the hash table - if so, we have our 2 numbers x and S - x.
Insert x into the hash table.
This runs in expected O(n) time.
Also, your approach is only O(n log n). That's O(n log n) for the sort and O(n) for each of the while loop and the two for loops, giving O(n log n + n) = O(n log n) in total. Well, that's assuming .size() is O(1) - I know it might be O(n) (giving O(n²) total running time), at least for older compilers.
Although I'm not too sure what the last two for loops are doing there - when you break from the while loop, you'll have your 2 numbers.
I'm trying to do a method where I have to delete a number from a vector of integers, and that number is passed as a parameter. The problem that I'm having right now is that when I try to delete the same number in consecutive positions, only one of them is deleted.
For example:
vector = (1, 2, 2, 3, 4, 5) and I want to remove the number "2", the result will be:
vector = (1, 2, 3, 4, 5)
But if the number is not in consecutive positions, the method works fine:
vector = (1, 2, 3, 2, 4, 5) ---> remove "2"
vector = (1, 3, 4, 5)
The code that I have is this:
void deleteNumber(int n, vector<int> &numbers)
{
bool hasEntered = false;
int counter = 0;
vector<int> deletedNumbers;
for(unsigned i = 0; i < numbers.size(); i++)
{
if(numbers[i] != n)
{
counter++;
}
else
{
counter = 0;
int counter2 = 0;
bool deleted = false;
for(unsigned j = 0; j < deletedNumbers.size() && deleted == false; j++) // Check if a number has been deleted before
{
if(deletedNumbers[j] != n)
{
counter2++;
}
else
{
deleted = true;
counter2 = 0;
}
}
if(counter2 == (int) deletedNumbers.size()) // Remove the number if it hasn't been removed
{
deletedNumbers.push_back(n);
for(unsigned k = 0; k<numbers.size(); k++)
{
if(numbers[k] == n)
numbers.erase(numbers.begin()+k);
}
counter2 = 0;
hasEntered = true;
}
}
}
}
I think that the error could be in the condition of the last for, where I finally remove the number.
The counters are used in order to determine if an element has been found or not. And also the method has to check if the item has been removed before.
If you don't understand something, please ask me.
Thanks in advance :)
you could try something like this:
void deleteNumber(int n, vector<int> &numbers)
{
vector<int>numbers_without_n;
for(unsigned i = 0; i < numbers.size(); i++)
if(numbers[i] != n)
numbers_without_n.push_back(numbers[i]);
numbers = numbers_without_n;
}
Your code looks like too complicated, thus it can contain many bugs.
This would delete all instances of n; O(numbers.size()):
void deleteNumber(int n, vector<int> &numbers) {
int i = 0;
for (int j = 0; j < numbers.size(); ++j) {
if (numbers[j] != n) numbers[i++] = numbers[j];
}
numbers.resize(i);
}
This would delete the first instance of n in each run; O(numbers.size()):
void deleteNumber(int n, vector<int> &numbers) {
int i = 0;
for (int j = 0; j < numbers.size();) {
if (numbers[j] == n) {
for (++j; j < numbers.size() && numbers[j] == n; ++j) {
numbers[i++] = numbers[j];
}
} else {
numbers[i++] = numbers[j++];
}
}
numbers.resize(i);
}
This would delete the first instance of n; O(numbers.size()):
void deleteNumber(int n, vector<int> &numbers) {
int i = 0;
for (int j = 0; j < numbers.size(); ++j) {
if (numbers[j] == n) {
for (++j; j < numbers.size(); ++j) {
numbers[i++] = numbers[j];
}
break;
}
numbers[i++] = numbers[j];
}
numbers.resize(i);
}
Pick whichever you need.
Please note that other answers, such as luk32's answer contain simpler code (using more STL) for deleting the first instance of n.
If you want to find and fix the bug in your code, I recommend that you try to find a very short input vector for which it fails, and then single-step through it in a debugger.
You don't need to have a loop inside the loop. The easiest way to handle the delete is to delete one item at a time and realize that this will mean you don't want to increment i when you have deleted an item. The easiest way to cancel the increment of i in the for loop is to decrement it first using --i. So you loop becomes
Check if the item matches the number
If so, delete the item and decrement i
Use std::remove and vector::erase
#include <algorithm>
void deleteNumber(int n, vector<int>& numbers)
{
numbers.erase(std::remove(numbers.begin(), numbers.end(), n), numbers.end());
}
First, I'm not sure what counter and counter2 are used for - if they're just being used to determine if you've iterated to the end of the vector without finding an element, you don't need them.
For the purpose of 'check if a number has been deleted', you just need a single boolean variable at the very top of the method, i.e. not inside the scope of the for loop.
I believe the following:
if(counter2 == (int) deletedNumbers.size()) // Remove the numbers if it hasn't been removed
can be replaced with if (!deleted).
So, here's a 'fixed' version while trying to stay as close to your existing logic as possible based on your code comments. This may not be the most efficient/elegant implementation however, I believe I have seen some other answers that use algorithms from the STL library to achieve the same thing.
void deleteNumber(int n, vector<int> &numbers)
{
bool deleted = false;
for(unsigned i = 0; i < numbers.size(); i++)
{
if (numbers[i] == n) // If we've found an instance of the number we're trying to delete
{
if (!deleted) // Check if an instance has already been deleted
{
numbers.erase(numbers.begin() + i); // Remove the number
deleted = true; // Flag that we have deleted an instance of the number
}
}
}
}
Alternately, instead of using a flag for 'deleted' to prevent deleting numbers after the first instance, you could optimize by just returning after you delete the first instance - that will prevent the rest of the loop from executing.
Ok, since apparently std::vector::erase does exists I would use standard c++ features:
void deleteNumber(int n, vector<int> &numbers) {
auto it = find(std::begin(numbers), std::end(numbers), n);
if(it != numbers.end()) numbers.erase(it);
}
EDIT: Forgot that end() is not a valid argument for erase.