leetcode-Contains Duplicate,STL unique,unique_copy等函数的使用

leetcode题目描述:

Given an array of integers, find if the array contains any duplicates. Your function should return true if any value appears at least twice in the array, and it should return false if every element is distinct.

解题思路:

本题要求判断一个数组中是否有重复元素,如果有,返回true,如果没有返回false。

方法一、

从头到尾,一次遍历一旦出现相同的元素,返回true即可。
class Solution {
public:
    bool containsDuplicate(vector<int>& nums) {
        if(nums.size()==1) return true;
        if(nums.size()==0) return false;
        bool flag=false;
        for(vector<int>::iterator iter=nums.begin();iter!=nums.end();iter++)
        {
            for(vector<int>::iterator iter1=iter+1;iter1!=nums.end();iter1++)
            {
                if(*iter==*iter1)
                {
                    flag=true;
                    return flag;
                }
            }
        }
        return flag;
        
    }
};

方法二、

利用STL容器函数unique,去除重复元素,最后判断去除重复元素之后的数组大小是否与最初的数组大小相等,若不同,说明有重复元素存在,返回true,否则返回false。
代码如下:
class Solution {
public:
    bool containsDuplicate(vector<int>& nums) {
        if(nums.size()==1) return false;
        if(nums.size()==0) return false;
        bool flag=true;
        int s=nums.size();
        sort(nums.begin(),nums.end());
        nums.erase(unique(nums.begin(),nums.end()),nums.end());
        int e=nums.size();
        if(s==e)
        flag=false;
        
        return flag;
    }
};

下面我们主要介绍unique函数、以及unique_copy函数:

unique()函数是将重复的元素折叠缩编,使成唯一。
unqiue_copy()函数是将重复的元素折叠缩编,使成唯一,并复制到他处。

这两个函数的剔除字符原理是,看当前字符与他前一个字符是否相同,如果相同就剔除当前字符,如果不同就跳转到下一个字符。所以在求一个字符串的字符集的时候要先把字符串排个序再调用上面两个函数剔除重复字符,获取字符集。
下面看一些代码比较

[cpp]  view plain copy
  1. string str = "zhaohaoyang";  
  2. vector<char> vecch(str.begin(), str.end()); //根据迭代器的起始位置和终止位置来定初始化一个容器  
  3. vector<char>::iterator it = vecch.begin();  
  4. for (; it != vecch.end(); ++it)  
  5. {  
  6.     cout<<*it;  
  7. }  
  8. cout<<endl;  输出:zhaohaoyang  

再加上下面两行:

[cpp]  view plain copy
  1. unique(str.begin(), str.end());  
  2. out<<str<<endl;  //输出的还是原样:zhaohaoyang  
       unique()是剔除重复的没错,可是他是剔除相邻之间字符重复的,str中的字符前后之间是没有重复的,所以unique函数是起不到作用的。

      假如把str换成"acttacct"执行上面的两句代码结果是:actactct,这个结果也是奇怪的。按照意愿应该是把多于的t与多于的c剔掉后只剩下actact了啊。最后两个字符ct是怎么回事呢?

      因为unique()函数并不是真的在源字符串上进行剔除的,原来的字符串经过unique()函数后虽然除掉了相邻之间重复的字符,可是字符串长度是不变的,也就是说所占内存大小没变。

      遇到这个问题通常会这么做str.erase(unique(str.begin(), str.end()), str.end());

unique()函数的返回值是源字符串中去除相邻之间相同字符后剩下的字符串中的最后一个字符的下一个位置,

举例说明:"acttacct"有8个字符,相邻之间重复的有两个,"acttacct"被unique()后的字符串面貌是"actactXX",

X代表的是不确定的字符。unique函数的返回值是一个迭代器类型,指向的是第一个X所处的位置。

STL中的参数区间都是左闭右开的,str.end()返回的迭代器指向第二个X位置的后面一个位置,所以调用str.erase()后就把后两个不确定的字符XX删除掉了。最后得到的就是我们最开始想要的结果了"actact"。


        以上展示还未用的sort()排序函数。现在来看sort()的加入会有什么新的变化。前面说到unique()和unique_copy()函数都是针对相邻之间相同字符的剔除,他们并不会从一个字符串的整体去剔除重复字符,如果不用sort()函数,那么我们想要获取一个字符串所包含的的字符集并不是每一次都能保证正确的(如果字符串中没有相同的字符就是正确的,如果相同的字符都是在相邻位置出现结果也是正确的,但大多数情况下却不是这么回事)。

[cpp]  view plain copy
  1. string str = "zhaohaoyang";  
  2. vector<char> vecch(str.begin(), str.end());  
  3. sort(str.begin(), str.end());  
  4. str.erase(unique(str.begin(), str.end()), str.end());  
  5. cout<<str<<endl;      //输出:aghnoyz  
在第二段代码中两行展示的不能剔除重复字符,现在可以从一个字符串出发剔除重复字符了,可以获取一个字符串的字符集了。关键在于使用了sort()函数对字符串进行排序,排序后的字符串相同字符都会集中出现,所以unique()就能正确发挥功能了。


上面所展示的是把获取的字符集存储在了源字符串变量中,如果遇到要把字符集放置在额外的变量中的情况,就要用到unique_copy()函数了。来看一段代码:

[cpp]  view plain copy
  1. string str = "zhaohaoyang";  
  2. string dststr;  
  3. dststr.resize(str.size());  
  4. sort(str.begin(), str.end());  
  5. dststr.resize(unique_copy(str.begin(), str.end(), dststr.begin()) - dststr.begin());  
  6. cout<<dststr<<endl;   //输出:aghnoyz  
dststr是存储字符集的目标串,str是源字符串变量。dststr在用之前必须要先设置大小,否则到unique_copy()的时候会报内存错误,因为是要存储字符串的字符集,所以dststr设置和源字符串相同的大小是完全可以的,最后再把剩余的位置erase掉就好了。
值得注意的是:
STL中list和vector的排序函数表示不同,如下:
list<int> a.
list.sort();
vector<int> b;
sort(b.begin(),b.end());





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值