IT公司笔试题算法部分(四)

本文解析了包括过桥问题、字符移动、单链表逆转、字符串转整型等经典编程题目,提供了详细的算法思路与实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

15、现在小明一家过一座桥,过桥的时候是黑夜,所以必须有灯。现在小明过桥要1秒,小明的弟弟要3秒,小明的爸爸要6秒,小明的妈妈要八秒,小明的爷爷要12秒。每次此桥最多可过两人,而过桥的速度依过桥最慢者而定,而且灯在点燃后30秒就会熄灭。问小明一家如何过桥?(原本是个智力题,这里用程序来求解)
#include "stdafx.h"
#define N    5
#define SIZE 64
 
// 将人员编号:小明-0,弟弟-1,爸爸-2,妈妈-3,爷爷-4
// 每个人的当前位置:0--在桥左边, 1--在桥右边
int Position[N];   
// 过桥临时方案的数组下标; 临时方案; 最小时间方案;
int Index, TmpScheme[SIZE], Scheme[SIZE];  
// 最小过桥时间总和,初始值100;每个人过桥所需要的时间
int MinTime=100, Time[N]={1, 3, 6, 8, 12}; 
// 寻找最佳过桥方案。Remnant:未过桥人数; CurTime:当前已用时间;
// Direction:过桥方向,1--向右,0--向左
void Find(int Remnant, int CurTime, int Direction)
{
    if(Remnant==0){                               // 所有人已经过桥,更新最少时间及方案
        MinTime=CurTime;
        for(int i=0; i<SIZE && TmpScheme[i]>=0; i++)
        {
            Scheme[i]=TmpScheme[i];
        }
    }else if(Direction==1){                        // 过桥方向向右,从桥左侧选出两人过桥
        for(int i=0; i<N; i++)                   
        {
            if(Position[i]==0 && CurTime+Time[i]<MinTime){
                TmpScheme[Index++] = i;
                Position[i] = 1;
                for(int j=0; j<N; j++)           
                {
                    int TmpMax = (Time[i]>Time[j] ? Time[i] : Time[j]);
                    if(Position[j]==0 && CurTime+TmpMax<MinTime)
                    {
                        TmpScheme[Index++] = j;   
                        Position[j] = 1;       
                        Find(Remnant-2, CurTime+TmpMax, !Direction);
                        Position[j] = 0;       
                        TmpScheme[--Index] = -1;
                    }
                }
                Position[i] = 0;
                TmpScheme[--Index] = -1;
            }
        }
    }else{        // 过桥方向向左,从桥右侧选出一个人回来送灯
        for(int j=0; j<N; j++)
        {
            if(Position[j]==1 && CurTime+Time[j] < MinTime)
            {
                TmpScheme[Index++] = j;
                Position[j] = 0;
                Find(Remnant+1, CurTime+Time[j], !Direction);
                Position[j] = 1;
                TmpScheme[--Index] = -1;
            }
        }
    }
}
int main(int argc, char* argv[])
{
    for(int i=0; i<SIZE; i++)        // 初始方案内容为负值,避免和人员标号冲突
        Scheme[i] = TmpScheme[i] = -1;
 
Find(N, 0, 1);                   // 查找最佳方案
 
    printf("MinTime=%d:", MinTime); // 输出最佳方案
    for(int i=0; i<SIZE && Scheme[i]>=0; i+=3)
        printf(" %d-%d %d", Scheme[i], Scheme[i+1], Scheme[i+2]);
    printf("/b/b ");
    return getchar();
}
 
16、2005年11月金山笔试题。编码完成下面的处理函数。函数将字符串中的字符'*'移到串的前部分,前面的非'*'字符后移,但不能改变非'*'字符的先后顺序,函数返回串中字符'*'的数量。如原始串为:ab**cd**e*12,处理后为*****abcde12,函数并返回值为5。(要求使用尽量少的时间和辅助空间)
int change(char *str)                     /* 这个算法并不高效,从后向前搜索效率要高些 */
{
     int count = 0;                       /* 记录串中字符'*'的个数 */
     for(int i=0, j=0; str[i]; i++)       /* 重串首开始遍历 */
     {
         if(str[i]=='*'){                 /* 遇到字符'*' */
              for(j=i-1; str[j]!='*'&&j>=0; j--) /* 采用类似插入排序的思想,将*前面 */
                   str[j+1]=str[j];             /* 的非*字符逐个后移,直到遇到*字符 */
              str[j+1] = '*';
              count++;
         }
     }
     return count;
}
int main(int argc, char* argv[])
{
     char str[] = "ab**cd**e*12";
     printf("str1=%s/n", str);
     printf("str2=%s, count=%d", str, change(str));
     return getchar();
}
// 终于得到一个比较高效的算法,一个网友提供,应该和金山面试官的想法一致。算法如下:
int change(char *str)
{
     int i,j=strlen(str)-1;
     for(i=j; j>=0; j--)
     {
         if(str[i]!='*'){
              i--;
         }else if(str[j]!='*'){
              str[i] = str[j];
              str[j] = '*';
              i--;
         }
     }
     return i+1;
}
 
