Appears K times in an array C++ - c++

So I have an algorithm that is suppose to return the int that appears K times in an array. If more than 1 int appears K times, the higher value should be returned. My following algorithm is not working correctly. In the example below, it returns 1 when it should be returning 5.
#include <iostream>
#include <algorithm>
int appearsKTimes (int size, int inputArray[], int k) {
std::sort(inputArray, inputArray + size);
int i = 1, count = 1;
int element = inputArray[0];
int res = -1;
while (i < size) {
if (element == inputArray[i]) {
count++;
} else {
if (count == k) {
res = element;
}
element = inputArray[i];
count = 1;
}
i++;
}
std::cout << res << std::endl;
return res;
}
int main() {
const int size = 7;
int array[size] = {1, 1, 2, 2, 2, 5, 5};
int occurences = 2;
appearsKTimes(size, array, occurences);
}

if (count == k) {
res = element;
}
std::cout << res << std::endl;
check the count of the last element.
I also think it will be better to count from the end.You need to check the all array all the time if you count from the first element.

Your approach with sorting is good and requires only O(NlogN) time complexity, but consider an another one with hash table as well. It requires O(N) in time and O(N) in space. It is shorter and has only a few extra variables, so there is less chance of making mistake:
1) Compute number frequencies with unordered_map (hash table): O(N)
2) Find the largest number with exactly k occurences: O(N)
int appearsKTimes (int size, int inputArray[], int k) {
unordered_map<int, int> freqs;
for (int i = 0; i < size; i++) {
freqs[inputArray[i]]++;
}
int res = - 1;
for (int i = 0; i < size; i++) {
if (freqs[inputArray[i]] == k)
res = max(res, inputArray[i]);
}
return res;
}

Related

Find the missing numbers in the given array

