互联网公司面试算法总结

互联网公司面试算法总结

互联网公司面试一般都要经历一到三轮的技术面试,那技术面试当中对于简历上的项目经历,每个应聘者应该都能详细的说出项目经历,所以手写算法就是一项很重要的考察项,闲话少说,如下列出一些面试中出现频率较高的算法。如果只为了找工作死记硬背算法题,个人感觉真的是没有太大意思,还是静下心来好好研究研究这些基础算法,对个人以后的发展还是会有帮助的。重要的是心态不要过于浮躁。

排序考察的都是内存排序,这里方法很多,但考察频率较高的首要就是快速排序、堆排序和归并排序。

快速排序:

int partion(int array[], int start, int end)

{

    int arr_start, arr_end, arr_major;

 

    if (!array || start < 0 || end < 0 || start > end) {

        return -1;

    }

 

    arr_start = start;

    arr_end = end;

    arr_major = array[arr_start];

 

    while (arr_start < arr_end) {

        while (arr_start < arr_end && array[arr_end] >= arr_major)

             arr_end--;

        if (arr_start < arr_end) {

             array[arr_start] = array[arr_end];

             arr_start++;

       }

 

       while (arr_start < arr_end && array[arr_start] < arr_major)

           arr_start++;

      if (arr_start < arr_end) {

          array[arr_end] = array[arr_start];

          arr_end--;

      }

    }

 

    array[arr_start] = arr_major;

 

    return arr_start;

}

 

void quick_sort(int array[], int start, int end)

{

    int mid = 0;

 

    if (!array || start < 0 || end < 0 || start > end) {

        return;

    }

 

    mid = partion(array, start, end);

    if (mid == -1) {

        return;

    }

 

    quick_sort(array, start, mid - 1);

    quick_sort(array, mid + 1, end);

 

    return;

}

堆排序:

void heapAdjust(int array[], int node, int length)

{

    int lchild;

    int exchange;

 

    if (!array)

        return;

 

    for (; 2*node + 1 < length; node = lchild) {

        lchild = 2*node + 1;

 

        if (lchild < length - 1 && array[lchild + 1] > array[lchild])

            ++lchild;

 

       if (array[node] < array[lchild]) {

           exchange = array[node];

           array[node] = array[lchild];

           array[lchild] = exchange;

       } else {

           break;

      }

    }

 

    return;

}

 

void heapSort(int array[], int length)

{

    int i;

 

    for (i = length/2 - 1; i >= 0; --i)

        heapAdjust(array, i, length);

 

    for (i = length - 1; i > 0; --i) {

         array[i] = array[0] ^ array[i];

         array[0] = array[0] ^ array[i];

         array[i] = array[0] ^ array[i];

        heapAdjust(array, 0, i);

    }

 

    return;

}

归并排序:

void merge(int array[], int low, int mid, int high)

{

    int i = low, j = mid + 1, p = 0;

    int *arr = NULL;

 

    if (!array)

        return;

 

    arr = (int *)malloc((high - low + 1)*sizeof(int));

    if (!arr)

        return;

 

    while (i <= mid && j <= high) {

        arr[p++] = (array[i] <= array[j])?array[i++]:array[j++];

    }

    while (i <= mid) {

        arr[p++] = array[i++];

    }

    while (j <= high) {

        arr[p++] = array[j++];

    }

 

    for (p = 0, i = low; i <= high; p++, i++) {

        array[i] = arr[p];

    }

 

    free(arr);

 

    return;

}

 

void mergeSort(int array[], int low, int high)

{

    int mid;

 

    if (low >= high) {

        return;

    }

 

    mid = (low + high) / 2;

    mergeSort(array, low, mid);

    mergeSort(array, mid + 1, high);

    merge(array, low, mid, high);

 

    return;

}

二分查找:

int binarySearch(int array[], int num, int high)

{

    int mid = 0;

    int left = 0;

    int right = high - 1;

 

    while (left <= right) {

        mid = (left + right) / 2;

        if (num < array[mid])

            right = mid;

       else if (num > array[mid])

           left = mid;

       else

           return mid;

    }

 

    return -1;

}

 

int recursiveBinarySearch(int array[], int num, int low, int high)

{

    int mid = (low + high) / 2;

 

    if (low > high)

        return -1;

 

    if (num < array[mid])

        high = mid - 1;

    else if (num > array[mid])

        low = mid + 1;

 

    if (array[mid] == num)

        return mid;

 

    return recursiveBinarySearch(array, num, low, high);

}

链表操作,出现频率较高的包括单链表反转,单链表元素两两反转,判断单链表有环等。

