文章目录
- L1-027 出租
- 题目描述
- 模拟
- 哈希表+二分查找
L1-027 出租
题目描述
下面是新浪微博上曾经很火的一张图:
一时间网上一片求救声,急问这个怎么破。其实这段代码很简单,index数组就是arr数组的下标,index[0]=2 对应 arr[2]=1,index[1]=0 对应 arr[0]=8,index[2]=3 对应 arr[3]=0,以此类推…… 很容易得到电话号码是18013820100。
本题要求你编写一个程序,为任何一个电话号码生成这段代码 —— 事实上,只要生成最前面两行就可以了,后面内容是不变的。
输入格式:
输入在一行中给出一个由11位数字组成的手机号码。
输出格式:
为输入的号码生成代码的前两行,其中arr中的数字必须按递减顺序给出。
输入样例:
18013820100
输出样例:
int[] arr = new int[]{8,3,2,1,0};
int[] index = new int[]{3,0,4,3,1,0,2,4,3,4,4};
模拟
这段代码的目的是将一个11位的电话号码转换成两个数组:arr
数组和index
数组,其中arr
数组包含电话号码中的不重复数字,且按照递减顺序排列;index
数组中的每个元素表示电话号码中对应位置的数字在arr
数组中的索引。下面是代码的详细注释:
#include<bits/stdc++.h>
using namespace std;
int a[20],b[20],c[20]; // 分别用于存储数字出现的次数,arr数组,index数组
int main()
{
string s; // 用于接收输入的电话号码
cin >> s; // 从标准输入读取电话号码
// 计算每个数字出现的次数
for(int i = 0; i < s.size(); i++)
a[s[i] - '0']++; // '0'到'9'的ASCII码值映射到0到9,增加对应数字出现的次数
int k = 0; // 用于记录arr数组的长度,即电话号码中不重复数字的数量
// 从大到小遍历可能出现的数字,将出现过的数字加入到b数组(即arr数组)
for(int i = 9; i >= 0; i--)
if(a[i] != 0)
b[k++] = i;
// 遍历电话号码的每个数字,找出它在arr数组中的索引,存入c数组(即index数组)
for(int i = 0; i < s.size(); i++)
for(int j = 0; j < k; j++)
if(s[i] - '0' == b[j])
{
c[i] = j; // 将索引存入c数组
break; // 找到索引后跳出内层循环
}
// 输出arr数组
printf("int[] arr = new int[]{");
for(int i = 0; i < k; i++)
if(i != k - 1)
printf("%d,", b[i]); // 对于不是最后一个元素,后面加逗号
else
printf("%d};\n", b[i]); // 最后一个元素后面加"};\n"
// 输出index数组
printf("int[] index = new int[]{");
for(int i = 0; i < 11; i++)
if(i != 11 - 1)
printf("%d,", c[i]); // 对于不是最后一个元素,后面加逗号
else
printf("%d};", c[i]); // 最后一个元素后面加"};"
return 0;
}
这段代码通过三个数组实现了功能:a
数组用于记录每个数字(0到9)在电话号码中出现的次数;b
数组存储了电话号码中出现的不重复数字,按照递减顺序排列,实际上即为所需的arr
数组;c
数组存储了电话号码中每个数字在b
数组(即arr
数组)中的索引位置,即为所需的index
数组。
最终,程序通过遍历电话号码,利用a
数组统计数字出现次数,由此构造b
数组(arr
),再通过与b
数组的匹配来填充c
数组(index
),最后格式化输出这两个数组。
哈希表+二分查找
这段代码的目的是将输入的11位电话号码转换成两个特定格式的数组:一个是arr
数组,包含电话号码中的唯一数字,按照从大到小的顺序排列;另一个是index
数组,表示电话号码中每个数字按arr
数组排序后的索引位置。下面是代码的详细解析:
// 引入必要的库文件
#include<bits/stdc++.h>
using namespace std;
vector<int> res; // 用于存储电话号码每个数字在arr数组中的索引
int main()
{
string s; // 用于存储输入的电话号码
cin >> s; // 读取输入的电话号码
// 使用unordered_set从电话号码中提取唯一的数字
unordered_set<char> num(s.begin(), s.end());
// 将提取出来的唯一数字复制到vector容器n中,方便后续操作
vector<char> n(num.begin(), num.end());
// 对容器n中的数字进行降序排序
sort(n.begin(), n.end(), greater<char>());
// 遍历电话号码的每个数字,找出它在n中的位置索引
for(char i : s)
{
int l = 0, r = s.size() - 1; // 初始化二分搜索的左右指针
while(l < r)
{
int mid = (l + r) >> 1; // 计算中点
if(n[mid] <= i) r = mid; // 如果中点元素小于等于当前元素,调整右指针
else l = mid + 1; // 否则调整左指针
}
res.push_back(l); // 将当前元素在n中的位置索引加入到res中
}
// 输出arr数组
printf("int[] arr = new int[]{");
for(int i = 0; i < n.size(); i++)
{
if(i != n.size() - 1)
printf("%c,", n[i]); // 对于数组的前n-1个元素,在其后添加逗号
else
printf("%c};\n", n[i]); // 对于数组的最后一个元素,在其后添加"};\n"以结束数组声明
}
// 输出index数组
printf("int[] index = new int[]{");
for(int i = 0; i < res.size(); i++)
{
if(i != res.size() - 1)
printf("%d,", res[i]); // 对于数组的前n-1个索引,在其后添加逗号
else
printf("%d};", res[i]); // 对于数组的最后一个索引,在其后添加"};"以结束数组声明
}
return 0;
}
代码的关键是使用unordered_set
来去除重复的数字,以及通过降序排序来确保arr
数组中的数字是从大到小排列的。对于index
数组的生成,则通过对每个数字在排序后的vector
中进行二分查找其索引位置,最后按照指定格式输出这两个数组。