C++面试宝典笔试题记录
2017-10-07 22:26
225 查看
链表相关的题
删除单向链表中的某个节点struct listNode{ int key; listNode* next; }; listNode* deleteNode(listNode* head, int target) { listNode* node1 = head; listNode* node2 = NULL; if (node1->key == target) // 先判断是否删除头节点 { head = head->next; free(node1); node1 = NULL; return head; } else { while (node1 != NULL) { node2 = node1; node1 = node1->next; if (node1->key != target) continue; else { node2->next = node1->next; free(node1); node1 = NULL; break; } } return head; } }
对链表进行排序
方法:每轮找出最小的数放在当前排序序列的最前面,类似于选择排序,但是交换次数比选择排序多,跟冒泡排序的次数相当。
void listSort(listNode* head) { if (head == NULL || head->next == NULL) return; listNode* p = head; listNode* q = p->next; int tmp; while (p->next!=NULL) { while (q!=NULL) { if (p->key > q->key) { tmp = p->key; p->key = q-key; q-key = tmp; } q = q->next; } p = p->next; } return head; }
使用冒泡排序算法:
void listBubbleSort(listNode* head) { if (head == NULL || head->next == NULL) return; listNode* cur = head; listNode* tail = NULL; int tmp; while (cur != tail) { while (cur->next != tail) // 内循环,每次将最大的数放 // 在本次排序的序列后面 { if (cur->key > cur->next->key) { tmp = cur->key; cur->key = cur-& de7a gt;next->key; cur->next->key = tmp; } } tail = cur; // 将tail放在已排好序的最大数的前面一个位置 cur = head; // 继续下一轮排序 } return ; }
参考博客:
http://blog.csdn.net/bitboss/article/details/51602826
链表反转
listNode* listRevert(listNode* head) { if (head == NULL || head->next == NULL) return ; listNode* p = head; listNode* q = p->next; listNode* r = NULL; p-next = NULL; while (q) { r = q->next; q->next = p; p = q; q = r; } head = p; return head; }
将两个升序排序的链表合并成一个升序排序的链表
// 使用非递归实现 listNode* Merge(listNode* head1, listNode2* head2) { // 先考虑存在空链表的情况 if (head1 == NULL) return head2; if (head2 == NULL) return head1; listNode* head = NULL; listNode* tmp = head; // 先找出新链表的表头 if (head1->key <= head2->key) { head = head1; head1 = head1->next; } else { head = head2; head2 = head2->next; } // 找到表头后移动tmp指针,注意,若移动head会使tmp同时移动,最后会找不到链表的头节点,这就是为什么要定义两个指针。 while (head1!=NULL&&head2!=NULL) { if (head1->key <= head2->key) { tmp->next = head1; tmp = head1; head1 = head1->next; } else { tmp->next = head2; tmp = head2; head2 = head2->next; } } if (head1!=NULL) tmp->next = head1; if (head2!=NULL) tmp->next = head2; return head; } // 使用递归实现 listNode* Merge2(listNode* head1, listNode* head2) { // 退出条件 if (head1 == NULL) return head2; if (head2 == NULL) return head1; listNode* head = NULL; if (head1->key <= head2->key) { head = head1; head->next = Merge2(head1->next, head2); } else { head = head2; head->next = Merge2(head1, head2->next); } return head; }
注意:对于函数的返回值,不能返回栈里的元素,也就是局部变量(函数体内定义的变量),可返回由malloc或new在堆里生成的变量,或者如上返回一个临时指针,但是该指针指向的是外部已有的一个空间,因此可以这么使用。但如果指向的是一块临时分配的栈,则不能返回该临时变量。
凑硬币
给定1分,2分,5分的硬币,问凑成1元的方案有多少种?使用for循环实现
// 凑硬币 void Coin(const int n, int money[]) { int count = 0; for (int n1 = n/money[0]; n1>=0;n1--) { for (int n2 = (n- money[0]*n1)/2; n2>=0; n2--) { cout << "5分:" << n1 << "个 " << "2分:" << n2 << "个 " << "1分:" << (n-n1*money[0]-n2*money[1]) << endl; count++; } } cout << "共" << count << "种组合。" << endl; }
使用递归实现
这里写代码片
奶牛生子问题
一只刚出生的奶牛,4年生1只奶牛,以后每一年生1只。现在给你一只刚出生的奶牛,求20年后有多少奶牛。// 奶牛生子问题 int calCowNum(const int year) { int i = 0; int sumCow = 1; for (i = 1; i <= year; i++) // 表示第一只奶牛从第一年到第二十年生子的情况 { if (i>=4) { if (year-i>3) // 如果当前生的奶牛是在第16年以内生的 sumCow += calCowNum(year - i); // 表示第一只奶牛生的奶牛,假设命名为Alice,加上Alice生的奶牛 else sumCow++; // 第17年以后生的奶牛在第20年以内不会生小奶牛 } } return sumCow; }
字符串处理问题
字符串循环移位编写一个函数,把一个char组成的字符串循环右移n位。例如,原来是“abcdefghi”,如果n=2,移位后应该是“hiabcdefg”。
备注:本题主要考察标准库函数的熟练程度,常用的有strcpy, memcpy, memset。
void LoopMove(char *pStr, int steps) { int n = strlen(pStr) - steps; char tmp[MAX_STR_LEN]; strcpy(tmp, pStr+n); strcpy(tmp+steps, pStr); tmp[strlen(pStr)] = '\0'; strcpy(pStr, tmp); }
String类的实现
编写类String的构造函数、析构函数和赋值函数。
class String { public: String(const char *str = NULL); // 普通构造函数 String(const String &other); // 拷贝构造函数 ~String(void); // 析构函数 String & operate =(const String &other); // 赋值函数 private: char *m_data; // 用于保存字符串 }; inline String::String(const char *str = NULL) // 普通构造函数 { if (str == NULL) // 若为空,则将m_data置为默认值 { m_data = new char[1]; *m_data = '\0'; } else { m_data = new char[strlen(str)+1]; // 注意这里不能用sizeof, 使用sizeof会得到指针的大小而不是数组的大小。 strcpy(m_data, str); } } inline String::String(const String &other) // 拷贝构造函数 { m_data = new char[strlen(other.m_data)+1]; //在类的成员函数内可以访问同种对象的私有成员(同种类肯定是友元关系) strcpy(m_data, other.m_data); } inline String::~String(void) // 析构函数 { delete [] m_data; } inline String::String & operate =(const String &other) // 赋值函数 { if (this == other) return *this; delete [] m_data; m_data = new char[strlen(other.data)+1]; strcpy(m_data, other.m_data); return *this; }
树遍历问题
二叉树深度优先遍历解决最大和的问题有n*n个格子,每个格子里有正数或者0,从最左上角望最右下角走,只能向下和向右,把所有经过的格子的数加起来,求最大值SUM。
DP算法,将问题分解成子问题,求局部最优解,计算从a[0][0]到a[n-1][n-1]的最大和问题,即为求a[0][1]和a[1][0]到a[n-1][n-1]的最大的和的问题。代码如下:
#include <iostream> using namespace std; const int N = 4; // 二维数组形参还可以为int arr[] 或者int (*arr) ; // 这里行数可以不说明,但是列数必须说明,因为如果省略了第二维或者更高维的大小,编译器将不知道如何正确的寻址。 int MaxSum(int arr , int row, int col) { if (row == N || col == N) return 0; // 这里分解成两个子问题求解 int temp1 = MaxSum(arr, row+1, col) + arr[row][col]; int temp2 = MaxSum(arr, row, col+1) + arr[row][col]; // 返回两个子问题中的最大和 return temp1 > temp2 ? temp1 : temp2; } int main() { int arr[4][4] = {{0,0,0,4},{0,3,0,0},{5,0,0,9},{0,0,2,1}}; cout << MaxSum(arr, 0, 0); return 0; }
> 上题,如何增加hash表来保存中间结果,避免重复递归还未写。
返回无序数组排序后的最大差值
请设计一个复杂度为O(n)的算法,计算一个未排序数组中排序后相邻元素的最大差值。给定一个数组的大小n和整数数组A,请返回最大差值。保证数组元素个数大于等于2,小于等于500。输入示例:
4
9 3 1 10
输出示例:
6
要求时间复杂度为O(n),则不能直接进行排序来做。
相关文章推荐
- C++笔试面试宝典总结
- C++笔试面试宝典总结
- C++笔试面试宝典总结
- 面试笔试记录:C++
- C/C++ 笔试、面试题目
- 华为--C++ 笔试面试题目
- 面试宝典之阿里巴巴2014校园招聘笔试题
- [互联网面试笔试汇总C/C++-10] 糖果拆包-美团
- C/C++ 笔试、面试题目大汇总2
- [转]java面试笔试题大汇总 及c/c++面试试题
- 1005_C/C++笔试题_14:16道c语言面试【10/11/12】
- [C/C++] C/C++ 笔试、面试题目大汇总
- [互联网面试笔试汇总C/C++-6] 迅雷
- C/C++ 笔试、面试题目大汇总(二)
- [转]腾讯研发类笔试面试试题(C++方向)
- C/C++笔试、面试题目大汇总 Visual C++常见面试题 王牌7
- 【面试笔试-c/c++】2012年9月土豆优酷网校园招聘笔试
- C/C++ 笔试、面试题目大汇总1
- C/C++ 笔试、面试题目大汇总(转)
- C++笔试面试答题(一)