华为8_26机试

华为8.26第一题:位转换:没有任何技巧,纯c++代码
* 题目描述:题目中提示,每个数字的二进制为32bit)
* 1.输入n个无符号整数
* 2.给每个数字增加干扰措施。
* 2.1 干扰1:让每个整数的二进制位置上的数字交换,即(2*i)与(2*i+1)交换,i=0:15。以下讨论说的都是二进制数。
* 2.2 干扰2:假设三个数a,b,c,a(XXXXXXXXXXa2a1)的最后两位弹出a1,a2;a1,a2进入b的头,同时b的最后两位b1b2弹出,此时b变为(a2a1XXXXXXXXXXXX),c同理,变为(b2b1XXXXXXXXXXXX),将c的尾巴c1c2弹入a的头,a变为(c2c1XXXXXXXXXXXXX)。
* 最终效果:(干扰2:再把每个数向右移动两位,溢出的部分依次像下一个整数的最高位移动,末尾的右移两位到第一个数的最高两位)
* a(XXXXXXXXXXXXa2a1)->(c2c1XXXXXXXXXXXXX);
* b(XXXXXXXXXXXXb2b1)->(a2a1XXXXXXXXXXXX);
* c(XXXXXXXXXXXXc2c1)->(b2b1XXXXXXXXXXXX);
* 。。。。。。应该叙述清楚了。倘若只有一个数a,这个应该好分析
* 3.输出每个***扰后的数字(十进制的,同空格隔开)

主要思路:

  1. 按照题目要求来,本题的思路是用unsigned int转二进制,再转字符串做翻转进行相应操作
    后续这种转换,我感觉要直接用移位来,这是c++的优势

小的tricks:我之前也遇到过字符串输入带空格。。。用getline(cin,s)。。。
在这里插入图片描述

#include <iostream>
#include <vector>
#include <string>
#include <unordered_map>
#include <algorithm>

using namespace std;

// 将数转换为32位数的二进制
string zhuanhuan1(unsigned int a)
{
  string temp;
  int t = 0;
  for (int i = 0; i < 32; i++)
  {
    // 转换成二进制,完全按照我们的数学公式来的
    t = a % 2;
    temp.push_back(t + '0'); // 数字转字符
    // 现在比如我们要字符‘1’转换成数字1
    // 字符型常量用''括起来的原因是,它们在计算机中都以各自的ASCII表示。而‘1’的对应编码是49的二进制码,但是我们的数字1,就等于1呀
    // 所以为了由原来的‘1’实际上就是49的二进制变成现在的1对应的二进制1,只好用49-48=1了。但是在ASCII码里‘0’对应的刚好是48的二进制码,
    // 所以我们转换的时候只需要‘1’-‘0’=1;就可以了
    // 而数字的ASCII码是按顺序规定的。所以其它字符要转换成数字都可以用减‘0’来表示
    // 而数字1转字符'1',就加上’0‘就可以了
    // https://www.cnblogs.com/sprayer/p/3163825.html

    a = a / 2; // 向下取整
  }
  reverse(temp.begin(), temp.end());
  return temp;
}

// 将32为二进制的数转换为十进制数

// 干扰措施1
void ganrao1(string &s)
{
  for (int i = 0; i < 16; i++)
  {
    swap(s[i * 2], s[i * 2 + 1]);
  }
}

// 干扰措施2
void ganrao2(string &s, char l1, char l2)
{
  s.pop_back();
  s.pop_back();
  reverse(s.begin(), s.end());
  s.push_back(l1);
  s.push_back(l2);
  reverse(s.begin(), s.end());
}