Implement a function which takes an array of numbers from 1 to 10 and returns the numbers from 1 to 10 which are missing. examples input: [5,2,6] output: [1,3,4,7,8,9,10]
C++ program for the above approach:
#include <bits/stdc++.h>
using namespace std;
// Function to find the missing elements
void printMissingElements(int arr[], int N)
{
// Initialize diff
int diff = arr[0] - 0;
for (int i = 0; i < N; i++) {
// Check if diff and arr[i]-i
// both are equal or not
if (arr[i] - i != diff) {
// Loop for consecutive
// missing elements
while (diff < arr[i] - i) {
cout << i + diff << " ";
diff++;
}
}
}
}
Driver Code
int main()
{
// Given array arr[]
int arr[] = { 5,2,6 };
int N = sizeof(arr) / sizeof(int);
// Function Call
printMissingElements(arr, N);
return 0;
}
How to solve this question for the given input?
First of all "plzz" is not an English world. Second, the question is already there, no need to keep writing in comments "if anyone knows try to help me".
Then learn standard headers: Why should I not #include <bits/stdc++.h>?
Then learn Why is "using namespace std;" considered bad practice?
Then read the text of the problem: "Implement a function which takes an array of numbers from 1 to 10 and returns the numbers from 1 to 10 which are missing. examples input: [5,2,6] output: [1,3,4,7,8,9,10]"
You need to "return the numbers from 1 to 10 which are missing."
I suggest that you really use C++ and get std::vector into your toolbox. Then you can leverage algorithms and std::find is ready for you.
#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>
std::vector<int> missingElements(const std::vector<int> v)
{
std::vector<int> missing;
for (int i = 1; i <= 10; ++i) {
if (find(v.begin(), v.end(), i) == v.end()) {
missing.push_back(i);
}
}
return missing;
}
int main()
{
std::vector<int> arr = { 5, 2, 6 };
std::vector<int> m = missingElements(arr);
copy(m.begin(), m.end(), std::ostream_iterator<int>(std::cout, " "));
std::cout << "\n";
return 0;
}
If you want to do something with lower computational complexity you can have an already filled vector and then mark for removal the elements found. Then it's a good chance to learn the erase–remove idiom:
std::vector<int> missingElements(const std::vector<int> v)
{
std::vector<int> m = { -1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
for (const auto& x: v) {
m[x] = -1;
}
m.erase(remove(m.begin(), m.end(), -1), m.end());
return m;
}
By this approach we are using space to reduce execution time. Here the time complexity is O(N) where N is the no of elements given in the array and space complexity is O(1) i.e 10' .
#include<iostream>
void printMissingElements(int arr[], int n){
// Using 1D dp to solve this
int dp[11] = {0};
for(int i = 0; i < n; i++){
dp[arr[i]] = 1;
}
// Traverse through dp list and check for
// non set indexes
for(int i = 1; i <= 10; i++){
if (dp[i] != 1) std::cout << i << " ";
}
}
int main() {
int arr[] = {5,2,6};
int n = sizeof(arr) / sizeof(int);
printMissingElements(arr, n);
}
void printMissingElements(int arr[], int n,int low, int high)
{
bool range[high - low + 1] = { false };
for (int i = 0; i < n; i++) {
if (low <= arr[i] && arr[i] <= high)
range[arr[i] - low] = true;
}
for (int x = 0; x <= high - low; x++) {
if (range[x] == false)
std:: cout << low + x << " ";
}
}
int main()
{
int arr[] = { 5,2,6,6,6,6,8,10 };
int n = sizeof(arr) / sizeof(arr[0]);
int low = 1, high = 10;
printMissingElements(arr, n, low, high);
return 0;
}
I think this will work:
vector<int> missingnumbers(vector<int> A, int N)
{ vector<int> v;
for(int i=1;i<=10;i++)
v.push_back(i);
sort(A.begin(),A.end());
int j=0;
while(j<v.size()) {
if(binary_search(A.begin(),A.end(),v[j]))
v.erase(v.begin()+j);
else
j++;
}
return v;
}

Is this a wrong approach to find whether array is subarray of another array?

bool isSubset(int arr1[], int m,int arr2[], int n){
set<int> hashset;
for (int i = 0; i < m; i++){
hashset.insert(arr1[i]);
}
for (int i = 0; i < n; i++) {
if (hashset.find(arr2[i]) == hashset.end())
return false;
}
return true;
}
Is this correct method to find whether arr2 is sub array of arr1 or not
because sub array is contiguous part of array but this code is not checking for any order that's why I want to be sure.
Is this correct method to find whether arr2 is sub array of arr1 or not
No, it isn't. Your method doesn't consider the order of elements. It is more of a method to find whether a bunch of numbers (given in arr2) exist in an arr1.
For instance, if int arr1[] = {1, 2, 3} and int arr2[] = {2, 1}, the method you implemented will return true, while it should return false.
Here is how you would do it:
#include <iostream>
bool isSubset(int array[], int m, int subarray[], int n)
{
if (n > m)
return false;
for (int i = 0; i <= m-n; i++) {
int ii = i, j;
for (j = 0; j < n; j++)
if (subarray[j] != array[ii])
break;
else
ii++;
if (j == n)
return true;
}
return false;
}
Then call it like this:
int main()
{
int array[] = {1, 2, 3};
const int m = sizeof(array) / sizeof(*array);
int subarray1[] = {1, 2};
const int n1 = sizeof(subarray1) / sizeof(*subarray1);
int subarray2[] = {2, 1};
const int n2 = sizeof(subarray2) / sizeof(*subarray2);
std::cout << isSubset(array, m, subarray1, n1) << "\n"; // Will print 1
std::cout << isSubset(array, m, subarray2, n1) << "\n"; // Will print 0
}
You understood that the way your code is checking subarray is wrong.
A suggestion-
Use of C language style array in C++ is discouraged. Instead, you should use the appropriate standard container, provided in Containers library. You can use std::array container in place of plain C style array. Below is the sample code to check subarray:
#include <iostream>
#include <array>
#include <algorithm>
int main () {
std::array<int,12> arr1 {9,5,2,5,9,2,4,7,0,4,5,1};
std::array<int,3> arr2 {5,9,2};
bool res = false;
size_t pos = 0;
std::array<int,12>::iterator x;
while ((x = std::find(arr1.begin() + pos, arr1.end(), arr2[0])) != arr1.end()) {
size_t currpos = x - arr1.begin();
if ((arr1.size() - currpos >= arr2.size()) &&
((std::equal(arr1.begin() + currpos, arr1.begin() + currpos + arr2.size(), arr2.begin())))) {
res = true;
break;
}
pos = currpos + 1;
}
if (res) {
std::cout << "arr2 is subarray of arr1" << std::endl;
} else {
std::cout << "arr2 is not subarray of arr1" << std::endl;
}
return 0;
}

Finding two associated indexes where the sum of two elements equals a target value

Background:
Given an array of integers, return indices of the two numbers such that they add up to a specific target.
You may assume that each input would have exactly one solution, and you may not use the same element twice.
Example:
Given nums = [2, 7, 11, 15], target = 9,
Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1].
Question:
I have a list of numbers 1,2,3,4,5. My target value is 8, so I should return indices 2 and 4. My first thought is to write a a double for loop that checks to see if adding two elements from the list will get my target value. Although, when checking to see if there is such a solution, my code returns that there is none.
Here is my code:
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> list;
list.push_back(1);
list.push_back(2);
list.push_back(3);
list.push_back(4);
list.push_back(5);
int target = 8;
string result;
for(int i = 0; i < list.size(); i++) {
for(int j = i+1; j < list.size(); j++) {
if(list[i] + list[j] == target) {
result = "There is a solution";
}
else {
result = "There is no solution";
}
}
}
cout << result << endl;
return 0;
}
Perhaps my approach/thinking is plain wrong. Could anyone provide any hints or suggestions to solving this problem?
Your approach is correct but you are forgetting you are in a loop that continues after finding the solution.
This will get you halfway there. I recommend putting both loops in a function, and returning once you find a match. One thing you could do is return a pair<int,int> from that function or you could simply output the results from within that point in the loop.
bool solutionFound = false;
int i,j;
for(i = 0; i < list.size(); i++)
{
for(j = i+1; j < list.size(); j++)
{
if(list[i] + list[j] == target)
{
solutionFound = true;
}
}
}
Here is what the function approach might look like:
pair<int, int> findSolution(vector<int> list, int target)
{
for (int i = 0; i < list.size(); i++)
{
for (int j = i + 1; j < list.size(); j++)
{
if (list[i] + list[j] == target)
{
return pair<int, int>(i, j);
}
}
}
return pair<int, int>(-1, -1);
}
int main() {
vector<int> list;
list.push_back(1);
list.push_back(2);
list.push_back(3);
list.push_back(4);
list.push_back(5);
int target = 8;
pair<int, int> results = findSolution(list, target);
cout << results.first << " " << results.second << "\n";
return 0;
}
Here's the C++ incorporating Dave's answer for linear execution time and a couple helpful comments:
pair<int, int> findSolution(vector<int> list, int target)
{
unordered_map<int, int> valueToIndex;
for (int i = 0; i < list.size(); i++)
{
int needed = target - list[i];
auto it = valueToIndex.find(needed);
if (it != valueToIndex.end())
{
return pair<int, int>(it->second, i);
}
valueToIndex.emplace(list[i], i);
}
return pair<int, int>(-1, -1);
}
int main()
{
vector<int> list = { 1,2,3,4,5 };
int target = 10;
pair<int, int> results = findSolution(list, target);
cout << results.first << " " << results.second << "\n";
}
You're doing this in n^2 time. Solve it in linear time by hashing each element, and checking each element to see if it's complement wrt. the total you're trying to achieve is in the hash.
E.g., for 1,2,3,4,5, with a target of 8
indx 0, val 1: 7 isn't in the map; H[1] = 0
indx 1, val 2: 6 isn't in the map, H[2] = 1
indx 2, val 3: 5 isn't in the map, H[3] = 2
indx 3, val 4: 4 isn't in the map, H[4] = 3
indx 4, val 5: 3 is in the map. H[3] = 2. Return 2,4
Code, as requested (Ruby)
def get_indices(arr, target)
value_to_index = {}
arr.each_with_index do |val, index|
if value_to_index.has_key?(target - val)
return [value_to_index[target - val], index]
end
value_to_index[val] = index
end
end
get_indices([1,2,3,4,5], 8)
Basically the same as zzxyz's most recent edit but a little quicker and dirtier.
#include <iostream>
#include <vector>
bool FindSolution(const std::vector<int> &list, // const reference. Less copying
int target)
{
for (int i: list) // Range-based for (added in C++11)
{
for (int j: list)
{
if (i + j == target) // i and j are the numbers from the vector.
// no need for indexing
{
return true;
}
}
}
return false;
}
int main()
{
std::vector<int> list{1,2,3,4,5}; // Uniform initialization Added in C++11.
// No need for push-backs of fixed data
if (FindSolution(list, 8))
{
std::cout << "There is a solution\n";
}
else
{
std::cout << "There is no solution\n";
}
return 0;
}