单链表反转:

list *reverseList(list *head)

{

    list *next = NULL;

    list *p = NULL, *pNew = NULL;

 

    if (head == NULL || head->next == NULL)

    return head;

 

    p = head;

 

    while (p != NULL) {

        next = p->next;

        p->next = pNew;

        pNew = p;

        p = next;

    }

 

    return pNew;

}

链表两两反转:

A->B->C->D->E->F->G->H->I

B->A->D->C->F->E->H->G->I

list *reverseListInPair(list *head)

{

    list *pHead = NULL;

    list *current = NULL;

    list *preNode = NULL;

    list *nextNode = NULL;

    list *nextNextNode = NULL;

 

    if (head == NULL || head->next == NULL)

        return head;

 

    current = head;

    pHead = head->next;

 

    while (current != NULL && current->next != NULL) {

        nextNode = current->next;

        nextNextNode = nextNode->next;

 

        nextNode->next = current;

        current->next = nextNextNode;

        if (preNode != NULL) {

            preNode->next = nextNode;

        }

        preNode = current;

        current = nextNextNode;

    }

 

    return pHead;

}

单链表是否有环:

思路:如果给出一个单链表,如何在一次遍历的情况下找出这个单链表的中间结点?

树的操作:树的层序遍历、前序遍历、中序遍历、后续遍历、二叉树的深度、二叉树是否为平衡二叉树、二叉树的最大路径和。

typedef struct __BiTreeNode {

    char data;

    struct BiTreeNode *lchild;

    struct BiTreeNode *rchild;

}BiTreeNode, *BiTree;

创建二叉树:

BiTree createBiTree()

{

    char ch;

    BiTree T = NULL;

 

    scanf("%c", &ch);

 

    if (ch == '#') {

        T = NULL;

    } else {

        T = (BiTreeNode *)malloc(sizeof(BiTreeNode));

        if (!T) {

            return NULL;

        }

        T->data = ch;

        T->lchild = createBiTree();

        T->rchild = createBiTree();

    }

 

    return T;

}

可以输入:abd##e##cf##g##

层序遍历:

int printLevelTree(BiTree T)

{

    BiTree p = NULL, last = NULL, nlast = NULL;

    QUEUE queue;

 

    if (!T) {

        return 0;

    }

 

    queue.push(T);

    last = T;

 

    while (!queue.empty()) {

        p = queue.pop();

        printf("%c", p->data);

 

        if (p->lchild) {

            queue.push(p->lchild);

            nlast = p->lchild;

        }

 

        if (p->rchild) {

            queue.push(p->rchild);

            nlast = p->rchild;

        }

 

        if (p == last) {

            printf("\n");

            last = nlast;

        }

    }

 

    return 1;

}

先序遍历递归算法:

int PreOrderRecursionTraverse(BiTree T)

{

    if (!T) {

        return 0;

    }

 

    printf("%c\n", T->data);

    PreOrderRecursionTraverse(T->lchild);

    PreOrderRecursionTraverse(T->rchild);

 

    return 0;

}

中序遍历递归算法:

int InOrderRecursionTraverse(BiTree T)

{

    if (!T) {

        return 0;

    }

 

    PreOrderRecursionTraverse(T->lchild);

    printf("%c\n", T->data);

    PreOrderRecursionTraverse(T->rchild);

 

    return 0;

}

后序遍历递归算法:

int PostOrderRecursionTraverse(BiTree T)

{

    if (!T) {

        return 0;

    }

 

    PreOrderRecursionTraverse(T->lchild);

    PreOrderRecursionTraverse(T->rchild);

    printf("%c\n", T->data);

 

    return 0;

}

先序遍历非递归算法:

int PreOrderNonRecursionTraverse(BiTree T)

{

    STACK stack;

    BiTree p;

 

    if (!T) {

        return 0;

    }

 

    stack.push(T);

 

    while (!stack.empty()) {

        p = stack.pop();

        printf("%c\n", p->data);

 

        if (p->rchild) {

            stack.push(p->rchild);

        }

        if (p->lchild) {

            stack.push(p->lchild);

        }

    }

 

    return 1;

}

中序遍历非递归算法:

int InOrderNonRecursionTraverse(BiTree T)

{

    STACK stack;

    BiTree p;

 

    if (!T) {

        return 0;

    }

 

    p = T;

 

    while (p || !stack.empty()) {

        if (p) {

            stack.push(p);

            p = p->lchild;

        } else {

            p = stack.pop();

            printf("%c\n", p->data);

            p = p->rchild;

        }

    }

 

    return 1;

}

后序遍历非递归算法:

int PostOrderNonRecursionTraverse(BiTree T)

{

    STACK stack;

    BiTree p;

 

    if (!T) {

        return 0;

    }

 

    p = T;

 

    while (p != NULL || !stack.empty()) {

        while (p != NULL) {

            stack.push(p);

            p->flag = 0;

            p = p->lchild;

        }

 

        p = stack.getTop();

        while (!stack.empty() && p->flag == 1) {

            p = stack.pop();

            printf("%c\n", p->data);

            p = stack.getTop();

        }

 

        if (!stack.empty()) {

            p = stack.getTop();

            p->flag = 1;

            p = p->rchild;

        } else {

            break;

        }

    }

 

    return 1;

}

二叉树的深度:

int treeDepth(BiTree T)

{

    int nLeft, nRight;

 

    if (!T) {

        return 0;

    }

 

    nLeft = treeDepth(T->lchild);

    nRight = treeDepth(T->rchild);

 

    return (nLeft > nRight) ? (nLeft + 1) : (nRight + 1);

}

二叉树是否为平衡二叉树:

int isBalancedBinaryTree(BiTree T, int *depth)

{

    int left, right, diff;

 

    if (!T) {

        *depth = 0;

        return 1;

    }

 

    if (isBalancedBinaryTree(T->lchild, &left) && \

        isBalancedBinaryTree(T->rchild, &right)) {

        diff = left - right;

        if (diff <= 1 && diff >= -1) {

            *depth = 1 + (left > right ? left : right);

            return 1;

        }

    }

 

    return 0;

}

二叉树的最大路径和:

int binaryTreeMaxPathSum(BiTree T, int *curMax)

{

    int maxLeft = 0, maxRight = 0, maxValue = 0;

    int temp;

 

    if (!T) {

        return 0

    }

 

    maxLeft = binaryTreeMaxPathSum(T->lchild, curMax);

    maxRight = binaryTreeMaxPathSum(T->rchild, curMax);

    temp = (0 > maxLeft ? 0 : maxLeft) + (0 > maxRight ? 0 : maxRight) + T->data;

    curMax = curMax > temp ? curMax : temp;

 

    return (0 > (maxRight > maxLeft ? maxRight : maxLeft) ? 0 : \

        (maxRight > maxLeft ? maxRight : maxLeft)) + T->data;

}

其他问题:全排列、连续子数组的最大和、查找两个字符串的最大公共子串

全排列(动态规划问题):

void swap(int *a, int *b)

{

    int temp;

 

    temp = *a;

    *a = *b;

    *b = temp;

}

 

void fullPermutation(int array[], int begin, int end)

{

    int i;

 

    if (!array) {

        return;

    }

 

    if (begin > end) {

        for (i = 0; i < end; i++) {

            printf("%d", array[i]);

        }

        printf("\n");

    } else {

        for (i = begin; i < end; i++) {

            swap(&array[begin], &array[i]);

            fullPermutation(array, begin + 1, end);

            swap(&array[begin], &array[i]); //回溯时还原

        }

    }

 

    return;

}

连续子数组的最大和:

{1, -2, 3, 10, -4, 7, 2, -5}

int findGreatestSumOfSubArray(int array[], int length)

{

    int i;

    int cSum = 0;

    int result;

 

    if (!array) {

        return -1;

    }

 

    result = array[0];

 

    for (i = 0; i < length; ++i) {

        if (cSum < 0) {

            cSum = array[i];

        } else {

            cSum += array[i];

        }

 

        if (cSum > result) {

            result = cSum;

        }

    }

 

    return result;

}

查找两个字符串的最大公共子串:

aocdfepmcdfa -> cdf

void subStr(char *s1, char *s2)

{

    int i, j, m = 0;

    in p, q;

    int len1, len2;

    char a[100] = {0};

    char b[100] = {0};

 

    if (!s1 || !s2) {

        return;

    }

 

    len1 = strlen(s1) <= strlen(s2) ? strlen(s1) : strlen(s2);

    len2 = strlen(s1) <= strlen(s2) ? strlen(s2) : strlen(s1);

 

    for (i = 0; i < len1; i++) {

        for (j = 0; j < len2; j++) {

            strcpy(a, "0");

            p = i;

            q = j;

            while (s1[p] == s2[q] && s1[p] != 0) {

                a[m] = s2[q];

                p++;

                q++;

                m++;

            }

            if (strlen(a) > strlen(b)) {

                strcpy(b, a);

            }

            m = 0;

        }

    }

 

    printf("max sub str:%s\n", b);

 

    return;

}

你可能感兴趣的:(互联网公司面试算法总结)