First the direct answers to your questions, but read on after that:
I want know if I need to free the heap memory
Yes, you should.
how to free the heap memory?
delete [] counter;
Note that the [] is essential as counter is a dynamic array. For non-array memory allocated with new, the [] should be omitted (see cppreference.com).
Issues in your code
- if(int i>1)is not valid C++ syntax. It should just be- if(i>1)
 
- counteris not initialised, so the outcome is not reliable.
 
- The first loop does not count occurrences of values but of indices, so (when the previous issues are fixed) the returned value will always be - false.
 
- If all of the above is fixed, this function can only deal with values that are in the range {0, n-1}, as other values are not valid indices of the - counterarray. Use a- setinstead. This also makes the question on memory management irrelevant, as the set will be destroyed when the function exits.
 
Proposed solution
Once the decision is taken to use a set, things become a lot easier. The set constructor can be given a range (of the nums vector) and once that set is contructed, it suffices to compare its size with that of the vector:
#include <vector>
#include <set>
using namespace std;
bool containsDuplicate(vector<int>& nums) {
    set<int> uniques(nums.begin(), nums.end());
    return uniques.size() < nums.size();
}