I have to eliminate duplicates from a array of characters using pointers and a function.
I can t get it to work correctly:
void del_copy(char *p){
int n = strlen(p);
for (int i = 0; i < n; i++){ // Element that we compare
for (int j = i + 1; j < n;j++){ //We compare p + i element with the rest of the elements
if (*(p + i) == *(p + j)){ //If we find two similar, we eliminate that element by shifting
for (int k = i; k < n; k++)
*(p + k) = *(p + k + 1);
}
}
}
}
After you do a shift the length changes. But your n doesn't take that into account.
Here's a simple algorithm:
let s be the empty set (characters encountered so far)
let result be an empty string
for each character c in the input string (
if c is not in s (
include c in s and
append c to the end of result
)
)
result is the result
For the char type on an ordinary machine with 8-bit byte, you can just use a std::bitset as set s.
Another simple algorithm is to sort the string first, if there is no requirement on preserving order. Then you can just scan it and look for duplicates.
sample to fix
void del_copy(char *p){
char c;
for (int i = 0; c=*(p+i); i++){
char *p2, *p3;
for(p2 = p+i+1, p3 = p2; *p3; ++p3){
if(*p3 != c)
*p2++ = *p3;
}
*p2 = '\0';
}
}
Here's my take at the problem. It basically uses a lookup table to check if the character has been seen before but is templated. You could use any kind of value_type.
#include <algorithm>
#include <unordered_map>
template <typename Container>
Container unique_all(Container const& c) {
Container out;
::std::unordered_map<typename Container::value_type,::std::size_t> lookup;
::std::copy_if(c.begin(), c.end(),
::std::back_inserter(out),
[&](typename Container::value_type ch) {return !lookup[ch]++;});
return out;
}
You can call it like this:
unique_all(::std::string("hello dear world"))
I have managed to fix my own code also. Thank you everyone for support.
I had to change the if loop for a while loop and to decrement de lenght #ScottMcP-MVP.
void del_copy(char *p){
int n = strlen(p);
for (int i = 0; i < n-1; i++){ // Element that we compare
for (int j = i + 1; j < n;j++){ //We compare p + i element with the rest of the elements
while(*(p + i) == *(p + j)){ //If we find two similar, we eliminate that element by shifting
for (int k = j; k < n; k++)
*(p + k) = *(p + k + 1);
n--; //decrement n because the lenght if smaller now
}
}
}
}
Related
I have this problem I'm curious about where I have an Array and I need to compute the Sum of this function:
Arr[L] + (Arr[L] ^ Arr[L+1]) + ... + (Arr[L] ^ Arr[L+1] ^ ... ^ Arr[R])
Example:
If the Array given was: [1, 2, 3, 5] and I asked what's the sum on the range [L = 1, R = 3] (assuming 1-based Index), then it'd be:
Sum = 1 + (1 ^ 2) + (1 ^ 2 ^ 3) = 4
In this problem, the Array, the size of the Array, and the Ranges are given. My approach for this is too slow.
There's also a variable called Q which indicates the number of Queries that would process each [L, R].
What I have:
I XOR'ed each element and then summed it to a variable within the range of [L, R]. Is there any faster way to compute this if the elements in the Array are suppose... 1e18 or 1e26 larger?
#include <iostream>
#include <array>
int main (int argc, const char** argv)
{
long long int N, L, R;
std::cin >> N;
long long int Arr[N];
for (long long int i = 0; i < N; i++)
{
std::cin >> Arr[i];
}
std::cin >> L >> R;
long long int Summation = 0, Answer = 0;
for (long long int i = L; i <= R; i++)
{
Answer = Answer ^ Arr[i - 1];
Summation += Answer;
}
std::cout << Summation << '\n';
return 0;
}
There are two loops in your code:
for (long long int i = 0; i < N; i++)
{
std::cin >> Arr[i];
}
long long int Summation = 0, Answer = 0;
for (long long int i = L; i <= R; i++)
{
Answer = Answer ^ Arr[i - 1];
Summation += Answer;
}
The second loop is smaller, and only does two operations (^= and +). These are native CPU instructions; this will be memory bound on the sequential access of Arr[]. You can't speed this up. You need all elements, and it doesn't get faster than a single sequential scan. The CPU prefetcher will hit maximum memory bandwidth.
However, the killer is the first loop. Parsing digits takes many, many more operations, and the range is even larger.
Disclaimer : NOT A FASTER SOLUTION !
Changing a bit the subject by making L and R valid indices of an integer matrix ( range [0, size) ), the following function is working for me:
size_t xor_rec(size_t* array, size_t size, size_t l, size_t r) {
if (l < 0 || r >= size || l > r) {
return 0; // error control
}
if (r > l + 1) {
size_t prev_to_prev_sum = xor_rec(array, size, l, r - 2);
size_t prev_sum = xor_rec(array, size, l, r - 1);
return prev_sum + ((prev_sum - prev_to_prev_sum) ^ array[r]);
}
if (r == l + 1) {
return array[r - 1] + (array[r - 1] ^ array[r]);
}
if (r == l) {
return array[r];
}
return 0;
}
Edit: changed int for size_t.
If indices are 0 based. That is L=0 implies the first element: Arr[0] is the first element in the array, then it's simply this:
int sum = 0;
int prev = 0;
for (int i = L; i <= R; i++)
{
int current = (prev ^ Arr[i]);
sum += current;
prev = current;
}
If it's 1 based, where L=1 is really Arr[0], then it's a quick adjustment:
int sum = 0;
int prev = 0;
for (int i = L; i <= R; i++)
{
int current = (prev ^ Arr[i-1]);
sum += current;
prev = current;
}
I know that there are many implementations of merge sort but this is one which I have read in the book "Introduction to algorithms". The following code is an implementation of merge sort which is not working correctly:
#include <iostream>
using namespace std;
void merge(int*a, int p, int q, int r) { //function to merge two arrays
int n1 = (q - p); // size of first sub array
int n2 = (r - q); // size of second subarray
int c[n1], d[n2];
for (int i = 0; i <= n1; i++) {
c[i] = a[p + i];
}
for (int j = 0; j <= n2; j++) {
d[j] = a[q + j];
}
int i = 0, j = 0;
for (int k = p; k < r; k++) { // merging two arrays in ascending order
if (c[i] <= d[j]) {
a[k++] = c[i++];
} else {
a[k++] = d[j++];
}
}
}
void merge_sort(int*a, int s, int e) {
if (s < e) {
int mid = (s + e) / 2;
merge_sort(a, s, mid);
merge_sort(a, mid + 1, e);
merge(a, s, mid, e);
}
}
int main() {
int a[7] { 10, 2, 6, 8, 9, 10, 15 };
merge_sort(a, 0, 6);
for (auto i : a)
cout << i << endl;
}
This code is not working correctly. What's wrong in this code? How can it be fixed?
First of all you should be correctly set for the size of the array.
void merge(int*a, int p, int q, int r) { //function to merge two arrays
/* If i am not wrong , p is the starting index of the first sub array
q is the ending index of it also q+1 is the starting index of second
sub array and r is the end of it */
/* size of the sub array would be (q-p+1) think about it*/
int n1 = (q - p); // size of first sub array
/* This is right n2 = (r-(q+1)+1)*/
int n2 = (r - q); // size of second subarray
int c[n1], d[n2];
for (int i = 0; i < n1; i++) {
c[i] = a[p + i];
}
for (int j = 0; j < n2; j++) {
d[j] = a[q + 1 + j];
}
.
.
.
}
Now , after this you have copies the both arrays in locally defined arrays. Until this, it is correct .
Now the main part is merging of the two arrays which you are doing in the for loop. You are just comparing the ith element of first sub array with jth element of the second, but what you are missing here is that there may be a time when you have updated all the values of the first( or second) sub array in the main array but still some elements are remaining int the second ( first) one.
For example, take these two subarrays
sub1={2,3,4,5};
sub2={7,8,9,10};
in this case you should break from the loop as soon as you have traversed either of the array completely and copy the rest of the elements of the other array in the same order.
Also in the for loop you increasing k two times in a loop , one in the for statement and another while updating a value, Check that too.
Hope this may solve the problem.
There are couple of things gone wrong in the implementation of your logic. I have indicated them clearly below:
void merge(int*a,int p,int q,int r){ //function to merge two arrays
int n1= (q-p); // size of first sub array
int n2= (r-q); // size of second subarray
int c[n1+1],d[n2]; //you need to add 1 otherwise you will lose out elements
for(int i=0;i<=n1;i++){
c[i]=a[p+i];
}
for(int j=0;j<n2;j++){
d[j]=a[q+j+1];//This is to ensure that the second array starts after the mid element
}
int i=0,j=0;
int k;
for( k=p;k<=r;k++){ // merging two arrays in ascending order
if( i<=n1 && j<n2 ){//you need to check the bounds else may get unexpected results
if( c[i] <= d[j] )
a[k] = c[i++];
else
a[k] = d[j++];
}else if( i<=n1 ){
a[k] = c[i++];
}else{
a[k] = d[j++];
}
}
}
A zero-indexed array A consisting of N different integers is given. The array contains integers in the range [1..(N + 1)], which means that exactly one element is missing.
Your goal is to find that missing element.
Write a function:
int solution(int A[], int N);
that, given a zero-indexed array A, returns the value of the missing element.
For example, given array A such that:
A[0] = 2 A[1] = 3 A[2] = 1 A[3] = 5
the function should return 4, as it is the missing element.
Assume that:
N is an integer within the range [0..100,000];
the elements of A are all distinct;
each element of array A is an integer within the range [1..(N + 1)].
Complexity:
expected worst-case time complexity is O(N);
expected worst-case space complexity is O(1), beyond input storage (not counting the storage required for input arguments).
It doesn't work for a case that there are two elements
int solution(vector<int> &A) {
sort(A.begin(), A.end());
int missingIndex = 0;
for (int i = 0; i < A.size(); i++)
{
if ( i != A[i]-1)
{
missingIndex = i+1;
}
}
return missingIndex;
}
Since your array is zero-indexed and the numbers are from 1 to N+1, the statement should be:
if ( i != A[i]-1)
Also, you should immediately break out from the for loop after updating the missingIndex because all entries beyond the missing element shall have (i != A[i]-1)
Moreover because of sorting your solution is O(NlogN) and not O(N).
Instead you can sum all the elements in the array (using unsigned long long int) and check its difference from N(N+1)/2
You can use the simple math formula for an arithmetic progression to get the sum of all numbers from 1 to N+1. Then iterate over all the given numbers and calculate that sum. The missing element will be the difference between the two sums.
int solution(std::vector<int> &a) {
uint64_t sum = (a.size() +1 ) * (a.size() + 2) / 2;
uint64_t actual = 0;
for(int element : a) {
actual += element;
}
return static_cast<int>(sum - actual);
}
Use all the power of STL:
#include <algorithm>
#include <functional>
int solution(vector<int> &A) {
return std::accumulate(A.begin(), A.end(), (A.size()+1) * (A.size()+2) / 2, std::minus<int>());
}
This solution uses the sign of the values as a flag. It needs at worst two pass over the elements. The N(N+1)/2 solution needs exactly one pass.
int solution(vector<int> &a) {
int n = (int)a.size();
for(auto k : a)
{
int i = abs(k) - 1;
if (i != n)
a[i] = -a[i];
}
for (int i = 0; i < n; ++i)
if (a[i]>0)
return i+1;
return n+1;
}
I solved it this way and thought of posting it here for my own reference for future and for others :)
#include <cstdint>
#include <numeric>
int solution(vector<int> &A) {
uint64_t sumAll = (A.size() + 1) * (A.size() + 2) / 2;
uint64_t sumA = std::accumulate(A.begin(), A.end(), 0);
return sumAll- sumA;
}
I solve it with this solution maybe there is something better but I test it with different values and find it work fine while the other solutions gives me strange results.
as example:
std::vector<int> A = { 12,13,11,14,16 };
std::vector<int> A2 = { 112,113,111,114,116 };
int Solution(std::vector<int> &A)
{
int temp;
for (int i = 0; i < A.size(); ++i)
{
for (int j = i+1;j< A.size();++j )
{
if (A[i] > A[j])
{
temp = A[i];
A[i] = A[j];
A[j] = temp;
}
}
}
for (int i = 0; i < A.size()-1;++i)
{
if ((A[i] + 1 != A[i + 1]))
{
return (A[i] + 1);
}
if(i+1 == A.size() - 1)
return (A[i+1] + 1);
}}
Now Everything fine but if I use the array above with the methods below, I will get wrong values excepts with small numbers <10;
std::vector<int> A = { 12,13,11,14,16 };
int Solution_2(std::vector<int> &A)
{
unsigned int n = A.size() + 1;
long long int estimated = n * (n + 1) / 2;
long long int total = 0;
for (unsigned int i = 0; i < n - 1; i++) total += A[i];
return estimated - total;
}
I will get this result -45.
or this one also the same result if I use array A :
std::vector<int> A = { 12,13,11,14,16 };
int Solution_3(std::vector<int> &A)
{
uint64_t sumAll = (A.size() + 1) * (A.size() + 2) / 2;
uint64_t sumA = std::accumulate(A.begin(), A.end(), 0);
return sumAll - sumA;
}
Hope Someone explains why this happens.
I'm in the process of trying to learn how to do things in C++, and one of the aspects with which I'm grappling is how to efficiently implement dynamically allocated multidimensional arrays.
For example, say I have an existing function:
void myfunc(int *lambda, int *D, int *tau, int r[*tau][*D])
{
int i, j, k, newj, leftovers;
r[0][0] = *lambda;
j = 0; // j indexes the columns; start with zero
for(i = 1; i < *tau; i++){ // i indexes the rows
leftovers = *lambda;
for(k = 0; k < j; k++){
r[i][k] = r[i - 1][k]; // copy prior to j
leftovers = leftovers - r[i][k];
}
r[i][j] = r[i - 1][j] - 1; // decrement
r[i][j+1] = leftovers - r[i][j]; // initialize to the right of j
if(j == *D - 2){ // second to last column
for(k = 0; k <= j; k++){ if(r[i][k] != 0){ newj = k; } }
j = newj; // can't think of a better way to do this
}else{
j++; // increment j
}
} // next row please
}
From what I've read, it seems a common recommendation is to use std::vector for this purpose. Would anyone care to offer some advice or code snippet on how to implement the r matrix above using the std::vector equivalent?
I would have thought this is a fairly common situation, but interestingly, google turned up fewer than 50 hits for "C99 into C++".
Thank you!
Ben
I think this would be about the most straightforward conversion:
void myfunc(int *lambda, std::vector<std::vector<int> > &r)
{
int i, j, k, newj, leftovers;
int tau = r.size();
r[0][0] = *lambda;
j = 0; // j indexes the columns; start with zero
for(i = 1; i < tau; i++){ // i indexes the rows
int D = r[i].size();
leftovers = *lambda;
for(k = 0; k < j; k++){
r[i][k] = r[i - 1][k]; // copy prior to j
leftovers = leftovers - r[i][k];
}
r[i][j] = r[i - 1][j] - 1; // decrement
r[i][j+1] = leftovers - r[i][j]; // initialize to the right of j
if(j == D - 2){ // second to last column
for(k = 0; k <= j; k++){ if(r[i][k] != 0){ newj = k; } }
j = newj; // can't think of a better way to do this
}else{
j++; // increment j
}
} // next row please
}
You have numerous options.
The quick change:
void myfunc(const int& lambda, const size_t& D, const size_t& tau, int* const* const r) {
...
Using a vector (which will not enforce matching sizes at compilation):
void myfunc(const int& lambda, std::vector<std::vector<int>>& r) {
const size_t tau(r.size()); // no need to pass
const size_t D(r.front().size()); // no need to pass
...
Or using std::array for static sizes:
enum { tau = 5, D = 5 };
void myfunc(const int& lambda, std::array<std::array<int,D>,tau>& r) {
...
Or using template parameters for fixed sizes:
template < size_t tau, size_t D >
void myfunc(const int& lambda, std::array<std::array<int,D>,tau>& r) {
...
or just:
template < size_t tau, size_t D >
void myfunc(const int& lambda, int r[D][tau]) {
...
Note that you can also combine static and dynamic sized arrays as needed in C++.
Finally, Multi Arrays are here to help you: http://www.boost.org/doc/libs/1_53_0/libs/multi_array/doc/user.html
I would change all r[x][y] to R(x,y) and use
int * r;
#define R(x,y) r[ (x) * (*D) + (y) ]
Or maybe change *D to *tau, I can never keep those straight.
I have an unsorted array. I have numerous queries in which I give a range (expressed as two array indexes) and then the maximum value from that range (that is, from the specified slice of the array) has to be returned.
For example:
array[]={23,17,9,45,78,2,4,6,90,1};
query(both inclusive): 2 6
answer: 78
Which algorithm or data structure do I construct to quickly retrieve maximum value from any range. (There are a lot of queries)
EDIT:
I am using C++
I think that some preprocessing is allowed. It is Range Minimum Query problem (maximum here).
Good review of this problem at TopCoder.
Suitable data structures: Segment tree and Sqrt-decomposition:
#include <cstdio>
#include <iostream>
#include <algorithm>
#define N int(3e4)
using namespace std;
int act[N], len, sz, res[N];
int answer(int l, int r) {
int ret = -1, i;
for (i = l; i % sz && i <= r; i++)
ret = max(ret, act[i]);
for (; i + sz <= r + 1; i += sz)
ret = max(ret, res[i / sz]);
for (; i <= r; i++)
ret = max(ret, act[i]);
return ret;
}
int main() {
int i, m;
cin >> m;
for (i = 0; ; i++) {
cin >> act[i];
if (act[i] == -1)
break;
}
len = i;
for (sz = 1; sz * sz < len; sz++);
for (int j = i + 1; j < sz * sz; j++)
act[j] = -1;
for (int i = 0; i < sz * sz; i++)
res[i / sz] = max(res[i / sz], act[i]);
for (int i = 0; i + m <= len; i++)
cout << answer(i, i + m - 1) << endl;
return 0;
}
mergesort n get the last index value of range as will me max.
array[]={23,17,9,45,78,2,4,6,90,1};
query(both inclusive): 2 6
mergesort return 6th index var (index = 1 .. n)
answer: 78
Let say this is your array array[]={23,17,9,45,78,2,4,6,90,1};
If your array is not that big, I would offer you preprocess the array and get another array like that:
{0,0} = 23; //between arr[0] and arr[0]
{0,1} = 23;
{0,2} = 23;
{0,3} = 45;
{9,9} = 1;
So your new array is going to be newArr = {23,23,23,45,....., 1}
You can find search in O(1), for example, max between 4-5 is newArr[4*array.length+5)-1];
In total, for n queries you will have O(n).
The space is if you have 10000(10^4) integer, then your newArr = 10^8 * 4B = 400MB, so if you have more than 10000 int, then this wouldnt work
EDIT: I thought of something but it is same as algorithm in Topcoder that MBo mentions.