目录1、题目描述1.1 方法一:排序1.2 方法二:哈希表1.3 方法三:数组位置交换2、题目升级2.1 方法一:哈希表2.2 方法二:辅助数组2.3 方法三:二分查找1、题目描述
找出数组中重复的数字。在一个长度为 n 的数组 nums
里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。
请找出数组中任意一个重复的数字。
题目示例:
先对数组进行排序
此时从头到尾扫一遍数组就可以了
时间复杂度 O ( l o g 2 n ) O(log_2n) O(log2n)
代码示例:
int repeatNum(vector<int>& v){
if(v.empty()) return -1;
int len = v.size();
sort(v.begin(), v.end());
for(int i = 1; i < len; i++){
if(v[i] == v[i-1]){
return v[i];
}
}
return -1;
}
时间复杂度 O ( n ) O(n) O(n)
、空间复杂度 O ( n ) O(n) O(n)
,提高时间效率是以创建一个 O ( n ) O(n) O(n)
的哈希表为代价的。
代码示例:
int repeatNum(vector<int>& v){
if(v.empty()) return -1;
map<int, int> m;
for(int i = 0; i < v.size(); i++){
if(m[v[i]]) return v[i];
else m[v[i]]++;
}
return -1;
}
(m)
是否等于 i 本身(v[i] == v[v[i]])
(m)
和 第 m
个数字交换时间复杂度为 O ( n ) O(n) O(n)
,空间复杂度为 O ( 1 ) O(1) O(1)
代码示例:
int repeatNum(vector<int>& v){
if(v.empty()) return -1;
for(int i = 0; i < v.size(); ++i){
if(v[i] < 0 || v[i] > v.size()-1) // 数字必须在 0 ~ n-1 之间
return -1;
}
for(int i = 0; i < v.size(); ++i){
while(v[i] != i){
if(v[i] == v[v[i]]) return v[i];
swap(v[i], v[v[i]]);
}
}
return false;
}
长度为 n+1 的数组,所有的数都在 1 ~ n 的范围内,因此数组中至少有一个数字是重复的。找出数组中 任意一个 重复的数字,但 不能修改输入的数组。
题目示例:
方法同上:
int repeatNum(vector<int>& v){
if(v.empty()) return -1;
map<int, int> m;
for(int i = 0; i < v.size(); i++){
if(m[v[i]]) return v[i];
else m[v[i]]++;
}
return -1;
}
时间复杂度为 O ( n ) O(n) O(n)
,空间复杂度为 O ( n ) O(n) O(n)
代码示例:
int repeatNum(vector<int>& v){
int len = v.size();
vector<int> v1(len);
for(int i = 0; i < len; ++i){
if(v1[v[i]]) return v1[v[i]];
else v1[v[i]] = v[i];
}
return -1;
}
将 1 ~ n 的数字从中间的数字 分成两部分,即分成 1 ~ m
和 m+1 ~ n
继续把包含重复数字的区间一分为二,直到找到一个重复的数字
时间复杂度为 O ( n l o g n ) O(nlog_n) O(nlogn),
空间复杂度为 O ( 1 ) O(1) O(1)
代码示例:
int countRange(vector<int>& v, int sz, int start, int end){
if(v.empty()) return 0;
int count = 0;
for(int i = 0; i < sz; ++i){
if(v[i] >= start && v[i] <= end){
++count;
}
}
return count;
}
int getrepeat(vector<int>& v){
if(v.empty()) return -1;
int sz = v.size();
int start = 1, end = sz-1;
while(end >= start){
int mid = start + ((end-start)>>1);
int count = countRange(v, sz, start, mid);
if(end == start){
if(count > 1) return start;
else break;
}
if(count > (mid - start + 1)) end = mid;
else start = mid + 1;
}
return -1;
}
测试代码:
bool duplicate(vector<int>& v, int **res){
if(v.empty()) return false;
for(int i = 0; i < v.size(); ++i){
if(v[i] < 0 || v[i] > v.size()-1)
return false;
}
for(int i = 0; i < v.size(); ++i){
while(v[i] != i){
if(v[i] == v[v[i]]) {
*res = &v[i];
return true;
}
swap(v[i], v[v[i]]);
}
}
return false;
}
int main(){
int arr[] = {2, 3, 5, 4, 3, 2, 6, 7};
vector<int> v(arr, arr+8); // 这种赋值方式不会导致vector自动扩展内部大小
int* res = nullptr;
if(duplicate(v, &res)) cout << *res << endl;
else cout << '0' << endl;
//cout << repeatNum(v) << endl;
return 0;
}
到此这篇关于关于c++数组中重复的数字的文章就介绍到这了,更多相关C++数组中重复数字内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!
注:文章转自微信公众号:Coder梁(ID:Coder_LT)
--结束END--
本文标题: 关于C++数组中重复的数字
本文链接: https://lsjlt.com/news/156191.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
2024-03-01
2024-03-01
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0