xiyou2023年3G一面题解

2024-03-16 08:50
文章标签 题解 3g 一面 xiyou2023

本文主要是介绍xiyou2023年3G一面题解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、简单说下 intshort intfloatdoublelong intlong long int 在 64 位机申请内存的大小。

64(左)与32位(右)的情况:实践出真知

#include <stdio.h>
int main(){printf("%d\n",sizeof(char));	 		//1	   1printf("%d\n",sizeof(short int));		//2	   2printf("%d\n",sizeof(int));				//4	   4printf("%d\n",sizeof(long int));		//4	   4printf("%d\n",sizeof(long long int));	//8	   8printf("%d\n",sizeof(float));			//4	   4printf("%d\n",sizeof(double));			//8	   8printf("%d\n",sizeof(long double));		//16   12return 0;
}

可见除了long double外其余变量在64位与32位所占字节数时相同的

另有测试得出加unsigned对所占字节数无改变 而任意指针类型在64位下占8个,32位下占4个

二、使用 c 语言完成五种交换值的方式。

  1. 最常用的中间变量交换法

    • 常规版

      int tep=a;
      a=b;
      b=tep;
      
    • 封装函数的指针进阶版

      void swap(int *a,int *b){int tep=*a;*a=*b;*b=tep;
      }
      
    • 宏替换无实际意义版

      #define swap(a,b) do{int tep=a;a=b;b=tep;}while(0)
      //加do-while语句是为了防止与其他语句产生关联性
      
  2. 数学法

    • 形式一

      a=a+b;
      b=a-b;
      a=a-b;
      
    • 形式二

      a=a*b;
      b=a/b;
      a=a/b;
      
  3. 位运算

    a=a^b;
    b=a^b;
    a=a^b;
    
  4. 利用符号优先级的巧妙方法

    b在括号中被赋为a后并不影响原算式中b的值

    • 形式一

      a=b+(b=a)*0;
      
    • 形式二

      a=a+b-(b=a);
      
  5. 栈实现(createstack函数以及top函数省去)

    压栈push 弹栈pop 返回当前栈顶元素top 创建一个栈头createstack

    typedef struct stack{int data;struct stack *next;
    }NODE,*Stack;
    void push(int n,Stack s){Stack node=(Stack)malloc(sizeof(NODE));assert(node);node->element=n;node->next=s->next;s->next=node;
    }
    void pop(Stack s){Stack node;if(s->next==NULL){printf("there is a false\n");return;}node=s->next;s->next=node->next;free(node);
    }
    void swap(int *a,int *b){Stack s=createstack();push(*a,s);push(*b,s);*a=top(s);pop(s);*b=top(s);
    }
    

先将a压入栈中,再压入b,将栈顶元素b的值赋给a,最后弹出b将栈顶元素a的值赋值给b

三、下面代码段将打印出多少个“=” ? 运用相关知识解释该输出。

#include  <stdio.h>
int main(){
for(unsigned int i = 3;i>=0;i--){putchar('='); } 
}

unsigned的范围从0到一个正数,所以i的值永远不会为负数,死循环无限输出=

四、逻辑关系的爱恨情仇。简述这个逻辑的运算过程以及输出 answer 的值。

