谷歌的电话面试都是用Google Doc敲代码,题目本身不是很难,不过想敲出bug-free还是很难的。
直接上题目
A. 链表重组
有一个链表,里面用int 存放key,现在给定一个值 val,我们重组链表,小于val的节点放在前面。并且相对顺序不能变化
- struct TreeNode{
- int value;
- TreeNode *pNext;
- };
- int ReconstructLinkedListByValue(TreeNode *head, int val){
- TreeNode *leftPart = NULL, *leftHead = NULL;
- TreeNode *rightPart = NULL, *rightHead = NULL;
- while(head){
- if(head->value > val){
- if(leftPart == NULL) leftHead = leftPart = head;
- else{
- leftPart->pNext = head;
- leftPart = head;
- }
- }
- else{
- if(rightPart == NULL) rightHead = rightPart= head;
- else{
- rightPart->pNext = head;
- rightPart= head;
- }
- }
- head = head->pNext;
- }
- if(leftHead == NULL){
- return rightHead;
- }
- else{
- leftPart.pNext = rightHead;
- return leftHead;
- }
- }
B. 小朋友拿数据
有两个小朋友,玩一个游戏,游戏的内容是:
有一个数组,只有头和尾可以取数据,一次只能取得一个,谁拿到的数据和最大谁就赢了。
现在假设两个小孩都足够聪明。你能否求出第一个小孩,取得的和是多少
分析:
首先让我想到的是动态规划,然后试图给出公式。
不管哪个小孩,我们用dp[i][j]表示第一次拿可以拿到的最优解。
因为他只有两种选择 a[i] 或者 a[j]
如果他拿了a[i] 那么剩余数组是 a[i+1, j] 因为第二个小孩也足够聪明,他从这个数组先拿,也可以拿到他的最优解 dp[i+1][j]
那么当前这个小孩,只能拿到 a[i+1, j] 的数据和减去最优解。
所以dp公式如下
- dp[i][j] = max(a[i] + sum(i+1, j) – dp[i+1][j],
- a[j] + sum(i, j-1) – dp[i][j-1]);
- 代码如下
- #define MAX_NUM 100
- int dp[MAX_NUM][MAX_NUM];
- int GetSumArray(int nums[], int sum[], int n){
- sum[0] = nums[0];
- for(int i = 1; i < n; i++){
- sum[i] = nums[i] + sum[i-1];
- }
- }
- int GetMaxSelect(int nums[], int n){
- int *sum = new int[n];
- GetSumArray(nums, sum, n);
- int i,j, k;
- for( i = 0; i < n; i++){
- dp[i][i] = nums[i];
- }
- for( k = 1; k < n; k++){
- for( i = 0; i + k < n; i++){
- j = k + i;
- dp[i][j] = max(nums[i] + (sum[j] – sum[i+1]) – dp[i+1][j],
- nums[j] + (sum[j-1] – sum[i]) – dp[i][j-1]);
- }
- }
- delete[] sum;
- return dp[0][n-1];
- }