华为软件岗0408笔试-C++实现
总体感受
第一次参加笔试不太清楚考试不能进行调试,再加上记错考试时间,弱鸡的我表示三道题都有思路,可惜都未能AC,考完用自己的IDE写了三道题的答案,欢迎讨论与指正~
第一题:编码数目
题目:输入N,M,求N+N^2+N^3+...+N^M的结果(取余1000000007),1<N<=65536,1<M<=100000
输入格式:每行输入N M,直到N M均等于0时跳出
输出格式:每行输出对应的结果
思路:考试时采用累乘+累加方法,每步进行求余运算确保不越界,case通过80%,可能是超时吧。后来了解到快速幂的方法,可以将朴素求幂的O(N)时间复杂度降低到O(logN),思路是幂次拆分成2^n的形式,举例:6^13=6^(2^0+2^2+2^3),这样原本需要13次运算可降低到3次。
C++实现:
#include <iostream>
#define MAXVAL 1000000007;
using namespace std;
long long quickPower(int N, int i);
int main(int argc, char const *argv[])
{
int N,M;
cin>>N>>M;
while(N!=0 || M!=0){
long long sum=0;
for(int i=1;i<=M;i++){
sum+=quickPower(N,i);
sum%=MAXVAL;
}
cout<<sum<<endl;
cin>>N>>M;
}
return 0;
}
// 快速幂
long long quickPower(int N, int i){
long long res=1;
long long nn=N, ii=i;
for(;ii!=0;ii/=2){
if(ii%2==1) res=(res*nn)%MAXVAL;
nn=(nn*nn)%MAXVAL;
}
return res;
} 第二题:二进制
题目:允许对二进制数进行两种操作:00->10,10->01,求可能的最大数(两种操作可以进行任意次)输入格式:先一行输出样例数,然后每两行输入二进制长度与二进制数本体,1<=长度<=10000
例如:
2
4
0001
10
1010111000
输出格式:每行输出每个样例的答案
例如:
1101
1111101111
思路:第一种操作是产生新的1,使数变大,第二种操作是右移1、左移0,虽然会暂时使数变小,但是会在高位产生连续0,为第一种操作提供可能。总的来说,第二种操作为第一种操作服务。找规律发现,从左往右遍历长度为n的二进制数,记录第一个0后1的个数为m,那么这些1一定会被第二种操作移动到末尾,然后采用第一种操作对二进制数中的连续0产生最可能多的1,最终答案是(n-m-1)个1 + 1个0 + m个1。
举例:101010011->100001111(第二种操作结果)->111101111(第一种操作结果)
注意:需要考虑二进制数全为1的情况,这时直接输出原二进制数即可(可能是考试时未考虑,case通过0 我太难了o(╥﹏╥)o)
#include <iostream>
using namespace std;
int main(){
int sampleNum, len;
string str;
cin>>sampleNum;
for(int i=0;i<sampleNum;i++){
cin>>len;
cin>>str;
int idx;
// 统计第一次0后的1的个数m
for(idx=0;idx<len;idx++){
if(str[idx]=='0') break;
}
if(idx==len){ // error:全为1的情况,直接输出
cout<<str<<endl;
}
else{ // 不全为1,最大数则由(len-m-1)个1,1个0,m个1组成
int cnt1=0;
for(;idx<len;idx++){
if(str[idx]=='1') cnt1++;
}
for(idx=0;idx<len-cnt1-1;idx++) str[idx]='1';
str[idx]='0';
for(idx++;idx<len;idx++) str[idx]='1';
cout<<str<<endl;
}
}
return 0;
} 第三题:解数独
题目:和leetcode 37题一致,链接:https://leetcode-cn.com/problems/sudoku-solver/ 输入格式:
{5,3,0,0,7,0,0,0,0}
{6,0,0,1,9,5,0,0,0}
{0,9,8,0,0,0,0,6,0}
{8,0,0,0,6,0,0,0,3}
{4,0,0,8,0,3,0,0,1}
{7,0,0,0,2,0,0,0,6}
{0,6,0,0,0,0,2,8,0}
{0,0,0,4,1,9,0,0,5}
{0,0,0,0,8,0,0,7,9}
{6,0,0,1,9,5,0,0,0}
{0,9,8,0,0,0,0,6,0}
{8,0,0,0,6,0,0,0,3}
{4,0,0,8,0,3,0,0,1}
{7,0,0,0,2,0,0,0,6}
{0,6,0,0,0,0,2,8,0}
{0,0,0,4,1,9,0,0,5}
{0,0,0,0,8,0,0,7,9}
输出格式:
{5,3,4,6,7,8,9,1,2}
{6,7,2,1,9,5,3,4,8}
{1,9,8,3,4,2,5,6,7}
{8,5,9,7,6,1,4,2,3}
{4,2,6,8,5,3,7,9,1}
{7,1,3,9,2,4,8,5,6}
{9,6,1,5,3,7,2,8,4}
{2,8,7,4,1,9,6,3,5}
{3,4,5,2,8,6,1,7,9}
{6,7,2,1,9,5,3,4,8}
{1,9,8,3,4,2,5,6,7}
{8,5,9,7,6,1,4,2,3}
{4,2,6,8,5,3,7,9,1}
{7,1,3,9,2,4,8,5,6}
{9,6,1,5,3,7,2,8,4}
{2,8,7,4,1,9,6,3,5}
{3,4,5,2,8,6,1,7,9}
思路:也和力扣的官方题解二——回溯法相似,维护三个数组来记录各行、各列以及各大格的填数情况,同时维护一个储存填数坐标的栈用于回溯。大致思路是遍历扫描数独矩阵,尝试填入空格,成功填入后将该格压入栈;当遭遇无法填入的情况时,则从栈中取出上一次填写的格的坐标,并修改它的值并继续扫描。
明明是刷过的题,可惜前面纠结太久,后面没时间写完了,下次一定要先看一遍所有题的题目然后选熟悉的题先做o(╥﹏╥)o
C++实现:
#include <iostream>
#include <vector>
#include <stack>
using namespace std;
int main(){
// 读取矩阵和初始化
vector<vector<int> > matrix(9,vector<int>(9,0)); // 数独矩阵
vector<int> row(9,0); // 行内元素
vector<int> col(9,0); // 列内元素
vector<int> block(9,0); // 箱内元素
for(int i=0;i<9;i++){
scanf("{%d,%d,%d,%d,%d,%d,%d,%d,%d}",&matrix[i][0],&matrix[i][1],&matrix[i][2],&matrix[i][3],&matrix[i][4],&matrix[i][5],&matrix[i][6],&matrix[i][7],&matrix[i][8]);
getchar(); // 将缓冲区里的回车键取出,使缓冲区为空,下次scanf进入阻塞状态
// 清空缓冲区的几种方法:
// 1、fflush(stdin)
// 2、while (ch=getchar() != '\n' && ch != 'EOF')
}
for(int i=0;i<9;i++){
for(int j=0;j<9;j++){
if(matrix[i][j]!=0){
int k=(i/3)*3+j/3;
int tmp=1<<matrix[i][j];
row[i]|=tmp;
col[j]|=tmp;
block[k]|=tmp;
}
}
}
// 开始尝试
bool step;
int r=0,c=0,preV=0,k,tmp;
stack<vector<int> > s; // 维护填入值的坐标点
while(r<9 && c<9){
step=true;
if(matrix[r][c]==0){
int i;
for(i=preV+1;i<=9;i++){
tmp=1<<i;
k=(r/3)*3+c/3;
if((row[r]&tmp)==0 && (col[c]&tmp)==0 && (block[k]&tmp)==0){ // 可以填入
matrix[r][c]=i;
row[r]|=tmp;
col[c]|=tmp;
block[k]|=tmp;
s.push({r,c});
preV=0;
break; // 填入数字后跳出
}
}
if(i==10){ // 找不到合适的数,回溯
// 包括:取出上一个填入点坐标,还原填入点坐标为0,还原三个元素数组,标记不步进
if(s.empty()){
cout<<"无解"<<endl;
return 0;
}
vector<int> pre=s.top();
s.pop();
r=pre[0];
c=pre[1];
k=(r/3)*3+c/3;
preV=matrix[r][c];
matrix[r][c]=0;
tmp=1<<preV;
// 标记数组复原
row[r]&=(~tmp);
col[c]&=(~tmp);
block[k]&=(~tmp);
// 不步进
step=false;
}
}
if(step){
c++;
if(c==9){
c%=9;
r++;
}
}
cout<<"row="<<r<<", col="<<c<<endl;
// 输出结果
for(int i=0;i<9;i++){
printf("{%d,%d,%d,%d,%d,%d,%d,%d,%d}\n",matrix[i][0],matrix[i][1],matrix[i][2],matrix[i][3],matrix[i][4],matrix[i][5],matrix[i][6],matrix[i][7],matrix[i][8]);
}
cout<<endl;
}
// 输出结果
for(int i=0;i<9;i++){
printf("{%d,%d,%d,%d,%d,%d,%d,%d,%d}\n",matrix[i][0],matrix[i][1],matrix[i][2],matrix[i][3],matrix[i][4],matrix[i][5],matrix[i][6],matrix[i][7],matrix[i][8]);
}
return 0;
}
正浩创新EcoFlow公司福利 742人发布