#include  <stdio.h>
int count = 100;// 简述逻辑 
//这里的count是一个全局变量,作用域和生存域都是整个代码区
int process(int num) { while (1) {//死循环,就算switch走完一遍没有目标也会继续重新执行,除非找到return离开函数switch (num) { case 0:  //这是旅途的第一站,对同一个数进行两次相同的异或运算后该数不变,则此处实际是0|10=10//逻辑或是有1则1,全0才0,逻辑异或是相同则0,不同则1num = num ^ 99 ^ 88 ^ 99 ^ 88 | 10; case 15:  //上面没有break,还在第一站,10^5=15//第二站进来15^5=10num = num ^ 5;  break;  case 8: //第四站,num=1*2的八次方,即256,随后这个表达式即num=num-(num++),num还没来得及加就被减为0了,随后加为1//左移实际上等价于*2的num次方num = 1 << num;num -= num++; break;  case 10:  //第三站,10-3=7,count=100+7=107,此后num变为8num = num + - 3;  count = count + num++;  break;  case 2:  //第六站,num变为1--num;  case 5:  //没有break,仍然是第六站,但有return,会跳出process函数,1<<1即2,answer的值也就明朗了return (1 << num);  default: //没有1的情况,所以这里是第五站,各部位符号优先级相同,则从左往右算,1&1=1,条件为真,执行num+1,即num=2//逻辑与是有0则0,全1才1,三元表达式a?b:c意为a如果非0执行b,否则实行cnum = num & 1 ? num + 1 : num; } } 
}
int main() { int start = 0; int answer = process(start); // 输出结果 printf("answer == %d\n", answer); return 0; 
}

五、structunion 的故事。

#include <stdio.h>
typedef struct str  { short e1 ; //2占八分之二char e2 ; //1占八分之三char e3 [ 6]; //6原来的用不完,重开一个占八分之六double e5 ; //8原来的用不完,重开一个占满int e6 ; //4占八分之四
}str ; //则该结构体所占内存为32
typedef union uni  { short e1 ; //2char e2 ;  //1char e3 [ 6]; //6struct str e4 ; //32double e5 ; //8int e6 ; //4
}uni ; //则该联合体所占内存为32
int main(){ int x  = sizeof (str); int y  = sizeof (uni); printf ("x = %d ,y = %d \ n " , x , y); printf ("hello = %d \ n " , printf ("3G = %d \n " , --x == 23 && x-- == 22 && ++y == 9)); //逻辑运算只算了--x,x的值变为31//其次后面的printf返回9并把其本身的内容输出//最后前面的printf输出其本身的内容printf ("x1 = %d ,y1 = %d \ n " , x , y); return 0 ; }

此题考点一在于结构体的内存对齐规则☞结构体中的各部分所占内存块会与占内存最大的那个变量对齐

当然也有办法让这个规则失效,在预处理阶段使用#pragame pack()可以使各部分强制按照()中的数对齐

注:括号中的数只能为1,2,4,8

考点二在于联合体的内存对齐规则☞联合体的内存为其各部分中所占内存最大的那部分

考点三在于逻辑运算的返回值

  • 逻辑运算的返回值一般为1(真)或0(假),且存在短路现象

  • 短路:&&前的结果为假则不进行其后的运算 同样||前的结果为真则不进行其后的运算

  • x–先判后算,–x先算后判

考点四在于printf的返回值,其返回值是其""中的字符数

注:\n%d都只占一个字符 也占一个字符

六、宏函数基础。

#include  <stdio.h>
#define SQR(x) x*x 
int main() { int i  = 1 , j  = 2 ; printf ("%d \ n " ,SQR ( i + j)); reutrn 0;
}

宏函数的替换很单纯 真的只是替换

所以SQR(i+j)会被替换为i+j*i+j 遵循四则运算法则故答案为5

七、小雪今天也有学习指针。

//以下程序运行结果是什么?

#include <stdio.h>
int main() { int nums [ 2][ 5]={{ 2 , 4 , 6 , 8 , 10},{12 ,14 ,16 ,18 ,20}}; //nums是一个由两个小数组组成的大数组int *ptr1=(int*)(&nums + 1); //先对nums取地址,其实和nums一样,也是对大整体加1加到了数组外面int *ptr2=(int*)(&nums [ 0]+ 1); //对nums[0]进行取地址,导致其+1的对象变为了一个小数组,加到了下一个小数组的第一个//此处为什么进行强制类型转化将在下面说明printf ("*nums[0][4]+1 = %d \ n " ,nums [ 0][ 4]+ 1); //第一个小数组的第五个数字,即10,再加1为11+printf ("*(nums[0])+1 = %d \ n ",*(nums [ 0])+ 1); //此处先对nums[0]取值,实际是*(nums[0][0]),即2,再加1为3printf ("*(nums[0]+1) = %d \ n ",*(nums [ 0]+ 1)); //nums[0]即nums[0][0],加1后为nums[0][1],取值后为4printf ("*(nums[1]+1) = %d \ n ",*(nums [ 1]+ 1)); //同上取值后为14printf ("*(nums+1) = %d \ n ",*(nums + 1)); //此处对nums整个大整体加1,会加到一个未定义的区域,取值后无法估值printf ("*(ptr2 -1) = %d \ n ",*(ptr2 - 1)); //由于二维数组实际上内存是连续分布的,第二个小数组第一个减1后到了nums[0][4],即10printf ("*(ptr -1) = %d \ n ",*(ptr1 - 1)); //由数组外面不存在的“nums[2][0]”-1后回归到了nums[1][4],即20return 0 ; 
}

关于ptr1ptr2指向地址前先进行强制转化的问题:

nums本质上是一个二级指针,是一个指向五个一级指针的二级指针,而ptr1ptr2是两个一级指针,直接使一级指针指向二维数组会报错

进行强制类型转化时会发生数据的截断

八、上一个被欺负的指针找来了她的男朋友。

//以下程序运行结果是什么?

 #include <stdio.h>int main() { int a [ 3][ 4 ] = {{ 1 , 2 , 3 , 4}, { 3 , 4 , 5 , 6}, { 5 , 6 , 7 , 8}}; int i ; int(* p)[ 4 ] = a,*q  = a [ 0]; //由于(*p)首先是一个指针,所以p是一个指向数组的指针;易得q指向的a[0]为1for (i  = 0 ; i  < 3 ; i++) { if (i == 0 ) (* p)[i  + i  / 2 ] = *q  + 1 ; //i+i/2还是0,将p指向第一个数组的第一个数改为了1+1=2else  p++,++ q ;  //i总共还能执行两次,p,q均向后移了两位,只是p是以一个数组的长度进行移动,而q是单个移动} for (i  = 0 ; i  < 3 ; i++) { printf ("a[%d][%d] = %d \ n " , i , i , a [ i][ i]);  } //输出三个值,即a[0][0]=2,a[1][1]=4,a[2][2]=7//此处需要注意a[0][0]在之前已经被p改变为2printf ("%d, %d \ n " , *((int*) p), * q); //p其实也可以理解为一个二级指针,所以要先进行强制类型转换再取值,p此前移动到了第三个数组,强转后再取值为5//q移动后的值即3}

九、那就简单排个序吧 。

解释这段代码的作用,以及代码逻辑和相关用法,以及这些函数的特性与作用。

#include  <stdio.h>
int int_cmp(const void * p1, const void * p2) { return (*( int *)p1 - *(int *) p2); } //将p强制转化后取值
//比较函数,经常改变形式以适用于qsort函数
//const void*是其适用性广泛的关键,可以任意强制转化来进行相应类型的比较
//如果p1比p2大则会返回1,相等返回0,否则返回-1
void _swap(void *p1, void * p2, int size) { int i = 0; for (i = 0; i< size; i++) { char tmp = *((char *)p1 + i); *(( char *)p1 + i) = *((char *) p2 + i); *(( char *)p2 + i) = tmp; } 
} 
//看上去写的很复杂,但实际上就是用中间变量交换两个变量的值
//值得注意的是如果p1和p2是两个数组,该交换函数仍然能交换它们所有值,适用性极强
void Qsort(void *base, int count, int size, int (*cmp)(void *, void *)) { //此处调用比较函数借助了一个函数指针cmp去调用函数,通常称其为回调函数//函数指针通常只用将函数原型里的函数名替换为*指针名即可//用函数指针去调用函数,指针只管调用,不用关心具体的函数内容,将调用与函数的关联性削弱//如果遇到了两个相似形式的函数,就可以直接用函数指针改变部分参数去同时调用两个函数int i = 0; int j = 0; for (i = 0; i< count - 1; i++) { for (j = 0; j < count-i-1; j++) { if (cmp ((char *) base + j*size , (char *)base + (j + 1)*size) > 0)//如果比较函数判断大于0,即前者比后者大就执行交换函数,该处比较的始终是两个相邻的元素,可见其本质是冒泡排序//两个for循环不断遍历最终完成排序{_swap(( char *)base + j*size, (char *)base + (j + 1)*size, size); } } } 
} 
//
int main() { int arr[] = { 1, 3, 5, 7, 9, 2, 4, 6, 8, 0 }; int i = 0; Qsort(arr, sizeof(arr) / sizeof(arr[0]), sizeof (int), (int (*)(void *, void *)) int_cmp); //qsort函数位于stdlib库中,原理是快速排序//qsort(要排序的数组,需要排序的元素个数,一个元素的大小,比较函数)for (i = 0; i< sizeof(arr) / sizeof(arr[0]); i++) { printf( "%d ", arr[i]); } printf("\n"); return 0; 
}

初看时快排,实际上为冒泡,同时该题处处都在考察对适用泛用性的理解

十、 学数学

下面的算式中,不同的汉字表示不同的数字,相同的汉字表示相同的数字,问这个算式中每个 汉字各代表什么数字?(提示:枚举)

(使用 C 语言向学长学姐解释解题思路及代码,请提前准备好代码,如果不会也没关系可以向 学长学姐讲述一下自己的想法)
在这里插入图片描述

爱 = () 数 = ()学 = ()啊 = ()

int x,y,z,t;
for(x=0;x<10;x++){for(y=0;y<10;y++){for(z=0;z<10;z++){for(t=0;t<10;t++){if(x*102+y*10+z*10+t*100==y+x*10+z*100+t*1000&&x!=y)printf("爱=(%d)\t数=(%d)\t学=(%d)\t啊=(%d)\n",t,z,x,y);}}}}

设元乘上各个位数相加,暴力求解即可,除去四个0的情况故加一个x!=y的限制条件

十一、你了解几种排序算法?简单说一下。

  • 冒泡排序(原始版)
void BubbleSort(int n,int*s){int tep;for(int j=0;j<n;j++){for(int k=1;k<n;k++){if(s[k-1]>s[k]){tep=s[k];s[k]=s[k-1];s[k-1]=tep;}}}
}
  • 选择排序(原始版)
void SelectSort(int n, int* s){  for(int i=0;i<n-1;i++){  int min=i;  for(int cnt=i+1;cnt<n;cnt++){  if(s[cnt]<s[min]){  min=cnt;  }  }  //每轮找到一个最小值与该轮第一个值交换if(min!=i){  int temp=s[i];  s[i]=s[min];  s[min]=temp;  }  }  
}
  • 快速排序(原始版)
void quicksort(int *m,int n){if(n<2)return;//递归的结束条件int pleft=0,pright=n-1;int judge=1,middle=m[0];//middle为基准值,比它小的放在左边,比它大的放在右边while(pleft<pright){if(judge==1){if(m[pright]>=middle){pright--;continue;}//直到找到一个比middle小的需要放到左边的为止m[pleft]=m[pright];pleft++;judge=0;continue;}if(judge==0){if(m[pleft]<=middle){pleft++;continue;}//同上  找到一个大的需要放到右边的为止m[pright]=m[pleft];pright--;judge=1;continue;}}m[pleft]=middle;//将被拿出来的基准值放到空出来的位置上quicksort(m,pleft);//先将左边一直递归排序完quicksort(m+pleft+1,n-pleft-1);//排完左边后对右边一直递归排序
}
  • 归并排序(递归原始版)
//在mosrt分为每个单份后的合并
void merge(int *arr,int *just,int left,int middle,int right){int l_pos=left;//左边的第一个元素int r_pos=middle+1;//右边的第一个元素int pos=left;//临时存放点while(l_pos<=middle&&r_pos<=right){//每次总是往临时数组中放入左右两个区间中更小的元素if(arr[l_pos]<arr[r_pos]){just[pos++]=arr[l_pos++];}else{just[pos++]=arr[r_pos++];}}//下面两个循环不会同时执行,只会出现一边排得更快导致另一边没排完需要继续排的结果while(l_pos<=middle){just[pos++]=arr[l_pos++];}while(r_pos<=right){just[pos++]=arr[r_pos++];}//将临时数组just中的值返回给arrwhile(left<=right){arr[left]=just[left];left++;}
}
//归并前将各个数字分开
void msort(int *arr,int *just,int left,int right){//保证递归后每个区间只有一个元素if(left<right){int middle=(left+right)/2;//将左边与中间元素分为一组//中间往后第一个元素与最后一个元素分为一组msort(arr,just,left,middle);msort(arr,just,middle+1,right);//将已经分为各个单一的数字归并merge(arr,just,left,middle,right);}
}
//归并前创建存储数组just
void merge_sort(int *arr,int n){int *just=(int*)malloc(n*sizeof(int));if(just){msort(arr,just,0,n-1);free(just);}else{printf("lost malloc");}
}

这篇关于xiyou2023年3G一面题解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/814949

相关文章

C++ | Leetcode C++题解之第393题UTF-8编码验证

题目: 题解: class Solution {public:static const int MASK1 = 1 << 7;static const int MASK2 = (1 << 7) + (1 << 6);bool isValid(int num) {return (num & MASK2) == MASK1;}int getBytes(int num) {if ((num &

C语言 | Leetcode C语言题解之第393题UTF-8编码验证

题目: 题解: static const int MASK1 = 1 << 7;static const int MASK2 = (1 << 7) + (1 << 6);bool isValid(int num) {return (num & MASK2) == MASK1;}int getBytes(int num) {if ((num & MASK1) == 0) {return

C - Word Ladder题解

C - Word Ladder 题解 解题思路: 先输入两个字符串S 和t 然后在S和T中寻找有多少个字符不同的个数(也就是需要变换多少次) 开始替换时: tips: 字符串下标以0开始 我们定义两个变量a和b,用于记录当前遍历到的字符 首先是判断:如果这时a已经==b了,那么就跳过,不用管; 如果a大于b的话:那么我们就让s中的第i项替换成b,接着就直接输出S就行了。 这样

【秋招笔试】9.07米哈游秋招改编题-三语言题解

🍭 大家好这里是 春秋招笔试突围,一起备战大厂笔试 💻 ACM金牌团队🏅️ | 多次AK大厂笔试 | 大厂实习经历 ✨ 本系列打算持续跟新 春秋招笔试题 👏 感谢大家的订阅➕ 和 喜欢💗 和 手里的小花花🌸 ✨ 笔试合集传送们 -> 🧷春秋招笔试合集 🍒 本专栏已收集 100+ 套笔试题,笔试真题 会在第一时间跟新 🍄 题面描述等均已改编,如果和你笔试题看到的题面描述

LeetCode 第414场周赛个人题解

目录 Q1. 将日期转换为二进制表示 原题链接 思路分析 AC代码 Q2. 范围内整数的最大得分 原题链接 思路分析 AC代码 Q3. 到达数组末尾的最大得分 原题链接 思路分析 AC代码 Q4. 吃掉所有兵需要的最多移动次数 原题链接 思路分析 AC代码 Q1. 将日期转换为二进制表示 原题链接 Q1. 将日期转换为二进制表示 思路分析

牛客小白月赛100部分题解

比赛地址:牛客小白月赛100_ACM/NOI/CSP/CCPC/ICPC算法编程高难度练习赛_牛客竞赛OJ A.ACM中的A题 #include<bits/stdc++.h>using namespace std;#define ll long long#define ull = unsigned long longvoid solve() {ll a,b,c;cin>>a>>b>

CVTE java web后台实习生笔试+技术一面总结

投的第一份简历,也可以说是第一次写笔试和参加面试。题在前面,总结在最后,努力不骗人。 笔试 题型:20道不定项选择题+2道算法题+1道架构设计题 选择题 选择题出的很全面,因为是不定项选择,一道题就可以考很多知识点。 当时做的时候以为笔试都是这么难,做完实验室同学告诉我这个算比较难的了,而且据我观察可能是跟春招找正式offer的一批难度的题。可能最后过的标准不一样吧。 选项信息量很大,

P2858 [USACO06FEB] Treats for the Cows G/S 题解

P2858 题意 给一个数组。每天把最左或者最右的东西卖掉,第 i i i个东西,第 d a y day day天卖出的价格是 a [ i ] ∗ d a y a[i]*day a[i]∗day。 记忆化搜索 void dfs(int l,int r,int day,ll sum){if(v[l][r]>=sum)return;v[l][r]=sum;if(l>r)//这就是dp答案{

【C++题解】1272. 郭远摘苹果

欢迎关注本专栏《C++从零基础到信奥赛入门级(CSP-J)》 问题:1272. 郭远摘苹果 类型:二维数组 题目描述: 郭远有一天走到了一片苹果林,里面每颗树上都结有不同数目的苹果,郭远身上只能拿同一棵树上的苹果,他每到一棵果树前都会把自己身上的苹果扔掉并摘下他所在树上的苹果并带走(假设郭远会走过每一棵苹果树),问在郭远摘苹果的整个过程中,他身上携带的最多苹果数与最小苹果数的差是多少?

【最新华为OD机试E卷-支持在线评测】机器人活动区域(100分)多语言题解-(Python/C/JavaScript/Java/Cpp)

🍭 大家好这里是春秋招笔试突围 ,一枚热爱算法的程序员 ✨ 本系列打算持续跟新华为OD-E/D卷的三语言AC题解 💻 ACM金牌🏅️团队| 多次AK大厂笔试 | 编程一对一辅导 👏 感谢大家的订阅➕ 和 喜欢💗 🍿 最新华为OD机试D卷目录,全、新、准,题目覆盖率达 95% 以上,支持题目在线评测,专栏文章质量平均 94 分 最新华为OD机试目录: https://blog.