I have written this code using vector. Some case has been passed but others show timeout termination error.
The problem statement is:-
You have an identity permutation of N integers as an array initially. An identity permutation of N integers is [1,2,3,...N-1,N]. In this task, you have to perform M operations on the array and report the sum of the elements of the array after each operation.
The ith operation consists of an integer opi.
If the array contains opi, swap the first and last elements in the array.
Else, remove the last element of the array and push opi to the end of the array.
Input Format
The first line contains two space-separated integers N and M.
Then, M lines follow denoting the operations opi.
Constraints :
2<=N,M <= 10^5
1 <= op <= 5*10^5
Output Format
Print M lines, each containing a single integer denoting the answer to each of the M operations.
Sample Input 0
3 2
4
2
Sample Output 0
7
7
Explanation 0
Initially, the array is [1,2,3].
After the 1st operation, the array becomes[1,2,4] as opi = 4, as 4 is not present in the current array, we remove 3 and push 4 to the end of the array and hence, sum=7 .
After 2nd operation the array becomes [4,2,1] as opi = 2, as 2 is present in the current array, we swap 1 and 4 and hence, sum=7.
Here is my code:
#include <bits/stdc++.h>
using namespace std;
int main()
{
long int N,M,op,i,t=0;
vector<long int > g1;
cin>>N>>M;
if(N>=2 && M>=2) {
g1.reserve(N);
for(i = 1;i<=N;i++) {
g1.push_back(i);
}
while(M--) {
cin>>op;
auto it = find(g1.begin(), g1.end(), op);
if(it != (g1.end())) {
t = g1.front();
g1.front() = g1.back();
g1.back() = t;
cout<<accumulate(g1.begin(), g1.end(), 0);
cout<<endl;
}
else {
g1.back() = op;
cout<<accumulate(g1.begin(), g1.end(), 0);
cout<<endl;
}
}
}
return 0;
}
Please Suggest changes.
Looking carefully in question you will find that the operation are made only on the first and last element. So there is no need to involve a whole vector in it much less calculating the sum. we can calculate the whole sum of the elements except first and last by (n+1)(n-2)/2 and then we can manipulate the first and last element in the question. We can also shorten the search by using (1<op<n or op==first element or op == last element).
p.s. I am not sure it will work completely but it certainly is faster
my guess, let take N = 3, op = [4, 2]
N= [1,2,3]
sum = ((N-2) * (N+1)) / 2, it leave first and last element, give the sum of numbers between them.
we need to play with the first and last elements. it's big o(n).
function performOperations(N, op) {
let out = [];
let first = 1, last = N;
let sum = Math.ceil( ((N-2) * (N+1)) / 2);
for(let i =0;i<op.length;i++){
let not_between = !(op[i] >= 2 && op[i] <= N-1);
if( first!= op[i] && last != op[i] && not_between) {
last = op[i];
}else {
let t = first;
first = last;
last = t;
}
out.push(sum + first +last)
}
return out;
}
Related
I am trying to find the number of sub arrays that have a sum equal to k:
int subarraySum(vector<int>& nums, int k)
{
int start, end, curr_sum = 0, count = 0;
start = 0, end = 0;
while (end < (int)nums.size())
{
curr_sum = curr_sum + nums[end];
end++;
while (start < end && curr_sum >= k)
{
if (curr_sum == k)
count++;
curr_sum = curr_sum - nums[start];
start++;
}
}
return count;
}
The above code I have written, works for most cases, but fails for the following:
array = {-1, -1, 1} with k = 0
I have tried to add another while loop to iterate from the start and go up the array until it reaches the end:
int subarraySum(vector<int>& nums, int k)
{
int start, end, curr_sum = 0, count = 0;
start = 0, end = 0;
while (end < (int)nums.size())
{
curr_sum = curr_sum + nums[end];
end++;
while (start < end && curr_sum >= k)
{
if (curr_sum == k)
count++;
curr_sum = curr_sum - nums[start];
start++;
}
}
while (start < end)
{
if (curr_sum == k)
count++;
curr_sum = curr_sum - nums[start];
start++;
}
return count;
}
Why is this not working? I am sliding the window until the last element is reached, which should have found a sum equal to k? How can I solve this issue?
Unfortunately, you did not program a sliding window in the correct way. And a sliding window is not really a solution for this problem. One of your main issues is, that you do not move the start of the window based on the proper conditions. You always sum up and wait until the sum is greater than the search value.
This will not really work. Especially for your example -1, -1, 1. The running sum of this is: -1, -2, -1 and you do not see the 0, although it is there. You may have the idea to write while (start < end && curr_sum != k), but this will also not work, because you handle the start pointer not correctly.
Your approach will lead to the brute force solution that typically takes something like N*N loop operations, where N is the size of the array. This, because we need a double nested loop.
That will of course always work, but maybe very time-consuming, and, in the end, too slow.
Anyway. Let us implement that. We will start from each value in the std::vector and try out all sub arrays starting from the beginning value. We must evaluate all following values in the std::vector, because for example the last value could be a big negative number and bring down the sum again to the search value.
We could implement this for example like the following:
#include <iostream>
#include <vector>
using namespace std;
int subarraySum(vector<int>& numbers, int searchSumValue) {
// Here we will store the result
int resultingCount{};
// Iterate over all values in the array. So, use all different start values
for (std::size_t i{}; i < numbers.size(); ++i) {
// Here we stor the running sum of the elements in the vector
int sum{ numbers[i] };
// Check for trivial case. A one-element sub-array does already match the search value
if (sum == searchSumValue) ++resultingCount;
// Now we build all subarrays beginning with the start value
for (std::size_t k{ i + 1 }; k < numbers.size(); ++k) {
sum += numbers[k];
if (sum == searchSumValue) ++resultingCount;
}
}
return resultingCount;
}
int main() {
vector v{ -1,-1,1 };
std::cout << subarraySum(v, 0);
}
.
But, as said, the above is often too slow for big vectors and there is indeed a better solution available, which is based on a DP (dynamic programming) algorithm.
It uses so-called prefix sums, running sums, based on the running sum before the current evaluated value.
We need to show an example. Let's use a std::vector with 5 values {1,2,3,4,5}. And we want to look subarrays with a sum of 9.
We can “guess” that there are 2 subarrays: {2,3,4} and {4,5} that have a sum of 9.
Let us investigate further
Index 0 1 2 3 4
Value 1 2 3 4 5
We can now add a running sum and see, how much delta we have between the current evaluated element and the left neighbor or over-next neighbor and so on. And if we have a delta that is equal to our search value, then we must have a subarray building this sum.
Running Sum 1 3 6 10 15
Deltas of 2 3 4 5 against next left
Running sum 5 7 9 against next next left
9 12 against next next next left
Example {2,3,4}. If we evaluate the 4 with a running sum of 10, and subtract the search value 9, then we get the previous running sum 1. “1+9=10” all values are there.
Example {4,5}. If we evaluate the 5 with a running sum of 15, and subtract the search value 9, then we get the previous running sum = 6. “6+9=15” all values are there.
We can find all solutions using the same approach.
So, the only thing we need to do, is to subtract the search value from the current running sum and see, if we have this running sum already calculated before.
Like: “Search-Value” + “previously Calculated Sum” = “Current Running Sum”.
Or: “Current Running Sum” – “Search-Value” = “previously Calculated Sum”
Again, we need to do the subtraction and check, if we already calculated such a sum previously.
So, we need to store all previously calculated running sums. And, because such a sum may appear more than one, we need to find occurrences of equal running sums and count them.
It is very hard to digest, and you need to think a while to understand.
With the above wisdom, you can draft the below potential solution.
#include <iostream>
#include <vector>
#include <unordered_map>
int subarraySum(std::vector<int>& numbers, int searchSumValue) {
// Here we will store the result
int resultingSubarrayCount{};
// Here we will stor all running sums and how ofthen their value appeared
std::unordered_map<int, int> countOfRunningSums;
// Continuosly calculating the running sum
int runningSum{};
// And initialize the first value
countOfRunningSums[runningSum] = 1;
// Now iterate over all values in the vector
for (const int n : numbers) {
// Calculate the running sum
runningSum += n;
// Check, if we have the searched value already available
// And add the number of occurences to our resulting number of subarrays
resultingSubarrayCount += countOfRunningSums[runningSum - searchSumValue];
// Store the new running sum. Respectively. Add 1 to the counter, if the running sum was alreadyy existing
countOfRunningSums[runningSum]++;
}
return resultingSubarrayCount;
}
int main() {
std::vector v{ 1,2,3,4,5 };
std::cout << subarraySum(v, 9);
}
There's a problem, which I've to solve in c++. I've written the whole code and it's working in the given test cases but when I'm submitting it, It's saying wrong answer. I can't understand that why is it showing wrong answer.
I request you to tell me an input for the given code, which will give incorrect output so I can modify my code further.
Shrink The Array
You are given an array of positive integers A[] of length L. If A[i] and A[i+1] both are equal replace them by one element with value A[i]+1. Find out the minimum possible length of the array after performing such operation any number of times.
Note:
After each such operation, the length of the array will decrease by one and elements are renumerated accordingly.
Input format:
The first line contains a single integer L, denoting the initial length of the array A.
The second line contains L space integers A[i] − elements of array A[].
Output format:
Print an integer - the minimum possible length you can get after performing the operation described above any number of times.
Example:
Input
7
3 3 4 4 4 3 3
Output
2
Sample test case explanation
3 3 4 4 4 3 3 -> 4 4 4 4 3 3 -> 4 4 4 4 4 -> 5 4 4 4 -> 5 5 4 -> 6 4.
Thus the length of the array is 2.
My code:
#include <bits/stdc++.h>
using namespace std;
int main()
{
bool end = false;
int l;
cin >> l;
int arr[l];
for(int i = 0; i < l; i++){
cin >> arr[i];
}
int len = l, i = 0;
while(i < len - 1){
if(arr[i] == arr[i + 1]){
arr[i] = arr[i] + 1;
if((i + 1) <= (len - 1)){
for(int j = i + 1; j < len - 1; j++){
arr[j] = arr[j + 1];
}
}
len--;
i = 0;
}
else{
i++;
}
}
cout << len;
return 0;
}
THANK YOU
As noted in the comments: Just picking the first two neighbours that have the same value and combining those will lead to suboptimal results.
You will need to investigate which two neighbours you should combine somehow. When you have combined two neighbours you then need to investigate which neighbours to combine on the next level. The number of combinations may become plentiful.
One way to solve this is through recursion.
If you've followed the advice in the comments, you now have all your input data in std::vector<unsigned> A(L).
You can now do std::cout << solve(A) << '\n'; where solve has the signature size_t solve(const std::vector<unsigned>& A) and is described below:
Find the indices of all neighbour pairs in A that has the same values and put the indices in a std::vector<size_t> neighbours. Example: If A contains 2 2 2 3, put 0 and 1 in neighbours.
If no neighbours are found (neighbours.empty() == true), return A.size().
Define a minimum variable and initialize it with A.size() - 1 which is the worst result you know you can get at this point. So, size_t minimum = A.size() - 1;
Loop over all indices stored in neighbours (for(size_t idx : neighbours))
Copy A into a new std::vector<unsigned>. Let's call it cpy.
Increase cpy[idx] by one and remove cpy[idx+1].
Call size_t result = solve(cpy). This is where recursion comes in.
Is result less than minimum? If so assign result to minimum.
Return minimum.
I don't think I ruined the programming exercise by providing one algorithm for solving this. It should still have plenty of things to deal with. Recursion won't be possible with big data etc.
There are 2 i/p array's. They are identical when they have exactly same numbers in it. To make them identical, we can swap their elements. Swapping will have cost. If we are swapping a and b elements then cost = min(a, b).
While making array's identical, cost should be minimum.
If it is not possible to make array identical then print -1.
i/p:
3 6 6 2
2 7 7 3
o/p :
4
Here I have swapped (2,7) and (2,6). So min Cost = 2 + 2 = 4.
Logic :
Make 2 maps which will store frequency of i/p array's elements.
if element "a" in aMap is also present in bMap, then we have to consider number of swapping for a = abs(freq(a) in aMap - freq(a) in bMap)
if frequency of elements is "odd", then not possible to make them identical.
else , add total swaps from both maps and find cost using
cost = smallest element * total swaps
Here is the code
#include<iostream>
#include<algorithm>
#include<map>
using namespace std;
int main()
{
int t;
cin >> t;
while(t--)
{
int size;
long long int cost = 0;
cin >> size;
bool flag = false;
map<long long int, int> aMap;
map<long long int, int> bMap;
// storing frequency of elements of 1st input array in map
for( int i = 0 ; i < size; i++)
{
long long int no;
cin >> no;
aMap[no]++;
}
// storing frequency of elements of 2nd input array in map
for(int i = 0 ; i < size; i++)
{
long long int no;
cin >> no;
bMap[no]++;
}
// fetching smallest element (i.e. 1st element) from both map
long long int firstNo = aMap.begin()->first;
long long int secondNo = bMap.begin()->first;
long long int smallestNo;
// finding smallest element from both maps
if(firstNo < secondNo)
smallestNo = firstNo;
else
smallestNo = secondNo;
map<long long int, int> :: iterator itr;
// trying to find out total number of swaps we have to perform
int totalSwapsFromA = 0;
int totalSwapsFromB = 0;
// trversing a map
for(itr = aMap.begin(); itr != aMap.end(); itr++)
{
// if element "a" in aMap is also present in bMap, then we have to consider
// number of swapping = abs(freq(a) in aMap - freq(a) in bMap)
auto newItr = bMap.find(itr->first);
if(newItr != bMap.end())
{
if(itr->second >= newItr->second)
{
itr->second -= newItr->second;
newItr->second = 0;
}
else
{
newItr->second -= itr->second;
itr->second = 0;
}
}
// if freq is "odd" then, this input is invalid as it can not be swapped
if(itr->second & 1 )
{
flag = true;
break;
}
else
{
// if freq is even, then we need to swap only for freq(a)/ 2 times
itr->second /= 2;
// if swapping element is smallest element then we required 1 less swap
if(itr->first == smallestNo && itr->second != 0)
totalSwapsFromA += itr->second -1;
else
totalSwapsFromA += itr->second;
}
}
// traversing bMap to check whether there any number is present which is
// not in aMap.
if(!flag)
{
for(itr = bMap.begin(); itr != bMap.end(); itr++)
{
auto newItr = aMap.find(itr->first);
if( newItr == aMap.end())
{
// if frew is odd , then i/p is invalid
if(itr->second & 1)
{
flag = true;
break;
}
else
{
itr->second /= 2;
// if swapping element is smallest element then we required 1 less swap
if(itr->first == smallestNo && itr->second != 0)
totalSwapsFromB += itr->second -1;
else
totalSwapsFromB += itr->second;
}
}
}
}
if( !flag )
{
cost = smallestNo * (totalSwapsFromB + totalSwapsFromA);
cout<<"cost "<<cost <<endl;
}
else
cout<<"-1"<<endl;
}
return 0;
}
No error in the above code but giving wrong answer and not getting accepted.
Can anyone improve this code / logic ?
Suppose you have 2 arrays:
A: 1 5 5
B: 1 4 4
We know that we want to move a 5 down and a 4 up, so we have to options: swapping 4 by 5 (with cost min(4, 5) = 4) or using the minimum element to do achive the same result, making 2 swaps:
A: 1 5 5 swap 1 by 4 (cost 1)
B: 1 4 4
________
A: 4 5 5 swap 1 by 5 (cost 1)
B: 1 1 4
________
A: 4 1 5 total cost: 2
B: 5 1 4
So the question we do at every swap is this. Is it better to swap directly or swapping twice using the minimum element as pivot?
In a nutshell, let m be the minimum element in both arrays and you want to swap i for j. The cost of the swap will be
min( min(i,j), 2 * m )
So just find out all the swaps you need to do, apply this formula and sum the results to get your answer.
#user1745866 You can simplify your task of determining the answer -1 by using only variable:
let we have int x=0 and we will just do XOR of all the i/p integers like this:
int x = 0;
for(int i=0;i<n;i++){
cin>>a[i];
x = x^a[i];
}
for(int i=0;i<n;i++){
cin>>b[i];
x = x^b[i];
}
if(x!=0)
cout<<-1;
else{
...do code for remain 2 condition...
}
Now the point is how it will work because , as all the numbers of both array should occurs only even number of times and when we do XOR operation of any number which occured even number of times we will get 0.... otherwise they can't be identical arrays.
Now for 2nd condition(which gives answer 0) you should use multimap so you would be able to directly compare both arrays in O(n) time complexity as if all elements of both arrays are same you can output:0
(Notice: i am suggesting multimap because 1:You would have both array sorted and all elements would be there means also duplicates.
2: because they are sorted, if they consist of same element at same position we can output:0 otherwise you have to proceed further for your 3rd condition or have to swap the elements.)
For reducing the swap cost see Daniel's answer. For finding if the swap is actually possible, please do the following, the swaps are actually only possible if you have an even number of elements in total, so that you can split them out evenly, so if you have 2, 4 or 6 5's you are good, but if you have 1, 3, or 5 5's return -1. It is impossible if your number of duplicates of a number is odd. For actually solving the problem, there is a very simple solution I can think of, through it is a little bit expensive, you just need to make sure that there are the same number of elements on each side so the simple way to do that would be to declare a new array:
int temp[size of original arrays];
//Go through both arrays and store them in temp
Take half of each element, so something like:
int count[max element in array - min element in array];
for(int i = 0; i < temp.size(); i++){
count[temp[i]]++;
}
Take half of each element from temp. When you see an element that matches a element on your count array so whenever you see a 1 decrement the index on the count array by 1, so something like count[1]--; Assuming count starts at 0. If the index is at zero and the element is that one, that means a swap needs to be done, in this case find the next min in the other array and swap them. Albeit a little bit expensive, but it is the simplest way I can think of. So for example in your case:
i/p:
3 6 6 2
2 7 7 3
o/p :
4
We would need to store the min index as 2. Cause that is the smallest one. So we would have an array that looks like the following:
1 1 0 0 1 1
//one two one three zero four zero five 1 six and 1 seven
You would go through the first array, when you see the second six, your array index at 6 would be zero, so you know you need to swap it, you would find the min in the other array, which is 2 and then swap 6 with 2, after wards you can go through the array smoothly. Finally you go through the second array, afterwards when you see the last 7 it will look for the min on the other side swap them...., which is two, note that if you had 3 twos on one side and one two on the other, chances are the three twos will go to the other side, and 2 of them will come back, because we are always swapping the min, so there will always be an even number of ways we can rearrange the elements.
Problem link https://www.codechef.com/JULY20B/problems/CHFNSWPS
here for calculating minimum number of swap.we will having 2 cases
let say an example
l1=[1,2,2]
l2=[1,5,5]
case 1. swap each pair wrt to min(l1,l2)=1
step 1 swapping single 2 of a pair of 2 from l1-> [1,1,2]
[2,5,5] cost is 1
step 2 swapping single 5 of a pair of 5 from l1-> [1,5,2]
[2,1,5] cost is 1
total cost is 2
case 2. swap min of l1 with max of l2(repeat until both list end)
try to think if we sort 1st list in increasing order and other as decreasing order then we can minimize cost.
l1=[1,2,2]
l2=[5,5,1]
Trick is that we only need to store min(l1,l2) in variable say mn. Then remove all common element from both list.
now list became l1=[2,2]
l2=[5,5]
then swap each element from index 0 to len(l1)-1 with jump of 2 like 0,2,4,6..... because each odd neighbour wiil be same as previous number.
after perform swapping cost will be 2 and
l1=[5,2]
l2=[2,5] cost is 2
total cost is 2
Let say an other example
l1=[2,2,5,5]
l2=[3,3,4,4]
after solving wrt to min(l1,l2) total cost will be 2+2+2=6
but cost after sorting list will be swap of ((2,4) and (5,3)) is 2+3=5
so minimum swap to make list identical is min(5,6)=5
//code
l1.sort()
l2.sort(reverse=True)
sums=0
for i in range(len(l1)):
sums+=min(min(l1[i],l2[i]),2*minimum))
print(sums)
#print -1 if u get odd count of a key in total (means sums of count of key in both list)
Found a few different solutions and debugging, and especially interested in below solution which requires only O(n) space, other than store a matrix (M*N). But confused about what is the logical meaning of cur[i]. If anyone have any comments, it will be highly appreciated.
I posted solution and code.
Given two words word1 and word2, find the minimum number of steps required to convert word1 to word2. (each operation is counted as 1 step.)
You have the following 3 operations permitted on a word:
a) Insert a character
b) Delete a character
c) Replace a character
class Solution {
public:
int minDistance(string word1, string word2) {
int m = word1.length(), n = word2.length();
vector<int> cur(m + 1, 0);
for (int i = 1; i <= m; i++)
cur[i] = i;
for (int j = 1; j <= n; j++) {
int pre = cur[0];
cur[0] = j;
for (int i = 1; i <= m; i++) {
int temp = cur[i];
if (word1[i - 1] == word2[j - 1])
cur[i] = pre;
else cur[i] = min(pre + 1, min(cur[i] + 1, cur[i - 1] + 1));
pre = temp;
}
}
return cur[m];
}
};
You can think of cur as being as a mix of the previous line and the current line in the edit distance matrix. For example, think of a 3x3 matrix in the original algorithm. I'll number each position like below:
1 2 3
4 5 6
7 8 9
In the loop, if you are computing the position 6, you only need the values from 2, 3 and 5. In that case, cur will be exactly the values from:
4 5 3
See the 3 in the end? That's because we didn't updated it yet, so it still has a value from the first line. From the previous iteration, we have pre = 2, because it was saved before we computed the value at 5.
Then, the new value for the last cell is the minimum of pre = 2, cur[i-1] = 5 and cur[i] = 3, exactly the values mentioned before.
EDIT: completing the analogy, if in the O(n^2) version you compute min(M[i-1][j-1], M[i][j-1], M[i-1][j]), in this O(n) version you'll compute min(pre, cur[i-1], cur[i]), respectively.
I got this question at an interview and at the end was told there was a more efficient way to do this but have still not been able to figure it out. You are passing into a function an array of integers and an integer for size of array. In the array you have a lot of numbers, some that repeat for example 1,7,4,8,2,6,8,3,7,9,10. You want to take that array and return an array where all the repeated numbers are put at the end of the array so the above array would turn into 1,7,4,8,2,6,3,9,10,8,7. The numbers I used are not important and I could not use a buffer array. I was going to use a BST, but the order of the numbers must be maintained(except for the duplicate numbers). I could not figure out how to use a hash table so I ended up using a double for loop(n^2 horrible I know). How would I do this more efficiently using c++. Not looking for code, just an idea of how to do it better.
In what follows:
arr is the input array;
seen is a hash set of numbers already encountered;
l is the index where the next unique element will be placed;
r is the index of the next element to be considered.
Since you're not looking for code, here is a pseudo-code solution (which happens to be valid Python):
arr = [1,7,4,8,2,6,8,3,7,9,10]
seen = set()
l = 0
r = 0
while True:
# advance `r` to the next not-yet-seen number
while r < len(arr) and arr[r] in seen:
r += 1
if r == len(arr): break
# add the number to the set
seen.add(arr[r])
# swap arr[l] with arr[r]
arr[l], arr[r] = arr[r], arr[l]
# advance `l`
l += 1
print arr
On your test case, this produces
[1, 7, 4, 8, 2, 6, 3, 9, 10, 8, 7]
I would use an additional map, where the key is the integer value from the array and the value is an integer set to 0 in the beginning. Now I would go through the array and increase the values in the map if the key is already in the map.
In the end I would go again through the array. When the integer from the array has a value of one in the map, I would not change anything. When it has a value of 2 or more in the map I would swap the integer from the array with the last one.
This should result in a runtime of O(n*log(n))
The way I would do this would be to create an array twice the size of the original and create a set of integers.
Then Loop through the original array, add each element to the set, if it already exists add it to the 2nd half of the new array, else add it to the first half of the new array.
In the end you would get an array that looks like: (using your example)
1,7,4,8,2,6,3,9,10,-,-,8,7,-,-,-,-,-,-,-,-,-
Then I would loop through the original array again and make each spot equal to the next non-null position (or 0'd or whatever you decided)
That would make the original array turn into your solution...
This ends up being O(n) which is about as efficient as I can think of
Edit: since you can not use another array, when you find a value that is already in the
set you can move every value after it forward one and set the last value equal to the
number you just checked, this would in effect do the same thing but with a lot more operations.
I have been out of touch for a while, but I'd probably start out with something like this and see how it scales with larger input. I know you didn't ask for code but in some cases it's easier to understand than an explanation.
Edit: Sorry I missed the requirement that you cannot use a buffer array.
// returns new vector with dupes a the end
std::vector<int> move_dupes_to_end(std::vector<int> input)
{
std::set<int> counter;
std::vector<int> result;
std::vector<int> repeats;
for (std::vector<int>::iterator i = input.begin(); i < input.end(); i++)
{
if (counter.find(*i) == counter.end())
result.push_back(*i);
else
repeats.push_back(*i);
counter.insert(*i);
}
result.insert(result.end(), repeats.begin(), repeats.end());
return result;
}
#include <algorithm>
T * array = [your array];
size_t size = [array size];
// Complexity:
sort( array, array + size ); // n * log(n) and could be threaded
// (if merge sort)
T * last = unique( array, array + size ); // n, but the elements after the last
// unique element are not defined
Check sort and unique.
void remove_dup(int* data, int count) {
int* L=data; //place to put next unique number
int* R=data+count; //place to place next repeat number
std::unordered_set<int> found(count); //keep track of what's been seen
for(int* cur=data; cur<R; ++cur) { //until we reach repeats
if(found.insert(*cur).second == false) { //if we've seen it
std::swap(*cur,*--R); //put at the beginning of the repeats
} else //or else
std::swap(*cur,*L++); //put it next in the unique list
}
std::reverse(R, data+count); //reverse the repeats to be in origional order
}
http://ideone.com/3choA
Not that I would turn in code this poorly commented. Also note that unordered_set probably uses it's own array internally, bigger than data. (This has been rewritten based on aix's answer, to be much faster)
If you know the bounds on what the integer values are, B, and the size of the integer array, SZ, then you can do something like the following:
Create an array of booleans seen_before with B elements, initialized to 0.
Create a result array result of integers with SZ elements.
Create two integers, one for front_pos = 0, one for back_pos = SZ - 1.
Iterate across the original list:
Set an integer variable val to the value of the current element
If seen_before[val] is set to 1, put the number at result[back_pos] then decrement back_pos
If seen_before[val] is not set to 1, put the number at result[front_pos] then increment front_pos and set seen_before[val] to 1.
Once you finish iterating across the main list, all the unique numbers will be at the front of the list while the duplicate numbers will be at the back. Fun part is that the entire process is done in one pass. Note that this only works if you know the bounds of the values appearing in the original array.
Edit: It was pointed out that there's no bounds on the integers used, so instead of initializing seen_before as an array with B elements, initialize it as a map<int, bool>, then continue as usual. That should get you n*log(n) performance.
This can be done by iterating the array & marking index of the first change.
later on swaping that mark index value with next unique value
& then incrementing that mark index for next swap
Java Implementation:
public static void solve() {
Integer[] arr = new Integer[] { 1, 7, 4, 8, 2, 6, 8, 3, 7, 9, 10 };
final HashSet<Integer> seen = new HashSet<Integer>();
int l = -1;
for (int i = 0; i < arr.length; i++) {
if (seen.contains(arr[i])) {
if (l == -1) {
l = i;
}
continue;
}
if (l > -1) {
final int temp = arr[i];
arr[i] = arr[l];
arr[l] = temp;
l++;
}
seen.add(arr[i]);
}
}
output is 1 7 4 8 2 6 3 9 10 8 7
It's ugly, but it meets the requirements of moving the duplicates to the end in place (no buffer array)
// warning, some light C++11
void dup2end(int* arr, size_t cnt)
{
std::set<int> k;
auto end = arr + cnt-1;
auto max = arr + cnt;
auto curr = arr;
while(curr < max)
{
auto res = k.insert(*curr);
// first time encountered
if(res.second)
{
++curr;
}
else
{
// duplicate:
std::swap(*curr, *end);
--end;
--max;
}
}
}
void move_duplicates_to_end(vector<int> &A) {
if(A.empty()) return;
int i = 0, tail = A.size()-1;
while(i <= tail) {
bool is_first = true; // check of current number is first-shown
for(int k=0; k<i; k++) { // always compare with numbers before A[i]
if(A[k] == A[i]) {
is_first = false;
break;
}
}
if(is_first == true) i++;
else {
int tmp = A[i]; // swap with tail
A[i] = A[tail];
A[tail] = tmp;
tail--;
}
}
If the input array is {1,7,4,8,2,6,8,3,7,9,10}, then the output is {1,7,4,8,2,6,10,3,9,7,8}. Comparing with your answer {1,7,4,8,2,6,3,9,10,8,7}, the first half is the same, while the right half is different, because I swap all duplicates with the tail of the array. As you mentioned, the order of the duplicates can be arbitrary.