常见算法学习笔记

1)、求单向链表倒数第k个元素

思想:通过双指针实现,设指针p、q初试都指向头结点。指针p后移k次,然后指针p、q一起后移直到p指向空指针。写代码过程中要考虑一些异常情况,如K大于链表长度等。

实现代码如下:

#include<iostream>
using std::cin;
using std::cout;
using std::endl;
using std::runtime_error;
struct ListNode
{
	int num;
	ListNode *next;
};
int getLastKNum(ListNode *head,int k)
{
	if(head==NULL)
	{
		throw runtime_error("头指针为空");
	}
	if(k<=0)
		throw runtime_error("k必须为正数");
	ListNode *p=head,*q=head;
	while(k>0&&p)//p右移k次
	{
		p=p->next;
		--k;
	}
	if(k>0)
		throw runtime_error("K大于链表长度!");
	while(p)
	{
		p=p->next;
		q=q->next;
	}
	if(q==head)//当k等于链表长度+1.
		throw runtime_error("K大于链表长度!");
	else
		return q->num;
}
void deleteList(ListNode *head)//释放空间
{
	ListNode *p=head;
	ListNode *q=head;
	while(p)
	{
		q=p;
		p=p->next;
		delete q;
	}
}
int main()
{
	ListNode *head=new ListNode();
	head->next=NULL;
	for(int i=1;i<10;i++)
	{
		ListNode *tmp=new ListNode();
		tmp->num=i;
		tmp->next=head->next;
		head->next=tmp;
	}
	try
	{
		for(int i=1;i<=9;i++)
			cout<<getLastKNum(head,i)<<endl;
	}catch(runtime_error err)
	{
		cout<<err.what()<<endl;
	}
	deleteList(head);
	
}

2)求500万以内的亲和数

思想来自于July博客http://blog.csdn.net/v_july_v/article/details/6441279。

2.1、什么是亲和数?

以下是摘自维基百科的解释:

相亲数(Amicable Pair),又称亲和数友爱数,指两个正整数中,彼此的全部约数之和(本身除外)与另一方相等。

例如220与284:

  • 220的全部约数(除掉本身)相加是:1+2+4+5+10+11+20+22+44+55+110=284
  • 284的全部约数(除掉284本身)相加的和是:1+2+4+71+142=220

换句话说,亲和数又可以说成是两个正整数中,一方的全部约数之和与另一方的全部约数之和相等。

  • 220的全部约数之和是:1+2+4+5+10+11+20+22+44+55+110+220 = 284+220 = 504
  • 284的全部约数之和是:1+2+4+71+142+284 = 220+284 = 504

2.2、问题的难点:
   因为基数比较大,如何能够快速的查找出亲和数这是一个难点.方法是以空间换时间.申请可以存放500万个整数的数组Divisor,数组存放每个数的亲和数.数n=Divisor[Divisor[n]]即为一对亲和数.
如何求全部约数之和:
1.简单办法:
int SumOfDivisor(int n)
{
	int sum=1;
	for(int i=2;i<=n/2;i++)
	{
		if(n%i==0)
			sum+=i;
	}
}
而July采用了另一个种办法.
比如说2这个数字,它一定是4,6,8...的约数.即2i的约数都会有2.可以依次将该数添加到Divisor数组中.其实这两种方式求约数之和是差不多的.但为什么我这里需要特别指出.主要是上周六参加腾讯实习生笔试,第一道附加题就需要用这种思想.哎,当时没想起,吃亏啊...
代码如下:
#include<iostream>
using std::cin;
using std::cout;
using std::endl;
void Amicable_Pair(int n);
int main()
{
	int n;
	cin>>n;
	Amicable_Pair(n);
	return 0;

}
/*
*求n内的亲和数
*/
void Amicable_Pair(int n)
{
	int *num=new int[n];
	for(int i=0;i<n;i++)
		num[i]=1;
	for(int i=2;i<=n/2;i++)
	{
		int j=i+i;
		while(j<n)
		{
			num[j]+=i;
			j+=i;
		}
	}//求出1-n的所有约数(除去本身)
	for(int i=220;i<n;i++)
	{
		if(i<num[i]&&num[i]<n&&i==num[num[i]])
			cout<<i<<" "<<num[i]<<endl;
	}
	delete[] num;
}

3、求平方根算法实现


你可能感兴趣的:(常见算法学习笔记)