注: 如下的题目皆来自互联网,答案是结合了自己的习惯稍作了修改。
1. 求一个数的二进制中的1的个数。
int func(int x) { int count = 0; while (x) { count++; x = x& (x - 1); } return count; }
2. 已知strcpy的函数原型:char *strcpy(char *strDest, const char *strSrc)其中strDest 是目的字符串,strSrc 是源字符串。不调用C++/C 的字符串库函数,请编写函数 strcpy。
int _tmain(int argc, _TCHAR* argv[]) { const char *srcStr = "This is a source string."; //char *desStr = (char *)malloc(sizeof(srcStr)); // Or below: char *desStr = (char *)malloc(sizeof(char)* strlen(srcStr) + 1); myStrcpy(desStr, srcStr); printf("Copy result: %s", desStr); } char *myStrcpy(char *strDest, const char *strSrc) { if (strSrc == NULL || strDest == NULL) { return NULL; } if (strDest == strSrc) { return strDest; } char *strDestStart = strDest; while (*strDest !='\0') { *strDest++ = *strSrc++; } return strDestStart; }
3. 链表题:
一个链表的结点结构
struct Node { int data ; Node *next ; }; typedef struct Node Node ;
(1)已知链表的头结点head,写一个函数把这个链表逆序
思路: 用三个指针p0,p1,p2,从头到尾依次遍历并反转结点
int _tmain(int argc, _TCHAR* argv[]) { int linkedListLength = 5; Node *myList = new Node(); Node *p = myList; printf("Original linked list is:"); for (int i = 0; i < linkedListLength; i++) { Node *node = new Node(); node->data = i; printf(" %d", i); p->next = node; p = node; } Node *reversedMyList = ReverseLinkedList(myList); printf("\r\nReversed linked list is:"); Node *r = reversedMyList; while (r->next != NULL) { printf(" %d", r->data); r = r->next; } } Node *ReverseLinkedList(Node *head) { // NULL if (head == NULL) { return NULL; } // One node only. if (head->next == NULL) { return head; } // Two or more than two nodes. Node *p0 = head; Node *p1 = p0->next; Node *p2 = p1->next; //p2 maybe null; p0->next = NULL; while (p2 != NULL) { p1->next = p0; p0 = p1; p1 = p2; p2 = p2->next; } p1->next = p0; return p1; }
(2)已知两个链表head1 和head2 各自有序,请把它们合并成一个链表依然有序。(保留所有结点,即便大小相同)
思路: 从head1 和 head2 中找一个较小值定义为head,然后一次用p0,p1遍历两个链表,逐步的插入到新链表里(currnt)。
int _tmain(int argc, _TCHAR* argv[]) { Node *p0 = new Node(); Node *p1 = new Node(); int data0[5] = { 1, 3, 5, 8, 10}; int data1[3] = { 2, 6, 7 }; Node *head0 = p0; Node *head1 = p1; for (int i = 0; i < sizeof(data0)/sizeof(data0[0]); i++) { Node *tmp0 = new Node(); tmp0->data = data0[i]; p0->next = tmp0; p0 = p0->next; } for (int j = 0; j < sizeof(data1)/sizeof(data1[0]); j++) { Node *tmp1 = new Node(); tmp1->data = data1[j]; p1->next = tmp1; p1 = p1->next; } head0 = head0->next; head1 = head1->next; Node *mergedList = MergeSortedLinkedList(head0, head1); } Node *MergeSortedLinkedList(Node *head0, Node *head1) { if (head0 == NULL) { return head1; } if (head1 == NULL) { return head0; } // Set new head for new merged sorted list. Node *head = NULL; Node *p0 = head0; Node *p1 = head1; if (head0->data < head1->data) { head = head0; p0 = p0->next; } else { head = head1; p1 = p1->next; } Node *current = head; while (p0 != NULL && p1 != NULL) { // Insert the value which is smaller. if (p0->data < p1->data) { current->next = p0; current = p0; p0 = p0->next; } else { current->next = p1; current = p1; p1 = p1->next; } } // All of nodes of one list have been added into new merged list. so add the rest nodes of the other list. if (p0 == NULL) { current->next = p1; } if (p1 == NULL) { current->next = p0; } return head; }
另外可以也可以采用递归(recursive)算法:
顺便补充一下递归算法的特点,其关键就是定义一个递归公式和递归结束条件。
Node * MergeRecursive(Node *head0, Node *head1) { if (head0 == NULL) { return head1; } if (head1 == NULL) { return head0; } Node *head = NULL; if (head0->data < head1->data) { head = head0; head->next = MergeRecursive(head0->next, head1); } else { head = head1; head->next = MergeRecursive(head0, head1->next); } return head; }
(3)Implement an Algorithm to check if the link list is in Ascending order?
思路: 遍历链表,只要找到某个结点的值比下个结点的值大,那么就可以判断为false。
bool IsAscendingList(Node *head) { Node *p = head; while (p->next != NULL) { if (p->data > p->next->data) { return false; } p = p->next; } return true; }
int _tmain(int argc, _TCHAR* argv[]) { int data0[5] = { 1, 3, 9, 8, 10}; //int data1[7] = { 9, 1, 2, 4, 6, 10}; int data1[7] = { 9, 4, 7, 6, 6}; int secMax0 = FindSecondMax(data0, sizeof(data0) / sizeof(data0[0])); int secMax1 = FindSecondMax(data1, sizeof(data1) / sizeof(data1[0])); } int FindSecondMax(int *data, int dataLength) { if (dataLength <= 1) { printf("The length of data should be more than 1."); return -1; } int max = data[0]; int secondMax = MIN_INT; for (int i = 1; i < dataLength; i++) { if (data[i] > max) { secondMax = max; max = data[i]; } else { if (data[i] > secondMax) { secondMax = data[i]; } } } return secondMax; }
5. 将数a、b的值进行交换,并且不使用任何中间变量.
思路: 采用异或运算(三次异或后,就被交换), 或加减运算。
int _tmain(int argc, _TCHAR* argv[]) { int a = 18; int b = 32; // Swap withouth other variables. 3 times XOR will swap two values. (1^1 = 0, 0^0 =0, 1^0 =1, 0^1 =1). a ^= b; b ^= a; a ^= b; printf("a:%d, b:%d", a, b); // method2 a = a + b; b = a - b; a = a - b; printf("a:%d, b:%d", a, b); }
6. 题目:在一个字符串中找到第一个只出现一次的字符。如输入abaccdeff,则输出b。
分析:这道题是2006 年google 的一道笔试题。
思路:采用bitmap或者byteArray的思路,遍历字符串,每个字符对应的整数值为index。 Array里保存字符出现的次数。
// Assuming the char is ASCII char FirstSingleChar(char *str) { int bitmap[255]; memset(bitmap, 0, 255 * sizeof(int)); char *p = str; while (*p != '\0') { bitmap[*p]++; p++; } p = str; while (*p!='\0') { if (bitmap[*p] == 1) { return *p; } } return '\0'; }
7.题目:输入一个表示整数的字符串,把该字符串转换成整数并输出。
例如输入字符串"345",则输出整数345。
思路: 遍历字符串,逐字符转换为整数(和‘0'做差), 其中注意一下对负数和数字的判断。
int ConvertStrToInt(char *str) { char *p = str; int result = 0; int asciiToInt = 0; bool isPostive = true; if (*p == '-') { isPostive = false; p++; } else if (*p == '+') { p++; } while (*p != '\0') { if (IsNumber(*p)) { asciiToInt = *p - '0'; result = result * 10 + asciiToInt; p++; } else { //Had better throw exception here. printf("Illegal number: %c", *p); break; } } if (!isPostive) { result = 0 - result; } return result; }
8. Reverse a string.
思路: 用两个指针指向一头一尾。然后向中间遍历,并逐个字符交换。
int _tmain(int argc, _TCHAR* argv[]) { // char *strForTest = "+345abc" will cause "access violation writing location". http://stackoverflow.com/questions/14664510/access-violation-writing-location char strForTest[] = "I like money"; ReverseWordsInSentence(strForTest); } void ReverseString(char *str) { int strLength = strlen(str); ReverseStringInFixedLength(str, strLength); } void ReverseStringInFixedLength(char *str, int strLength) { char *p1 = str; char *p2 = str + strLength -1; char tmp; while (p1 < p2) { // Swap two chars. tmp = *p1; *p1 = *p2; *p2 = tmp; p1++; p2--; } }
9. Revese words in a sentense. for example. reverse "I like money" to "money like I".
思路:Reverse the whole string, then reverse each word. Using the reverseStringInFixedLength() above.
void ReverseWordsInSentence(char *sen) { ReverseString(sen); char *pStartOfWord = sen; char *p = pStartOfWord; while (*p != '\0') { // Skip blank spaces. while (*p == ' ' && *p != '\0') { p++; } pStartOfWord = p; while (*p != ' ' && *p != '\0') { p++; } int wordLength = p - pStartOfWord; ReverseStringInFixedLength(pStartOfWord, wordLength); } }
10. 给出一个数组,还有一个给定的数,打印出数组中的一对数(不重复),使其和等于指定的数
思路:先排序(快排),然后再用两个指针从头尾依次向中间遍历。如果和大于期待的值,那么左移right指针,如果小于期待的值,那么右移left指针。
For sorted array, the time complexity is O(n). For unsorted array, we may do a quick sort and then call our method. The time complexity is O(nlogn). Here is the C++ sample codes, and I have checked it works well. int _tmain(int argc, _TCHAR* argv[]) { int nums[7] = { 1, 2, 3, 3, 4, 4, 5 }; printUniquePairs(nums, 7, 7); } void printUniquePairs(int *numbers, int numbersLength, int expectedSum) { int sum = 0; //Augrments judgements. e.g. Null, length. if (numbersLength < 2) { printf("Number length should be more than 2."); return; } // Quick sort. QuickSort(numbers); // Use two points (left, and right) moving from two sides into the center. int *p1 = numbers; int *p2 = numbers + numbersLength - 1; int previousP1Value; int previousP2Value; while (p1 < p2) { sum = *p1 + *p2; previousP1Value = *p1; previousP2Value = *p2; if (sum == expectedSum) { printf("Print unique pair: %d, %d.", *p1, *p2); p1++; p2--; // If the value is duplicated, then skip. if (previousP1Value == *p1) { p1++; } if (previousP2Value == *p2) { p2--; } } else if (sum < expectedSum) { p1++; // If the value is duplicated, then skip. if (previousP1Value == *p1) { p1++; } } else if (sum > expectedSum) { p2--; if (previousP2Value == *p2) { p2--; } } }