Enumerate subsets with DFS

I want to enumerate all possible subsets of a given array, which should be 2^N in total. Here I use sum to represent all subsets since sums are distinct in this example. I use a auxiliary array called taken to mark if the current item is taken and do a DFS. Here is the code:
void dfs(vector<int>& res, vector<int>& nums, vector<bool>& taken, int sum, int pos) {
for (int i = pos; i < nums.size(); ++i) {
if (!taken[i]) {
taken[i] = true;
res.push_back(nums[i] + sum);
dfs(res, nums, taken, sum + nums[i], pos + 1);
taken[i] = false;
}
}
return;
}
int main() {
vector<int> test = {1, 10, 100, 1000};
vector<bool> t(4, false);
vector<int> res;
dfs(res, test, t, 0, 0);
return 0;
}
But this code does not return 2^n results in result.
I have fixed your code
void dfs(vector<int>& res, vector<int>& nums, int sum, int pos) {
for (int i = pos; i < nums.size(); ++i) {
res.push_back(sum + nums[i]);
dfs(res, nums, sum + nums[i], i + 1); // i + 1 instead of pos + 1
}
return;
}
int main() {
vector<int> test = {1, 2, 3};
vector<int> res;
dfs(res,test,0, 0);
cout << res.size() << endl;
copy(res.begin(), res.end(), ostream_iterator<int>(cout , " "));
cout <<endl;
return 0;
}
And since you do not visit the elements backwards (i.e. already added indexes) you do not have to maintain an array to check for visited.
void enumerate_all_subsets(vector <int> &res, const vector <int> &nums) {
if(nums.empty()) return;
for(auto i = 0ull; i < (1 << nums.size()); ++ i) {
int sum = 0;
for(auto k = 0; k < nums.size(); ++ k)
if((i >> k) & 1)
sum += nums[k];
res.push_back(sum);
}
}
This iterates over a vector of a size up to size 63 (if your unsigned long longs are 64 bit). Any larger vectors should probably be rethought as that would take a while as this is O(2^n), as you noted.
Basically each bit of the unsigned long long i represents a position in nums and if it should be added to the sum or not.

