有一个数组a[1000]存放0--1000;要求每隔二个数删掉一个数,到末尾时循环至开头继续进行,求最后一个被删掉的数的原始下标位置。
以7个数为例:
{0,1,2,3,4,5,6,7} 0-->1-->2(删除)-->3-->4-->5(删除)-->6-->7-->0(删除),如此循环直到最后一个数被删除。
方法1:数组
#include
using namespace std;
#define null 1000
int main()
{
int arr[1000];
for (int i=0;i<1000;++i)
arr[i]=i;
int j=0;
int count=0;
while(count<999)
{
while(arr[j%1000]==null)
j=(++j)%1000;
j=(++j)%1000;
while(arr[j%1000]==null)
j=(++j)%1000;
j=(++j)%1000;
while(arr[j%1000]==null)
j=(++j)%1000;
arr[j]=null;
++count;
}
while(arr[j]==null)
j=(++j)%1000;
cout<<J<<ENDL;
return 0;
}方法2:链表
#include
using namespace std;
#define null 0
struct node
{
int data;
node* next;
};
int main()
{
node* head=new node;
head->data=0;
head->next=null;
node* p=head;
for(int i=1;i<1000;i++)
{
node* tmp=new node;
tmp->data=i;
tmp->next=null;
head->next=tmp;
head=head->next;
}
head->next=p;
while(p!=p->next)
{
p->next->next=p->next->next->next;
p=p->next->next;
}
cout<data;
return 0;
}
方法3:通用算法
#include
#define MAXLINE 1000 //元素个数
/*
MAXLINE 元素个数
a[] 元素数组
R[] 指针场
suffix 下标
index 返回最后的下标序号
values 返回最后的下标对应的值
start 从第几个开始
K 间隔
*/
int find_n(int a[],int R[],int K,int& index,int& values,int s=0) {
int suffix;
int front_node,current_node;
suffix=0;
if(s==0) {
current_node=0;
front_node=MAXLINE-1;
}
else {
current_node=s;
front_node=s-1;
}
while(R[front_node]!=front_node) {
printf("%d\n",a[current_node]);
R[front_node]=R[current_node];
if(K==1) {
current_node=R[front_node];
continue;
}
for(int i=0;i<K;I++){
front_node=R[front_node];
}
current_node=R[front_node];
}
index=front_node;
values=a[front_node];
return 0;
}
int main(void) {
int a[MAXLINE],R[MAXLINE],suffix,index,values,start,i,K;
suffix=index=values=start=0;
K=2;
for(i=0;ia[i]=i;
R[i]=i+1;
}
R[i-1]=0;
find_n(a,R,K,index,values,2);
printf("the value is %d,%d\n",index,values);
return 0;
}
试题:
void test2()
{
char string[10], str1[10];
int i;
for(i=0; i<10; i++)
{
str1[i] = 'a';
}
strcpy( string, str1 );
}
解答:对试题2,如果面试者指出字符数组str1不能在数组内结束可以给3分;如果面试者指出strcpy(string, str1)调用使得从str1内存起复制到string内存起所复制的字节数具有不确定性可以给7分,在此基础上指出库函数strcpy工作方式的给10 分;
str1不能在数组内结束:因为str1的存储为:{a,a,a,a,a,a,a,a,a,a},没有'\0'(字符串结束符),所以不能结束
strcpy( char *s1,char *s2)他的工作原理是,扫描s2指向的内存,逐个字符付到s1所指向的内存,直到碰到'\0',因为str1结尾没有'\0',所以具有不确定性,不知道他后面还会付什么东东。
正确应如下
void test2()
{
char string[10], str1[10];
int i;
for(i=0; i<9; i++)
{
str1[i] = 'a'+i; //把abcdefghi赋值给字符数组
}
str[i]='\0';//加上结束符
strcpy( string, str1 );
}
第二个code题是实现strcmp
int StrCmp(const char *str1, const char *str2)
做是做对了,没有抄搞,比较乱
int StrCmp(const char *str1, const char *str2)
{
assert(str1 && srt2);
while (*str1 && *str2 && *str1 == *str2) {
str1++, str2++;
}
if (*str1 && *str2)
return (*str1-*str2);
elseif (*str1 && *str2==0)
return 1;
elseif (*str1 = = 0 && *str2)
return -1;
else
return 0;
}
int StrCmp(const char *str1, const char *str2)
{
//省略判断空指针(自己保证)
while(*str1 && *str1++ = = *str2++);
return *str1-*str2;
}
第三个code题是实现子串定位
int FindSubStr(const char *MainStr, const char *SubStr)
做是做对了,没有抄搞,比较乱
int MyStrstr(const char* MainStr, const char* SubStr)
{
const char *p;
const char *q;
const char * u = MainStr;
//assert((MainStr!=NULL)&&( SubStr!=NULL));//用断言对输入进行判断
while(*MainStr) //内部进行递增
{
p = MainStr;
q = SubStr;
while(*q && *p && *p++ == *q++);
if(!*q )
{
return MainStr - u +1 ;//MainStr指向当前起始位,u指向
}
MainStr ++;
}
return -1;
}
分析:
int arr[] = {6,7,8,9,10};
int *ptr = arr;
*(ptr++)+=123;
printf(“ %d %d ”, *ptr, *(++ptr));
输出:8 8
过程:对于*(ptr++)+=123;先做加法6+123,然后++,指针指向7;对于printf(“ %d %d ”, *ptr, *(++ptr));从后往前执行,指针先++,指向8,然后输出8,紧接着再输出8
华为全套完整试题
高级题
6、已知一个单向链表的头,请写出删除其某一个结点的算法,要求,先找到此结点,然后删除。
slnodetype *Delete(slnodetype *Head,int key){}中if(Head->number==key)
{
Head=Pointer->next;
free(Pointer);
break;
}
Back = Pointer;
Pointer=Pointer->next;
if(Pointer->number==key)
{
Back->next=Pointer->next;
free(Pointer);
break;
}
void delete(Node* p)
{
if(Head = Node)
while(p)
}
有一个16位的整数,每4位为一个数,写函数求他们的和。
解释:
整数1101010110110111
和 1101+0101+1011+0111
感觉应该不难,当时对题理解的不是很清楚,所以写了一个函数,也不知道对不对。
疑问:
既然是16位的整数,1101010110110111是2进制的,那么函数参数怎么定义呢,请大虾指教。
答案:用十进制做参数,计算时按二进制考虑。
/* n就是16位的数,函数返回它的四个部分之和 */
char SumOfQuaters(unsigned short n)
{
char c = 0;
int i = 4;
do
{
c += n & 15;
n = n >> 4;
} while (--i);
return c;
}
有1,2,....一直到n的无序数组,求排序算法,并且要求时间复杂度为O(n),空间复杂度O(1),使用交换,而且一次只能交换两个数.(华为)
#include
int main()
{
int a[] = {10,6,9,5,2,8,4,7,1,3};
int len = sizeof(a) / sizeof(int);
int temp;
for(int i = 0; i < len; )
{
temp = a[a[i] - 1];
a[a[i] - 1] = a[i];
a[i] = temp;
if ( a[i] == i + 1)
i++;
}
for (int j = 0; j < len; j++)
cout<<A[J]<<",";
return 0;
}
(慧通)
1 写出程序把一个链表中的接点顺序倒排
typedef struct linknode
{
int data;
struct linknode *next;
}node;
//将一个链表逆置
node *reverse(node *head)
{
node *p,*q,*r;
p=head;
q=p->next;
while(q!=NULL)
{
r=q->next;
q->next=p;
p=q;
q=r;
}
head->next=NULL;
head=p;
return head;
}
2 写出程序删除链表中的所有接点
void del_all(node *head)
{
node *p;
while(head!=NULL)
{
p=head->next;
free(head);
head=p;
}
cout<<"释放空间成功!"<<ENDL;
}
3两个字符串,s,t;把t字符串插入到s字符串中,s字符串有足够的空间存放t字符串
void insert(char *s, char *t, int i)
{
char *q = t;
char *p =s;
if(q == NULL)return;
while(*p!='\0')
{
p++;
}
while(*q!=0)
{
*p=*q;
p++;
q++;
}
*p = '\0';
}
分析下面的代码:
char *a = "hello";
char *b = "hello";
if(a= =b)
printf("YES");
else
printf("NO");
这个简单的面试题目,我选输出 no(对比的应该是指针地址吧),可在VC是YES 在C是NO
lz的呢,是一个常量字符串。位于静态存储区,它在程序生命期内恒定不变。如果编译器优化的话,会有可能a和b同时指向同一个hello的。则地址相同。如果编译器没有优化,那么就是两个不同的地址,则不同
写一个函数,功能:完成内存之间的拷贝
memcpy source code:
270 void* memcpy( void *dst, const void *src, unsigned int len )
271 {
272 register char *d;
273 register char *s;
27
275 if (len == 0)
276 return dst;
277
278 if (is_overlap(dst, src, len, len))
279 complain3("memcpy", dst, src, len);
280
281 if ( dst > src ) {
282 d = (char *)dst + len - 1;
283 s = (char *)src + len - 1;
284 while ( len >= 4 ) {
285 *d-- = *s--;
286 *d-- = *s--;
287 *d-- = *s--;
288 *d-- = *s--;
289 len -= 4;
290 }
291 while ( len-- ) {
292 *d-- = *s--;
293 }
294 } else if ( dst < src ) {
295 d = (char *)dst;
296 s = (char *)src;
297 while ( len >= 4 ) {
298 *d++ = *s++;
299 *d++ = *s++;
300 *d++ = *s++;
301 *d++ = *s++;
302 len -= 4;
303 }
304 while ( len-- ) {
305 *d++ = *s++;
306 }
307 }
308 return dst;
309 }
公司考试这种题目主要考你编写的代码是否考虑到各种情况,是否安全(不会溢出)
各种情况包括:
1、参数是指针,检查指针是否有效
2、检查复制的源目标和目的地是否为同一个,若为同一个,则直接跳出
3、读写权限检查
4、安全检查,是否会溢出
memcpy拷贝一块内存,内存的大小你告诉它
strcpy是字符串拷贝,遇到'\0'结束
/* memcpy ─── 拷贝不重叠的内存块 */
void memcpy(void* pvTo, void* pvFrom, size_t size)
{
void* pbTo = (byte*)pvTo;
void* pbFrom = (byte*)pvFrom;
ASSERT(pvTo != NULL && pvFrom != NULL); //检查输入指针的有效性
ASSERT(pbTo>=pbFrom+size || pbFrom>=pbTo+size);//检查两个指针指向的内存是否重叠
while(size-->0)
*pbTo++ == *pbFrom++;
return(pvTo);