机试——华为

需要识记的点

1、qsort
void qsort(void * base, int num_elem, int size_elem, int (fcmp)(const void ,const void *));
参数:
1 待排序数组首地址
2 数组中待排序元素数量
3 各元素的占用空间大小
4 指向函数的指针,用于确定排序的顺序 int comp(const void , const void)

int comp(const void *a,const void *b)
{
    return *(int*)a - *(int*)b;  //由小到大排序
}

2、sort排序

#include <algorithm>
bool vector_int_cmp(int a, int b)
{
    return (b<a);   //升序
}
sort(v.begin(), v.end(),vector_int_cmp);

3、C++

string::iterator it;
getline(cin,s);
int *arry = new int[n];
vector<int> v(ch_array, ch_array+WORD_CNT);   //数组array赋值到vector中

str2 = str.substr(3,5);

4、C

    char str[128];
    fgets(str,128,stdin);
    puts(str);

     char*p;
    p=strtok(input,",");
    p=strtok(NULL,",");

//比较字符串大小 从小到大
int cmp_string(const void *a,const void *b)
{
    return strcmp((char *)a,(char *)b);
}

一、过滤字符(60分):

通过键盘输入一串小写字母(a~z)组成的字符串。请编写一个字符串过滤程序,若字符串中出现多个相同的字符,将非首次出现的字符过滤掉。
比如字符串“abacacde”过滤结果为“abcde”。

要求实现函数:void stringFilter(const char *pInputStr, long lInputLen, char *pOutputStr);

【思路】
用一个hash表,bool hash[26] = {0};对应26个字母是否在pInputStr出现与否,这样就不要再增加一个FOR循环,在pOutputStr从头遍历一遍pInputStr是否在pOutputStr中出现过了。
bool hash[26] = {0}; 表示首先都没有出现过,随着往pOutputStr加数据,将对应的hash表中的对应字母置1。

二、四则运算匹配

输入一个只包含个位数字的简单四则运算表达式字符串,计算该表达式的值
注: 1、表达式只含 +, -, *, /, (, ), 四则运算符
2、表达式数值只包含个位整数(0-9),且不会出现0作为除数的情况
3、要考虑加减乘除按通常四则运算规定的计算优先级
4、除法用整数除法,即仅保留除法运算结果的整数部分。比如8/3=2。输入表达式保证无0作为除数情况发生
5、输入字符串一定是符合题意合法的表达式,其中只包括数字字符和四则运算符字符,除此之外不含其它任何字符,不会出现计算溢出情况
• 要求实现函数:
int calculate(int len,char *expStr)
【输入】 int len: 字符串长度;
char *expStr: 表达式字符串;
【输出】 无
【返回】 计算结果

• 示例
1) 输入:char *expStr = “1+4*5-8/3”
函数返回:19
2) 输入:char *expStr = “8/3*3”
函数返回:6