17、2005年11月15日华为软件研发笔试题。实现一单链表的逆转。
#include "stdafx.h"
 
typedef char eleType;       // 定义链表中的数据类型
typedef struct listnode     // 定义单链表结构
{
     eleType data;
     struct listnode *next;
}node;
 
node *create(int n)         // 创建单链表,n为节点个数
{
     node *p = (node *)malloc(sizeof(node));  
     node *head = p;    head->data = 'A';
     for(int i='B'; i<'A'+n; i++)
     {                 
         p = (p->next = (node *)malloc(sizeof(node)));
         p->data = i;
         p->next = NULL;       
     }
     return head;
}
 
 
void print(node *head)      // 按链表顺序输出链表中元素
{
     for(; head; head = head->next)
         printf("%c ", head->data); 
     printf("/n");
}
 
node *reverse(node *head, node *pre) // 逆转单链表函数。这是笔试时需要写的最主要函数
{
     node *p=head->next;
     head->next = pre;
     if(p)
         return reverse(p, head);
     else
         return head;
}
 
int main(int argc, char* argv[])
{
     node *head = create(6);
     print(head);
     head = reverse(head, NULL);
     print(head);
     return getchar();
}
 
18、编码实现字符串转整型的函数(实现函数atoi的功能),据说是神州数码笔试题。如将字符串 +123”à123, -0123à-123, “123CS45”à123, 123.45CSà123, CS123.45”à0
#include "stdafx.h"
int str2int(const char *str)         // 字符串转整型函数
{
     int i=0, sign=1, value = 0;
     if(str==NULL) return NULL;      // 空串直接返回 NULL
     if(str[0]=='-' || str[0]=='+'){ // 判断是否存在符号位
         i = 1;
         sign = (str[0]=='-' ? -1 : 1);
     }
     for(; str[i]>='0' && str[i]<='9'; i++)    // 如果是数字,则继续转换
         value = value * 10 + (str[i] - '0');
     return sign * value;
}
int main(int argc, char *argv[])
{
     char *str = "-123.45CS67";
     int val = str2int(str);
     printf("str=%s/tval=%d/n", str, val);
     return getchar();
}
 
19、歌德巴赫猜想。任何一个偶数都可以分解为两个素数之和。
#include "stdafx.h"
#include "math.h"
int main(int argc, char* argv[])
{
     int Even=78, Prime1, Prime2, Tmp1, Tmp2;
     for(Prime1=3; Prime1<=Even/2; Prime1+=2)
     {
         for(Tmp1=2,Tmp2=sqrt(float(Prime1)); Tmp1<=Tmp2 && Prime1%Tmp1 != 0; Tmp1++);
         if(Tmp1<=Tmp2) continue;
         Prime2 = Even-Prime1;
         for(Tmp1=2,Tmp2=sqrt(float(Prime2)); Tmp1<=Tmp2 && Prime2%Tmp1 != 0; Tmp1++);
         if(Tmp1<=Tmp2) continue;
         printf("%d=%d+%d/n", Even, Prime1, Prime2);
     }
     return getchar();
}
 
1.已知strcpy 函数的原型是: char *strcpy(char *strDest, const char *strSrc); 其中strDest 是目的字符串,strSrc 是源字符串。不调用C++/C 的字符串库函数, 请编写函数 strcpy 答案: char *strcpy(char *strDest, const char *strSrc) { if ( strDest == NULL || strSrc == NULL) return NULL ; if ( strDest == strSrc) return strDest ; char *tempptr = strDest ; while( (*strDest++ = *strSrc++) != ‘\0) ; return tempptr ; } 3.12 main 函数执行以前,还会执行什么代码? (Autodesk) 答案:全局对象的构造函数会在main 函数之前执行。 3.13 描述内存分配方式以及它们的区别。 (Autodesk , Microsoft) 答案:1) 从静态存储区域分配。内存在程序编译的时候就已经分配好,这块 内存在程序的整个运行期间都存在。例如全局变量,static 变量。 (2) 在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上 创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理 器的指令集。 (3) 从堆上分配,亦称动态内存分配。程序在运行的时候用malloc 或new 申 请任意多少的内存,程序员自己负责在何时用free 或delete 释放内存。动态内 存的生存期由我们决定,使用非常灵活,但问题也最多。 3.14 什么是虚拟存储器?virtual memory 怎样映射到physical memory?页面替换 算法有哪些? (Microsoft) 见操作系统 p238 页。掌握的页面替换算法NRU,FIFO,第二次机会页面替换 算法,LRU 3.15 有个同样的容器,里面装满了粒数相同的药丸,正常药丸的质量为m,变 质药丸的质量为m+1,现在已知这个容器中,有一个装的全是变质药丸,用电 子秤只称一次,找出哪个容器装的是变质药丸(Microsoft) 答案:把个容器依次编号为1、2、3、4,然后从中分别取出1、2、3、4 粒药 丸,称这10 粒药丸的质量,如果质量为10m+1,则说明第一个容器装的是变质药 丸,如果为10m+2 则说明第二个装的变质药丸,依次类推。 3.16 比较一下C++中static_cast dynamic_cast 的区别。 (Autodesk) 。。。。。。。。。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值