《剑指Offer》第三章

26 篇文章 1 订阅
4 篇文章 0 订阅

第一题:数值的整数次方

需要注意的地方:指数为负数,指数为负数的时候,数值为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;
}






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值