思路
1、定义一个vector v来保存输入的值。
2、定义一个大数组arr[10000]来标记出现过的值(hash散列),作用在于:n值在每运算一次(如n /= 2)之后,都将a[n] = 1;表示该数n已经出过一次了。
3、遍历vector中的值,若arr[v[i]] == 0;表示该数还没出现过,为关键值。
注意
1、大数组一般定义成全局的(main函数外边),防止栈溢出。调用的cmp子函数也定义到外边。
2、关于vectord的使用
定义和初始化:
vector<int> a; //相当于定义了一个长度可变的int类型的一维数组int a[];
a.resize(8); //将变量a的长度resize为8,默认这8个元素都是0.
vector<int> a1(10); //直接定义长度为10的int数组,默认这10个元素值都为0.
vector<int> a2(100, 9);// 把100长度的数组中所有的值都初始化为9.
vector<int> a3[10];//此处是中括号,此处相当是一个于二维int数组,
//即a3[0]~a3[9]中每一个都是vector容器.
排序:
vector<int> v;
sort(v.begin(),v.end(),cmp);//sort函数默认从小到大排,可通过添加参数cmp修改规则
3.此处这种以空间换时间的解法需要记住
4.此处通过添加flag和if()来实现题目要求的空格格式输出.先输出空格,后输出值.
代码 v.1
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
//1.main函数的外边定义一个大数组来标记出现过的值(hash散列),cmp用来给定sort排序规则
int arr[10000];
bool cmp(int a,int b){
return a > b; //从大到小排序规则
}
int main(){
int k,flag = 0; //flag用于后边控制输出格式
cin >> k;
//2.定义vector来存储输入的值,对每个值循环计算,并标记出出现过的值
vector<int> v(k);
for(int i = 0;i < k;i++){
cin >> v[i];
int n = v[i];
while(n != 1){
if(n % 2 != 0)
n = (3 * n + 1);
n = n/2;
arr[n] = 1; //在大数组中标记
}
}
//3.对vector排序,按照格式输出
sort(v.begin(),v.end(),cmp);
for(int i = 0;i < k;i++){
if(arr[v[i]] == 0){
if(flag == 1)cout << " "; //先输出空格,再输出数字,避免了最后的数字后边的空格。
cout << v[i];
flag = 1;
}
}
return 0;
}
代码v.2
优化
1、while里边添加break;减少计算量
2、变量n改在循环外边定义(函数开头),减小空间复杂度
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
//1.main函数的外边定义一个大数组来标记出现过的值(hash散列),cmp用来给定sort排序规则
int arr[10000];
bool cmp(int a,int b){
return a > b; //从大到小排序规则
}
int main(){
int k,n,flag = 0; //flag用于后边控制输出格式
cin >> k;
//2.定义vector来存储输入的值,对每个值循环计算,并标记出出现过的值
vector<int> v(k);
for(int i = 0;i < k;i++){
cin >> v[i];
n = v[i];
while(n != 1){
if(n % 2 != 0)
n = (3 * n + 1);
n = n/2;
if(arr[n] == 1) //出现重复的就不用继续计算了
break;
arr[n] = 1; //在大数组中标记
}
}
//3.对vector排序,按照格式输出
sort(v.begin(),v.end(),cmp);
for(int i = 0;i < k;i++){
if(arr[v[i]] == 0){
if(flag == 1)cout << " "; //先输出空格,再输出数字,避免了最后的数字后边的空格。
cout << v[i];
flag = 1;
}
}
return 0;
}