(C/C++) 算法,编程题

注: 如下的题目皆来自互联网,答案是结合了自己的习惯稍作了修改。

1. 求一个数的二进制中的1的个数。

int func(int x)
{
int count = ; while (x)
{
count++;
x = x& (x - );
} 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) + ); 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)算法:

顺便补充一下递归算法的特点,其关键就是定义一个递归公式和递归结束条件。

(1) 递归就是在过程或函数里调用自身。
(2) 在使用递归策略时,必须有一个明确的递归结束条件,称为递归出口。
(3) 递归算法解题通常显得很简洁,但递归算法解题的运行效率较低。所以一般不提倡用递归算法设计程序。
(4) 在递归调用的过程当中系统为每一层的返回点、局部量等开辟了栈来存储。递归次数过多容易造成栈溢出等。所以一般不提倡用递归算法设计程序。
 
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;
}

  

 4.  写一个函数找出一个整数数组中,第二大的数
思路:一次遍历数组找出最大和次大数。
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://*.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--;
}
}
}

  

上一篇:css关系选择器


下一篇:安卓SQLite数据库操作,半小时开发新闻管理系统,纯干货