int main()
{
  // 输入
  unsigned int temp;
  vector<unsigned int> arr;
  while (cin >> temp)
  {
    arr.push_back(temp);
  }
  vector<string> str(arr.size());

  // 转换为二进制并增加干扰1
  for (int i = 0; i < arr.size(); i++)
  {
    str[i] = zhuanhuan1(arr[i]); // unsigend int arr[i]->string str[i]
    //cout << str[i] << endl;
    ganrao1(str[i]); //干扰1
    //cout << str[i] << endl;
  }

  // 施加干扰2
  char f_l1 = str[0][str[0].size() - 1]; // 第一个数的二进制后两位fl1、fl2
  char f_l2 = str[0][str[0].size() - 2];
  char l_l1 = str[str.size() - 1][str[0].size() - 1]; // 最后一个数的二进制后两位ll1、ll2
  char l_l2 = str[str.size() - 1][str[0].size() - 2];
  if(str.size()>1{
    for (int i = 1; i < str.size(); i++)
    {
      char l = str[i][str[i].size() - 1]; // 记录当前数字的最后两位,在干扰里面会pop_back()出去,先保留
      char r = str[i][str[i].size() - 2];
      ganrao2(str[i], f_l1, f_l2);
      //cout << "干扰2" << str[i] << endl;
      f_l1 = l;
      f_l2 = r;
    }
  }
  ganrao2(str[0], l_l1, l_l2); // 第一个数做干扰2处理
  // 转换回十进制的数
  for(int i=0, i<arr.size(); i++){
    arr[i] = zhuanhuan2(str[i]);
    cout << arr[i] << " ";
  }
  return 0;
}
第二题:输入一组矩形,分别给出宽和高,求这些矩形组成的连续最大面积(最大柱状图面积的变形)。

这题算法上leetcode有变形,算法倒是不难。比较费事的是输入格式,输入的是 “[1,2,3],[1,2,3]" 这样的一行字符串,第一个数组是宽,第二个数组是高,用c++费了好大劲一个个字符串处理的,这时候特别想念Python的split.
这题还考了边界处理,包括非法字符,两个数组长度不对等,宽<=0或高<=0的情况。不处理边界只能拿70%,别问我怎么知道的。 😣

主要思路:双指针方法
c++没有split() 方法:根据匹配给定的正则表达式来拆分字符串
难点在于io处理,我是通过string::find("],[")来把输入分割成两个字符串s1和s2,然后分别处理
如何验证字符串是否合法:处理字符串之后根据数字重构一次正确的字符串,相同则合法,否则不合法

关于输入的一个思路:先去掉所有的[和] 再用,作为分隔符划分

// 假设输入:"[1,2,3],[4,5,6]"
while(getline(cin, str)){
	string str2;
	for(auto c:str){
		if(c!='['||c!=']'){
			str2+=c;
		}
	}
	# str2: "1,2,3,4,5,6"
	vector<int> width;
	vector<int> long;
	# 如果str2.size()+1是偶数则长宽不等
	int n = (str2.size()+1)/2;
	int i=0;
	for(auto c:str2){
		if(c!=','){
			if(i<n/2){
				width.push_back(c-'0');
			}
			else{
				length.push_back(c-'0');
			}
		}
	}
	
	// 然后将width,longth输入算法进行处理
} 

恰烂分:

在这里插入图片描述

第三题:猜数字

给定一系列字符串,并告诉你每个字符串中有多少个字符是存在的并在最终位置上,有多少个字符存在,但是位置不对。请根据它们猜出正确的字符串。
示例:字符串,存在并位置对的个数,存在但是位置不对的个数
cloxy 3 0
cxmnu 1 1
kcotd 2 1
apqud 2 0
bldwz 1 1
答案:cloud

主要思路:
回溯+dfs

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>

using namespace std;

int p, n;
string w[101];
int a[101], b[101]; // a[i]代表第i个示例,w剩余未分配的正确位置正确字符
string ans = "";

// dfs(j, c) 状态:word:cloud 的第j个字符是c
// 选择: 选择与字符c匹配或者不匹配

bool dfs(int j, char c){
  for(int i=0; i<n; i++){
    // prune  base link
    if(a[i]<0 || b[i]<0 || a[i]+b[i]>(p-j)){
      return false;
    }
  }
  // 选择
  ans+=c; // 全局变量
  vector<int> st(n,0); // visited, if dfs fails, we need to use st to restore a and b

  int cnt = 0;

  // 遍历所有示例
  for(int i=0; i<n; i++){
    // c is at correct position
    if(c==w[i][j]){
      a[i]--;
      s[t]=1;
      cnt+=a[i];
    }
    else if(w[i].find(c)!=-1){ // c is at wrong position而已
      b[i]--;
      st[i]=2;
      cnt+=b[i];
    }
  }
  // cnt = a[i] + b[i] for all i
  if(j==p-1 && cnt ==0) return true; // end of dfs, check correctness

  for(char d ='a'; d<='z'; d++){ // 继续dfs
    if(ans.find(d)!=-1) continue; // d is already used
    if(dfs(j+1, d)) return true;
  }
  // 撤销选择
  ans.pop_back(); // dfs fails, restore a[i], b[i]
  for(int i=0; i<n; i++){
    if(st[i]==1){
      a[i]++}
    else if(st[i]==2){
      b[i]++;
    }
  }
  return false;

}

void main(){
  cin>>p>>n;
  // p是该字符有p个字母
  // n是输入的示例有多少个
  for(int i =0; i<n; i++){
    cin>>w[i];
    cin>>a[i];
    cin>>b[i];
  }
  for(char c='a'; c<='z'; c++){
    if(dfs(0, c)){
      cout << ans << endl;
      return;
    }
  }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值