Algorithm to compute mode

I'm trying to devise an algorithm in the form of a function that accepts two parameters, an array and the size of the array. I want it to return the mode of the array and if there are multiple modes, return their average. My strategy was to take the array and first sort it. Then count all the occurrences of a number. while that number is occurring, add one to counter and store that count in an array m. So m is holding all the counts and another array q is holding the last value we were comparing.
For example: is my list is {1, 1, 1, 1, 2, 2, 2}
then i would have m[0] = 4 q[0] = 1
and then m[1] = 3 and q[1] = 2.
so the mode is q[0] = 1;
unfortunately i have had no success thus far. hoping someone could help.
float mode(int x[],int n)
{
//Copy array and sort it
int y[n], temp, k = 0, counter = 0, m[n], q[n];
for(int i = 0; i < n; i++)
y[i] = x[i];
for(int pass = 0; pass < n - 1; pass++)
for(int pos = 0; pos < n; pos++)
if(y[pass] > y[pos]) {
temp = y[pass];
y[pass] = y[pos];
y[pos] = temp;
}
for(int i = 0; i < n;){
for(int j = 0; j < n; j++){
while(y[i] == y[j]) {
counter++;
i++;
}
}
m[k] = counter;
q[k] = y[i];
i--; //i should be 1 less since it is referring to an array subscript
k++;
counter = 0;
}
}
Even though you have some good answers already, I decided to post another. I'm not sure it really adds a lot that's new, but I'm not at all sure it doesn't either. If nothing else, I'm pretty sure it uses more standard headers than any of the other answers. :-)
#include <vector>
#include <algorithm>
#include <unordered_map>
#include <map>
#include <iostream>
#include <utility>
#include <functional>
#include <numeric>
int main() {
std::vector<int> inputs{ 1, 1, 1, 1, 2, 2, 2 };
std::unordered_map<int, size_t> counts;
for (int i : inputs)
++counts[i];
std::multimap<size_t, int, std::greater<size_t> > inv;
for (auto p : counts)
inv.insert(std::make_pair(p.second, p.first));
auto e = inv.upper_bound(inv.begin()->first);
double sum = std::accumulate(inv.begin(),
e,
0.0,
[](double a, std::pair<size_t, int> const &b) {return a + b.second; });
std::cout << sum / std::distance(inv.begin(), e);
}
Compared to #Dietmar's answer, this should be faster if you have a lot of repetition in the numbers, but his will probably be faster if the numbers are mostly unique.
Based on the comment, it seems you need to find the values which occur most often and if there are multiple values occurring the same amount of times, you need to produce the average of these. It seems, this can easily be done by std::sort() following by a traversal finding where values change and keeping a few running counts:
template <int Size>
double mode(int const (&x)[Size]) {
std::vector<int> tmp(x, x + Size);
std::sort(tmp.begin(), tmp.end());
int size(0); // size of the largest set so far
int count(0); // number of largest sets
double sum(0); // sum of largest sets
for (auto it(tmp.begin()); it != tmp.end(); ) {
auto end(std::upper_bound(it, tmp.end(), *it));
if (size == std::distance(it, end)) {
sum += *it;
++count;
}
else if (size < std::distance(it, end)) {
size = std::distance(it, end);
sum = *it;
count = 1;
}
it = end;
}
return sum / count;
}
If you simply wish to count the number of occurences then I suggest you use a std::map or std::unordered_map.
If you're mapping a counter to each distinct value then it's an easy task to count occurences using std::map as each key can only be inserted once. To list the distinct numbers in your list simply iterate over the map.
Here's an example of how you could do it:
#include <cstddef>
#include <map>
#include <algorithm>
#include <iostream>
std::map<int, int> getOccurences(const int arr[], const std::size_t len) {
std::map<int, int> m;
for (std::size_t i = 0; i != len; ++i) {
m[arr[i]]++;
}
return m;
}
int main() {
int list[7]{1, 1, 1, 1, 2, 2, 2};
auto occurences = getOccurences(list, 7);
for (auto e : occurences) {
std::cout << "Number " << e.first << " occurs ";
std::cout << e.second << " times" << std::endl;
}
auto average = std::accumulate(std::begin(list), std::end(list), 0.0) / 7;
std::cout << "Average is " << average << std::endl;
}
Output:
Number 1 occurs 4 times
Number 2 occurs 3 times
Average is 1.42857
Here's a working version of your code. m stores the values in the array and q stores their counts. At the end it runs through all the values to get the maximal count, the sum of the modes, and the number of distinct modes.
float mode(int x[],int n)
{
//Copy array and sort it
int y[n], temp, j = 0, k = 0, m[n], q[n];
for(int i = 0; i < n; i++)
y[i] = x[i];
for(int pass = 0; pass < n - 1; pass++)
for(int pos = 0; pos < n; pos++)
if(y[pass] > y[pos]) {
temp = y[pass];
y[pass] = y[pos];
y[pos] = temp;
}
for(int i = 0; i < n;){
j = i;
while (y[j] == y[i]) {
j++;
}
m[k] = y[i];
q[k] = j - i;
k++;
i = j;
}
int max = 0;
int modes_count = 0;
int modes_sum = 0;
for (int i=0; i < k; i++) {
if (q[i] > max) {
max = q[i];
modes_count = 1;
modes_sum = m[i];
} else if (q[i] == max) {
modes_count += 1;
modes_sum += m[i];
}
}
return modes_sum / modes_count;
}