——————————————————————————————————————————————————
① 将中缀表达式解析成后缀表达式
中缀表达式翻译成后缀表达式的方法如下:
(1)从右向左依次取得数据ch,需要一个运算符栈op_stack,输出的后缀表达式缓存suffix。
(2)如果ch是操作数,直接输出给suffix。
(3)如果ch是运算符(含左右括号),则:
a:如果ch = ‘(‘,压栈。
b:如果ch = ‘)’,依次输出栈中的运算符,直到遇到’(‘为止,并弹出’(‘。
c:如果ch不是’)’或者’(‘,那么就和op_stack栈顶点运算符top做优先级比较。
1:如果ch优先级比top高,那么将ch入栈(来的优先级高,入栈)。
2:如果ch优先级低于或者等于top,那么输出top,然后将ch入栈(来的优先级不高,输出栈顶,将来的ch压栈)。
(4)如果表达式已经读取完成,而op_stack栈中还有运算符时依次由顶端输出
如果我们有表达式(A-B)*C+D-E/F,要翻译成后缀表达式,并且把后缀表达式存储在一个名叫output的字符串中,可以用下面的步骤。

(1)读取’(‘,压入堆栈,output为空
(2)读取A,是运算数,直接输出到output字符串,output = A
(3)读取’-‘,此时栈里面只有一个’(‘,因此将’-‘压入栈,output = A
(4)读取B,是运算数,直接输出到output字符串,output = AB
(5)读取’)’,这时候依次输出栈里面的运算符’-‘,然后就是’(‘,直接弹出,output = AB-
(6)读取’*’,是运算符,由于此时栈为空,因此直接压入栈,output = AB-
(7)读取C,是运算数,直接输出到output字符串,output = AB-C
(8)读取’+’,是运算符,它的优先级比’‘低,那么弹出’‘,压入’+”,output = AB-C*
(9)读取D,是运算数,直接输出到output字符串,output = AB-C*D
(10)读取’-‘,是运算符,和’+’的优先级一样,因此弹出’+’,然后压入’-‘,output = AB-C*D+
(11)读取E,是运算数,直接输出到output字符串,output = AB-C*D+E
(12)读取’/’,是运算符,比’-‘的优先级高,因此压入栈,output = AB-C*D+E
(13)读取F,是运算数,直接输出到output字符串,output = AB-C*D+EF
(14)原始字符串已经读取完毕,将栈里面剩余的运算符依次弹出,output = AB-C*D+EF/-

② 后缀表达式的求值
从左到右扫描后缀表 达式,遇到运算符就把表达式中该运算符前面两个操作数取出并运算,然后把结果带回后缀表达式;继续扫描直到后缀表达式最后一个表达式。
设置一个操作数栈,开始时,栈为空,然后从左到右扫描后缀表达式suffix。
若遇操作数,则进栈;
若遇运算符,则从栈中退出两个元素,先退出的放到运算符的右边,后退出的 放到运算符左边,运算后的结果再进栈,直到后缀表达式扫描完毕。此时,栈中仅有一个元素,即为运算的结果。

int calculate(int len,char *expStr)
{
    char *suffix = new char[len];
    char *op_stack = new char[len];
    int op_top = 0,j=0;

    //先将中缀表达式转换为后缀表达式
    for(int i=0; i<len; ++i)
    {       
        if(is_digit(expStr[i]))    //如果为操作数直接输出
        {
            suffix[j++] = expStr[i];
        }
        else  //操作符
        {
            if(expStr[i] == '(' || !op_top)
            {
                op_stack[op_top++] = expStr[i];
            }
            else if(expStr[i] == ')')
            {
                //将操作栈栈顶元素~ '('之间的操作符出栈输出
                while(op_top && op_stack[op_top-1] != '(')
                {
                    suffix[j++] = op_stack[--op_top];
                }
                op_top--;  //将( 出栈
            }
            else if(priority(expStr[i],op_stack[op_top-1]) == 1)  //来的优先级> 栈顶
            {
                op_stack[op_top++] = expStr[i];
            }
            else if(priority(expStr[i],op_stack[op_top-1]) != 1)     //来的优先级<= 栈顶
            {
                suffix[j++] = op_stack[--op_top]; 
                op_stack[op_top++] = expStr[i];
            }           
        }           
    }
    while(op_top)
    {
        suffix[j++] = op_stack[--op_top];
    }

    //由后缀表达式求值
    int *dig_stack = new int[len];
    int dig_top = 0,a,b;

    for(int i=0; i<j; ++i)
    {
        if(is_digit(suffix[i]))
        {
            dig_stack[dig_top++] = suffix[i] - '0';
        }
        else
        {
            a = dig_stack[--dig_top];
            b = dig_stack[--dig_top];           
            dig_stack[dig_top++] = cal(b,a,suffix[i]);
        }
    }
    return dig_stack[--dig_top];
}

三、链表翻转

给出一个链表和一个数k,比如链表1→2→3→4→5→6,k=2,则翻转后2→1→4→3→6→5,若k=3,翻转后3→2→1→6→5→4,若k=4,翻转后4→3→2→1→5→6,用程序实现。

对reverse的解释如下图:
机试——华为_第1张图片

typedef struct _node
{
    int data;
    struct _node * next;
}node;

//翻转start后一位~end位置的链表
//返回end的指针
node * reverse(node **pre_start, node **end)
{
    assert(end || pre_start);    
    node *start,*after_end;
    node *p,*pre,*tmp;

    start = (*pre_start)->next;
    if(start == *end)  //only one node need not reverse
        return;
    after_end = (*end)->next;
    pre = start;
    p = pre->next;
    *end = start;

    while(p != after_end)
    {
        //将p插入到pre_start的后面
        pre->next = p->next;
        p->next = start;
        (*pre_start)->next = p;
        start = p;
        p = pre->next;
    }

    (*end)->next = after_end;

    return *end;
}

//main函数中的处理
    p = head;
    while(p)
    {
        //找到需要翻转的尾节点P2
        tmpk = k;
        p2 = p->next; 
        while(tmpk>1 && p2)
        {
            p2 = p2->next;
            tmpk --;
        }
        if(!p2)
        {
            break;
        }

        p = reverse(&p,&p2);                   
    }

四、字符串整数相减

输入两行字符串正整数,第一行是被减数,第二行是减数,输出第一行减去第二行的结果。
备注:1、两个整数都是正整数,被减数大于减数
示例:
输入:1000000000000001
1
输出:1000000000000000
解析:a-b
1:保证a>b
若a

你可能感兴趣的:(机试——华为)