第一题:数值的整数次方
需要注意的地方:指数为负数,指数为负数的时候,数值为0,首先给出一般性的解法:
//注意,判断浮点数是否相等,不能用==,而是差值在某个范围内
bool equal(double num1, double num2)
{
if (num1 - num2 > -0.0000001 && num1 - num2 < 0.0000001)
return true;
else
return false;
}
double PowerWithUnsignedExponent(double base, unsigned int exponent)
{
double result = 1.0;
for (int i = 1; i <= exponent; ++i)
result *= base;
return result;
}
double Power(double base, int exponent)
{
if (equal(base, 0.0) && exponent < 0)
throw new exception("输入不合法");
unsigned int absExponent = (unsigned int)(exponent);
if (exponent < 0)
absExponent = (unsigned int)(-exponent);
double result = PowerWithUnsignedExponent(base, absExponent);
if (exponent < 0)
result = 1 / result;
return result;
}
书中给出了高效的解法:a^n=a^(n/2)*a^(n/2) 或者 a^n=a^((n-1)/2)*a^((n-1)/2)*a,利用这个式子,求解:
double PowerWithUnsignedExponent(double base, unsigned int exponent)
{
if (exponent == 0)
return 1;
if (exponent == 1)
return base;
double result = PowerWithUnsignedExponent(base, exponent >> 1);
result *= result;
if (exponent & 0x1 == 1)
result *= base;
return result;
}
第二题:打印1到最大的n位数
这个题,注意很可能会溢出,所以用数组模拟加法来解。
bool Increment(vector<int> &number)
{
bool isOverflow = false;
int nTakeOver = 0;
int length = number.size();
for (int i = length -1; i >= 0; --i)
{
int nSum = number[i] + nTakeOver;
if (i == length - 1)
++nSum;
if (nSum >= 10)
{
if (i == 0)
isOverflow = true;
else
{
nSum -= 10;
nTakeOver = 1;
number[i] = nSum;
}
}
else
{
number[i] = nSum;
break;
}
}
return isOverflow;
}
void PrintNumber(vector<int> &number)
{
int i = 0;
while (i < number.size() && number[i] == 0)
{
++i;
}
for (; i < number.size(); ++i)
{
cout << number[i];
}
cout << "\n";
}
void print1ToMaxNDigits(int n)
{
if (n <= 0)
return;
vector<int> number(n,0);
while (!Increment(number))
PrintNumber(number);
}
第三题:在O(1)时间内删除链表节点
一种思路是两个节点,前后各一个。另一种思路是交换要删除的节点和后面的节点,然后删除后面的节点即可,第一种思路第一章总结过
第四题:调整数组顺序使奇数位于偶数前面
void RerderOddEven(vector<int> &nums)
{
int left = 0;
int right = nums.size() - 1;
while (left < right)
{
while (left < right && (nums[left] & 0x01) == 1)
++left;
while (left < right && (nums[right] & 0x01) == 0)
--right;
if (left < right)
swap(nums[left], nums[right]);
}
}
第五题:反转链表
容易出错的题
ListNode* ReverseList(ListNode *pHead)
{
ListNode *pReversedHead = NULL;
ListNode *pNode = pHead;
ListNode *pPrev = NULL;
while (pNode != NULL)
{
ListNode *pNext = pNode->next;
if (pNext == NULL)
pReversedHead = pNext;
pNode->next = pPrev;
pPrev = pNode;
pNode = pNext;
}
return pReversedHead;
}
第六题:合并两个排序的链表
非递归解:
ListNode* Merge(ListNode*pHead1, ListNode*pHead2)
{
ListNode *newList = NULL;
if (pHead1 == NULL)
return pHead2;
if (pHead2 == NULL)
return pHead1;
if (pHead1->val < pHead2->val)
{
newList = pHead1;
pHead1 = pHead1->next;
}
else
{
newList = pHead2;
pHead2 = pHead2->next;
}
ListNode *pNode = newList;
while (pHead1 != NULL && pHead2 != NULL)
{
if (pHead1->val < pHead2->val)
{
pNode->next = pHead1;
pNode = pHead1;
pHead1 = pHead1->next;
}
else
{
pNode->next = pHead2;
pNode = pHead2;
pHead2 = pHead2->next;
}
}
if (pHead1 == NULL)
pNode->next = pHead2;
else
pNode->next = pHead1;
return newList;
}
递归解,简洁多了:
ListNode *Merge(ListNode *pHead1, ListNode *pHead2)
{
ListNode *newList = NULL;
if (pHead1 == NULL)
return pHead2;
if (pHead2 == NULL)
return pHead1;
if (pHead1->val < pHead2->val)
{
newList = pHead1;
newList->next = Merge(pHead1->next, pHead2);
}
else
{
newList = pHead2;
newList->next = Merge(pHead1, pHead2->next);
}
return newList;
}