互联网公司面试一般都要经历一到三轮的技术面试,那技术面试当中对于简历上的项目经历,每个应聘者应该都能详细的说出项目经历,所以手写算法就是一项很重要的考察项,闲话少说,如下列出一些面试中出现频率较高的算法。如果只为了找工作死记硬背算法题,个人感觉真的是没有太大意思,还是静下心来好好研究研究这些基础算法,对个人以后的发展还是会有帮助的。重要的是心态不要过于浮躁。
排序考察的都是内存排序,这里方法很多,但考察频率较高的首要就是快速排序、堆排序和归并排序。
快速排序:
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;
}
查找两个字符串的最大公共子串:
aocdfe、pmcdfa -> 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;
}