练习系列 - 9、微软实习面试题

/*!
\author LiuBao
\date 2011/4/12
\brief 微软实习面试题
*/
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
 
#define ARRAY_SIZE(array)   \
    (sizeof(array) / sizeof(array[0]))
 
typedef struct BTree BTree;
 
struct BTree
{
    BTree *left;
    BTree *right;
    int value;
};
 
typedef struct Node Node;
 
struct Node
{
    Node *next;
    int value;
};
 
/*!
考察算法1
原意是要用最快方法,在可重复元素的排序数组中,寻找一个值的出现次数,
这个问题可以归结为用最快方法寻找该值的出现在数组中的最小下标。由此,
衍生出本题。
在可重复元素排序数组array中,dest出现的数组下标最小值。
1、若dest大于数组最大值,返回n
2、若dest小于等于数组最小值,返回0
3、否则,若dest在数组中不存在,返回大于dest的元素的数组下标最小值
\note 真不知道如此不确定性为的函数有啥用?
\param array 可能具有可重复元素的排序数组
\param n 数组元素个数
\param dest 查找元素值
\return 查找结果(下标值)
*/
int low_bound(const int array[], int n, int dest)
{
    int retVal = -1;
 
    if(array[n - 1] < dest)
        retVal = n;
    else if(array[0] >= dest)
        retVal = 0;
    else
    {
        int low = 0;
        int high = n - 1;
        int mid;
 
        while(low <= high)
        {
            mid = (low + high) / 2;
 
            if(array[mid] < dest)
                low = mid + 1;
            else
                high = mid - 1;
        }
 
        retVal = high + 1;
    }
 
    return retVal;
}
 
/*!
辅助函数1
用int数组内元素创建一个单向链表
\param array 用于创建链表的数组
\param n 数组元素个数
\return 若创建成功,返回链表头指针;否则返回NULL
*/
Node *create_link(const int *array, int n)
{
    Node *head = NULL;
    Node **p = &head;
 
    while(n-- && (*p = malloc(sizeof(Node))))
    {
        (*p)->value = *array++;
        p = &(*p)->next;
    }
 
    *p = NULL;
 
    return head;
}
 
/*!
考察算法2
查找单向链表head的倒数第n个节点,最末个节点记为倒数第1个
\param head 查找单向链表的头指针
\param n 查找倒数节点序号
\return 查找成功返回该节点指针;否则返回NULL
*/
Node *find_backwards(Node *head, int n)
{
    Node *pre = head;
 
    while(n-- && head) head = head->next;
    while(head) pre = pre->next, head = head->next;
 
    return (!n && head) ? NULL : pre;
}
 
/*!
辅助函数2
插入节点到排序二叉树中
\param root 排序二叉树根节点,可以为NULL
\param val 插入的值
\return 返回成功插入的节点指针
*/
BTree *insert_node(BTree *root, int val)
{
    BTree **p = &root;
 
    while(*p)
    {
        if((*p)->value < val)
            p = &(*p)->right;
        else
            p = &(*p)->left;
    }
 
    if((*p = calloc(sizeof(BTree), 1)))
        (*p)->value = val;
 
    return *p;
}
 
/*!
考察算法3
验证一颗树是否为排序二叉树
\param root 树根
\return 若是排序二叉树,返回真;否则返回假
*/
int is_sort_tree(BTree *root)
{
    static int pre = INT_MIN;
    static int success = 1;
 
    if(root && success)
    {
        is_sort_tree(root->left);
 
        if(pre <= root->value)
            pre = root->value;
        else
            success = 0;
 
        is_sort_tree(root->right);
    }
 
    return success;
}
 
int main()
{
    int array[] = {2, 2, 3, 6, 6, 8, 9, 9};
 
    /* 测试算法1 */
    printf("low bound: %d\n", low_bound(array, ARRAY_SIZE(array), 7));
 
    /* 测试算法2 */
    {
        Node *link = create_link(array, ARRAY_SIZE(array));
        Node *found;
 
        if((found = find_backwards(link, 6)))
            printf("found backwards: %d\n", found->value);
    }
 
    /* 测试算法3 */
    {
        int array[] = {4, 3, 5, 7, 6, 9};
        BTree *root = insert_node(NULL, 6);     //创建树根
        int i;
 
        for(i = 0; i < ARRAY_SIZE(array); ++i)  //创建排序二叉树
            insert_node(root, array[i]);
 
        insert_node(root->left, 7);             //可以用来破坏排序二叉树
 
        printf("test result : %d\n", is_sort_tree(root));
    }
 
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值