前幾天我有幸收到亞馬遜在線筆試邀請,於是今天上午准時參加了筆試。
共2道算法編程題,由於是第一次參加這種筆試,即便是在線,由於時間限制,難免會緊張。
總共限時為2.5h,完成第一道題就花了2h,第2道題因此也沒有完成了,遺憾+慚愧!
下面給出第一道題的解答。
題目如下:
Question:
Given an array with positive integers and another integer for example{7 2 4} 9, you are required to generate an equation, by inserting operator add ("+") and minus ("-") among the array . The left side of equation are consist of the array and the right side of equation is the integer. here the result is 7-2+4=9
Rules:
Don't include any space in the generated equation.
In case there is no way to create the equation, please output "Invalid". For example {1 1} 10, output is "Invalid"
The length of the integer array is from 1 to 15( include 1 and 15). If the length is 1, for example the input {7} 7, the output is 7=7
There is no operator "+" or "-" in front of the first number:
Don't change the order of the numbers. For example: {7 2 4} 9. 7-2+4=9 is correct answer, 4-2+7=9 is wrong answer.
There could be multiple input, meaning your function could be called multiple times. Do remember print a new line after the call.
Sample Input and Output:
Input:
1 2 3 4 10
1 2 3 4 5
Output:
1+2+3+4=10
Invalid
---------------------------
#include <iostream>
#include <cstring>
using namespace std;
/* ********************************************************************** */
/* *
Args:
array[]: the inputted array
final: the target value
length: the element length
*/
void createEquationAndPrint( int array[], int length, int final){
// Your Code is here
cout<< " Invalid ";
}
int splitAndConvert( char* strings, int array[]){
char*tokenPtr = strtok(strings, " ");
int i= 0;
while(tokenPtr!=NULL){
array[i] = atoi(tokenPtr);
i++;
tokenPtr=strtok(NULL, " ");
}
return i;
}
int main(){
char line[ 1000] = { 0} ;
while(gets(line)){
int array[ 30] = { 0};
int length = splitAndConvert(line,array);
if(length== 0){
break;
}
createEquationAndPrint(array, length- 1, array[length- 1]);
cout<<endl;
}
return 0;
}
很明顯,題目要求填寫函數createEquationAndPrint的具體實現過程。
分析:這道題,咋一看來,應該屬於類似全排列的題型,一般需要用遞歸的思路來解決。但在線筆試不允許添加額外、單獨的函數作為遞歸函數,所以最終放棄了該思路,采用循環才完成全排列的遍歷。
我當時在線的函數設計如下:
// Your Code is here
if(!array || length< 0)
return;
bool found = false;
int i = 0;
char *opera = new char[length+ 1];
while(i<length+ 1)
{
opera[i++] = ' + ';
}
opera[length] = ' = ';
int *array_bak = new int[length+ 1];
i = 0;
while(i<length+ 1)
{
array_bak[i] = array[i];
i++;
}
int allSum = 0;
i = 0;
while(i<length) // all number except the final one
{
allSum += array[i];
i++;
}
if(allSum < final)
{
found = false;
cout<< " Invalid ";
}
else if(allSum == final)
{
found = true;
i = 0;
while(i<length)
{
opera[i] = ' + ';
i++;
}
opera[length] = ' = ';
cout << array_bak[ 0];
i = 1;
while(i<length+ 1)
cout << opera[i] << array_bak[i++];
// cout << endl;
}
else
{
int k = 1;
while(k < length)
{
int currNum = array[k];
if(currNum == 0)
{
k++;
continue;
}
if(allSum- 2*currNum < final)
{
k++;
continue;
}
else if(allSum- 2*currNum == final)
{
found = true;
opera[k] = ' - ';
cout << array_bak[ 0];
int j = 1;
while(j<length+ 1)
cout << opera[j] << array_bak[j++];
// cout << endl;
k++;
continue;
}
else
{
allSum -= 2*currNum;
array[k] = 0;
opera[k] = ' - ';
k = 0;
continue;
}
}
}
delete opera;
delete array_bak;
if(found)
return;
else
cout<< " Invalid ";
}
本地測試時,嘗試了多種不同的測試用例,沒有發現問題,結果提交在線測試,各種問題,由於時間關系,沒有來得及找到問題原因,匆匆提交~
后來筆試結束后,下來跟同學討論了下,發現了當時在線設計的算法考慮不周全,存在很多問題,於是重新考慮本題的設計。
還是想使用遞歸來實現,主要在於代碼可能會比較精簡。但遞歸過程中,可能需要保存很多中間變量。之前看過的一些算法設計題,一般都是通過函數參數傳遞引用來保存,但這里已經限定了遞歸函數的形式,所以最終采用靜態全局變量來進行解決。由於遞歸的過程也是一個壓棧、出棧的操作過程,因此基於棧來保存中間變量也不是沒有可能。這個思路暫時沒有實現。
下面給出這種思路的解法:
2 // Your Code is here
3 static int sum = 0;
4 static bool found = false;
5 static char *print_str = new char[ 31];
6 static int origin_length = length;
7 static int recur_times = 0;
8
9 if(recur_times == 0)
10 {
11 sum = 0;
12 found = false;
13 origin_length = length;
14 }
15
16 recur_times++;
17
18 if(length == 1) // if only one element
19 {
20 if(array[ 0] == final)
21 {
22 sprintf(print_str, " %d=%d ", array[ 0], final);
23 found = true;
24 cout << print_str << endl;
25 }
26 }
27 else if(length > 2) // when many elements for add/minor
28 {
29 if(length == origin_length)
30 {
31 sum = array[ 0];
32 sprintf(print_str, " %d ", array[ 0]);
33 }
34
35 int curr = array[origin_length-length+ 1];
36
37 int temp_sum = sum;
38 char *temp_str = new char[ 31];
39 strcpy(temp_str, print_str);
40
41 sum = temp_sum + curr;
42 sprintf(print_str, " %s+%d ", temp_str, curr);
43 createEquationAndPrint(array, length- 1, final);
44
45 sum = temp_sum - curr;
46 sprintf(print_str, " %s-%d ", temp_str, curr);
47 createEquationAndPrint(array, length- 1, final);
48
49 delete temp_str;
50 }
51 else if(length == 2) // when only one element for add/minor
52 {
53 if(sum + array[origin_length-length+ 1] == final)
54 {
55 sprintf(print_str, " %s+%d=%d ", print_str, array[origin_length- 1], final);
56 found = true;
57 cout << print_str << endl;
58 }
59 else if(sum - array[origin_length-length+ 1] == final)
60 {
61 sprintf(print_str, " %s-%d=%d ", print_str, array[origin_length- 1], final);
62 found = true;
63 cout << print_str << endl;
64 }
65 }
66
67 if(length == origin_length)
68 {
69 if(!found)
70 cout << " Invalid " << endl;
71
72 recur_times = 0;
73 }
74
75 return;
76 }
個人覺得,目前的實現應該沒有什么漏洞了,但整體代碼還是比較復雜,應該有更簡潔的設計方式,期待大家的集體智慧~~
至於第2道題,題目如下:
Question:
There is a 5*5 matrix; the elements in this matrix are different integer from 0 to 24. The elements in this matrix are disordered. 0 is a special element. The upper element, under element, left element and right element of 0 can be exchanged with 0. Such exchange operations are named as ‘U’, ‘D’, ‘L’ and ‘R’.
Operation "U" means 0 exchanged with its upper element.
Operation "D" means 0 exchanged with its under element.
Operation "L" means 0 exchanged with its left element.
Operation "R" means 0 exchanged with its right element.
For example, the original matrix is
[20, 18, 7, 19, 10
24, 4, 15, 11, 9
13, 0, 22, 12, 14
23, 16, 1, 2, 5
21, 17, 8, 3, 6]
With the operation sequence “URRDDL”, the new matrix will be
[20, 18, 7, 19, 10
24, 15, 11, 12, 9
13, 4, 22, 2, 14
23, 16, 0, 1, 5
21, 17, 8, 3, 6]
Now, we know the original matrix, the matrix after the operations and all the operations made on the original matrix. Please provide the correct sequence for the operations.
The input will be the original matrix, the target matrix and an operation sequence with wrong order.
If there is a correct sequence for this input, then print the correct sequence. Otherwise, print “None”.
Rules and example:
The elements in the original matrix are different.
The elements in the original matrix are random ordered.
The max lenght of operatoins is 15.
If "0" is already on the boundary, it is not possible to do further movement. for example, if 0 is in the top row, then there is no more "U".
The input will be the original matrix, the target matrix and an operation sequence with wrong order.
The output will be a correct operation sequence.
In case there is no way to get the target matrix with the input operations, please output “None”
Don’t include any space in the generated operation sequence.
For examples, the original matrix is
Example 1:
[20, 18, 7, 19, 10
24, 4, 15, 11, 9
13, 0, 22, 12, 14
23, 16, 1, 2, 5
21, 17, 8, 3, 6]
The target matrix is
[20, 18, 7, 19, 10
24, 4, 0, 11, 9
13, 22, 15, 12, 14
23, 16, 1, 2, 5
21, 17, 8, 3, 6]
The input operation sequence is “UR”
The output operation sequence should be “RU”
Example 2:
[20, 18, 7, 19, 10
24, 4, 15, 11, 9
13, 0, 22, 12, 14
23, 16, 1, 2, 5
21, 17, 8, 3, 6]
The target matrix is
[20, 18, 7, 19, 10
24, 15, 11, 12, 9
13, 4, 22, 2, 14
23, 16, 0, 1, 5
21, 17, 8, 3, 6]
The input operation sequence is “RRLUDD”
The output operation sequence should be “URRDDL”
代碼結構如下:
#include <stdio.h>
#include < string.h>
void calculateTheRightSequence( int originalMatrix[][ 5], int newMatrix[][ 5],
char inputSequence[], char outputSequence[]);
int Getnput( char operation[], int originalMatrix[][ 5], int newMatrix[][ 5]);
int main()
{
int original[ 5][ 5];
int newMatrix[ 5][ 5];
char inputOperation[ 100]={ 0};
char outputOperation[ 100]= { 0};
while( Getnput(inputOperation, original, newMatrix) )
{
calculateTheRightSequence(original, newMatrix, inputOperation, outputOperation);
printf( " %s\n ", outputOperation);
}
return 0;
}
// your code is here
void calculateTheRightSequence( int originalMatrix[][ 5], int newMatrix[][ 5],
char inputSequence[], char outputSequence[])
{
}
int Getnput( char operation[], int originalMatrix[][ 5], int newMatrix[][ 5])
{
int i = 0, j = 0;
for( i = 0; i < 5; ++i )
for(j = 0; j < 5; ++j)
{
if( scanf( " %d ", &originalMatrix[i][j]) != 1 )
break;
}
if( j < 5 ) return 0;
for( i = 0; i < 5; ++i )
for(j = 0; j < 5; ++j)
{
scanf( " %d ", &newMatrix[i][j]);
}
scanf( " %s ", operation );
return 1;
}
應該也是個類似全排列問題,留待后面慢慢考慮,也算是貼出來跟大伙分享,哈哈~
2012-09-25第二次在線筆試
Question 1 / 2.
Given an array A, find the maximum neighboring-peak-valley difference of A, MaxD(A).
For example, A={2, 3, 6, 5, 7, 9}, the elements 2, 5 could be regarded as the valley while 6 and 9 are the peaks. The difference of each neighboring peak-valley pair could be enumerated as below:
D[2, 6]=4, D[6,5]=1, D=[5,9]=4.
Thus, MaxD(A)=4.
Please write a program to find the maximum neighboring-peak-valley difference of an array. The input contains several lines(10 lines at most), and each line contains of several numbers separated by space. We treat every line an array.And each line has 2 numbers at least and 20 numbers at most.
The output should be the maximum neighboring-peak-valley difference of the arrays and separated by comma. For example:
Input:
2 3 6 5 7 9
2 3 6 5 7
2 3 6 5 7 9 10
Output:
4,4,5
思路:本題比較簡單,考慮好邊界情況就可以了
#include <stdio.h>
#include < string.h>
#define ISSPACE(x) ((x)==' '||(x)=='\r'||(x)=='\n'||(x)=='\f'||(x)=='\b'||(x)=='\t')
char * rightTrim( char *str){
int len = strlen(str);
while(--len>= 0){
if(ISSPACE(str[len])){
str[len] = ' \0 ';
} else{
break;
}
}
return str;
}
char * getInputLine( char *buffer, int length){
if(fgets(buffer,length, stdin)==NULL){
return NULL;
}
rightTrim(buffer);
if(strlen(buffer)<= 0){
return NULL;
}
return buffer;
}
/*
For example, A={2, 3, 6, 5, 7, 9}, the elements 2, 5 could be regarded as the valley while 6 and 9 are the peaks.
The difference of each neighboring peak-valley pair could be enumerated as below:
D[2, 6]=4, D[6,5]=1, D=[5,9]=4.
Thus, MaxD(A)=4.
*/
void maxNeighboringPeak( char ** data, int count){
/* Enter your code here. Read input from STDIN. Print output to S TDOUT */
int *MaxD = new int[count];
char *line_char = NULL;
int line_int[ 20];
int peak_valley_value[ 20];
int peak_valley_label[ 20];
for( int i= 0; i<count; i++)
{
line_char = data[i];
int line_len = strlen(line_char);
int num = 0;
int begin, end;
begin = 0;
end = 0;
for( int j= 0; j<line_len; j++)
{
int temp_num = 0;
if(line_char[j] == ' ')
end = j- 1;
else
{
if(j==line_len- 1)
end = j;
else
continue;
}
for( int k=begin; k<=end; k++)
{
temp_num = 10*temp_num + (line_char[k]- ' 0 ');
}
line_int[num] = temp_num;
num++;
begin = end+ 2;
}
int peak_valley_num = 0;
for( int j= 0; j<num; j++)
{
if(j== 0)
{
if(line_int[j] < line_int[j+ 1])
{
peak_valley_value[peak_valley_num] = line_int[j];
peak_valley_label[peak_valley_num] = - 1;
peak_valley_num++;
}
else if(line_int[j] > line_int[j+ 1])
{
peak_valley_value[peak_valley_num] = line_int[j];
peak_valley_label[peak_valley_num] = 1;
peak_valley_num++;
}
}
else if(j==num- 1)
{
if(line_int[j- 1] < line_int[j])
{
peak_valley_value[peak_valley_num] = line_int[j];
peak_valley_label[peak_valley_num] = 1;
peak_valley_num++;
}
else if(line_int[j- 1] > line_int[j])
{
peak_valley_value[peak_valley_num] = line_int[j];
peak_valley_label[peak_valley_num] = - 1;
peak_valley_num++;
}
}
else
{
if(line_int[j- 1] <= line_int[j] && line_int[j] >= line_int[j+ 1])
{
peak_valley_value[peak_valley_num] = line_int[j];
peak_valley_label[peak_valley_num] = 1;
peak_valley_num++;
}
else if(line_int[j- 1] >= line_int[j] && line_int[j] <= line_int[j+ 1])
{
peak_valley_value[peak_valley_num] = line_int[j];
peak_valley_label[peak_valley_num] = - 1;
peak_valley_num++;
}
}
}
MaxD[i] = 0;
for( int j= 0; j<peak_valley_num- 1; j++)
{
int temp;
if(peak_valley_label[j] + peak_valley_label[j+ 1] == 0)
temp = (peak_valley_value[j] > peak_valley_value[j+ 1]) ? (peak_valley_value[j] - peak_valley_value[j+ 1]) : (peak_valley_value[j+ 1] - peak_valley_value[j]);
MaxD[i] = (MaxD[i] > temp ? MaxD[i] : temp);
}
}
for( int j= 0; j<count; j++)
{
if(j== 0)
printf( " %d ", MaxD[j]);
else
printf( " ,%d ", MaxD[j]);
}
delete MaxD;
}
int main( int argc, char ** argv){
char buffers[ 512][ 512];
char *input[ 512];
int inputCount = 0;
while(getInputLine(buffers[inputCount], 512) != NULL){
input[inputCount++] = buffers[inputCount];
}
maxNeighboringPeak(input, inputCount);
return 0;
}
Question 2 / 2.
We have a file which contains lines of some classify rules, we can place integers ( 0 < n < max(Integer)) to different categories by the rules, for example:
n1 : a = 4
n2 : a = 1 or a = 2 or a = 23
n3 : a > 100
n4 : a > 24 and a < 54
n5 : a > 54 and a < 58 or a = 22
The first line means if a number equals to 4, then it should be place to category n1;
The second line means if a number equals to 1 or 2 or 23, then it should be place to category n2;
The third line means any number greater than 100 should be placed into category n3;
The fourth line means any number greater than 24 and smaller than 24 should be placed into category n4;
The fifth line means any number greater than 54 and smaller than 58 or equals to 22 should be placed into category n5.
The file has the following rule
1. Category and rules are sperated by semicolon;
2. "a" is a key words in the file, it represent the integer;
3. Key words(":", "=", "or", ">", "<", "and", "a") are sperated by space;
4. "and" should have a higher precedence then "or", this meas rule "a > 10 or a > 5 and a < 8" will get true if a = 11
Write a program to parse a rule file and output the given number's category. If it's not belongs to any of the category, output "none". Please notice that expression evaluation API(eval() function or other equivalent functions) should not be used.
In all the testcases, we have a input like the following(The fist line contains several numbers we want to classify, and the category name can be any string):
45,22
n1 : a = 4
category 2 : a = 1 or a = 2 or a = 23
n3 : a > 100
n4 : a > 24 and a < 54
n5 : a > 54 and a < 58 or a = 22
And the output should be:
n4,n5
Information may be help:
1. The rules in the same testcase we provide are not conflict with anyone else;
2. None of the rule we provided is a self-conflict rule, for example, we provide no rule like this "n1 : a = 5 and a = 3".
思路:本題思路不難,難就 難在字符串庫string.h中各種字符串操作,比較復雜,時間不夠,就沒做出來。。。
有興趣的可以研究研究
#include <stdio.h>
#include < string.h>
#include <stdlib.h>
#define ISSPACE(x) ((x)==' '||(x)=='\r'||(x)=='\n'||(x)=='\f'||(x)=='\b'||(x)=='\t')
char * rightTrim( char *str)
{
int len = strlen(str);
while(--len>= 0) {
if(ISSPACE(str[len])) {
str[len] = ' \0 ';
} else {
break;
}
}
return str;
}
char * getInputLine( char *buffer, int length)
{
if(fgets(buffer,length, stdin)==NULL) {
return NULL;
}
rightTrim(buffer);
if(strlen(buffer)<= 0) {
return NULL;
}
return buffer;
}
int extractNumbersToArray( char *str, int *numbers)
{
const char *split = " , ";
char *p = strtok (str,split);
int index = 0;
while(p!=NULL) {
numbers[index++] = atoi(p);
p = strtok(NULL,split);
}
return index;
}
void determineRuleAndOutput( int *numbers, int numberCount, char ** rules, int ruleCount)
{
// your code here
int curr_num = 0;
char * curr_rule = NULL;
for( int i= 0; i<numberCount; i++)
{
curr_num = numbers[i];
for( int j= 0; j<ruleCount; j++)
{
curr_rule = rules[j];
for( int k= 0; k<strlen(curr_rule); k++)
{
}
}
}
}
int main( int argc, char ** argv)
{
int numbers[ 1024];
char numberBuffer[ 1024];
getInputLine(numberBuffer, 1024);
int numberCount = extractNumbersToArray(numberBuffer, numbers);
char buffers[ 1024][ 1024];
char *rules[ 1024];
int ruleCount = 0;
while(getInputLine(buffers[ruleCount], 1024) != NULL) {
rules[ruleCount++] = buffers[ruleCount];
}
determineRules(numbers, numberCount, rules, ruleCount);
return 0;
}