好文档 - 专业文书写作范文服务资料分享网站

算法大全-面试题-数据结构 

天下 分享 时间: 加入收藏 我要投稿 点赞

其中,curr2.Next = curr1.Next.Next; 这句话是关键,它负责把上一个单链表的表尾和下一个单链表的非空表头连接起来。

7.单链表交换任意两个元素(不包括表头)

先一次遍历找到这两个元素curr1和curr2,同时存储这两个元素的前驱元素pre1和pre2。 然后大换血

public static Link SwitchPoints(Link head, Link p, Link q) {

if (p == head || q == head)

throw new Exception(\ if (p == q)

return head;

//find p and q in the link Link curr = head; Link curr1 = p; Link curr2 = q; Link pre1 = null; Link pre2 = null;

int count = 0; while (curr != null) {

if (curr.Next == p) {

pre1 = curr; count++;

if (count == 2) break; }

else if (curr.Next == q) {

pre2 = curr; count++;

if (count == 2) break; }

curr = curr.Next; }

curr = curr1.Next;

pre1.Next = curr2;

curr1.Next = curr2.Next; pre2.Next = curr1; curr2.Next = curr; return head; }

注意特例,如果相同元素,就没有必要交换;如果有一个是表头,就不交换。

8.判断单链表是否有环?如何找到环的“起始”点?如何知道环的长度?

算法思想:

先分析是否有环。为此我们建立两个指针,从header一起向前跑,一个步长为1,一个步长为2,用while(直到步长2的跑到结尾)检查两个指针是否相等,直到找到为止。

static bool JudgeCircleExists(Link head) {

Link first = head; //1 step each time Link second = head; //2 steps each time

while (second.Next != null && second.Next.Next != null) {

second = second.Next.Next; first = first.Next; if (second == first) return true; }

return false; }

那又如何知道环的长度呢?

根据上面的算法,在返回true的地方,也就是2个指针相遇处,这个位置的节点P肯定位于环上。我们从这个节点开始先前走,转了一圈肯定能回来: static int GetCircleLength(Link point) {

int length = 1; Link curr = point;

while (curr.Next != point) {

length++;

curr = curr.Next;

}

return length; }

继续我们的讨论,如何找到环的“起始”点呢?

延续上面的思路,我们仍然在返回true的地方P,计算一下从有环单链表的表头head到P点的距离

static int GetLengthFromHeadToPoint(Link head, Link point) {

int length = 1; Link curr = head; while (curr != point) {

length++;

curr = curr.Next; }

return length; }

如果我们把环从P点“切开”(当然并不是真的切,那就破坏原来的数据结构了),那么问题就转化为计算两个相交“单链表”的交点(第10题): 一个单链表是从P点出发,到达P(一个回圈),距离M;另一个单链表从有环单链表的表头head出发,到达P,距离N。

我们可以参考第10题的GetIntersect方法并稍作修改。 private static Link FindIntersect(Link head) {

Link p = null;

//get the point in the circle

bool result = JudgeCircleExists(head, ref p); if (!result) return null; Link curr1 = head.Next; Link curr2 = p.Next; //length from head to p int M = 1;

while (curr1 != p) {

M++;

curr1 = curr1.Next; }

//circle length int N = 1;

while (curr2 != p)

{

N++;

curr2 = curr2.Next; }

//recover curr1 & curr2 curr1 = head.Next; curr2 = p.Next;

//make 2 links have the same distance to the intersect if (M > N) {

for (int i = 0; i < M - N; i++) curr1 = curr1.Next; }

else if (M < N) {

for (int i = 0; i < N - M; i++) curr2 = curr2.Next; }

//goto the intersect while (curr1 != p) {

if (curr1 == curr2) {

return curr1; }

curr1 = curr1.Next; curr2 = curr2.Next; }

return null; }

9.判断两个单链表是否相交

这道题有多种算法。

算法1:把第一个链表逐项存在hashtable中,遍历第2个链表的每一项,如果能在第一个链表中找到,则必然相交。

static bool JudgeIntersectLink1(Link head1, Link head2) {

Hashtable ht = new Hashtable(); Link curr1 = head1; Link curr2 = head2;

//store all the elements of link1

while (curr1.Next != null) {

ht[curr1.Next] = string.Empty; curr1 = curr1.Next; }

//check all the elements in link2 if exists in Hashtable or not while (curr2.Next != null) {

//if exists

if (ht[curr2.Next] != null) {

return true; }

curr2 = curr2.Next; }

return false; }

算法2:把一个链表A接在另一个链表B的末尾,如果有环,则必然相交。如何判断有环呢?从A开始遍历,如果能回到A的表头,则肯定有环。 注意,在返回结果之前,要把刚才连接上的两个链表断开,恢复原状。 static bool JudgeIntersectLink2(Link head1, Link head2) {

bool exists = false; Link curr1 = head1; Link curr2 = head2;

//goto the end of the link1 while (curr1.Next != null) {

curr1 = curr1.Next; }

//join these two links curr1.Next = head2; //iterate link2

while (curr2.Next != null) {

if (curr2.Next == head2) {

exists = true; break; }

curr2 = curr2.Next;

算法大全-面试题-数据结构 

其中,curr2.Next=curr1.Next.Next;这句话是关键,它负责把上一个单链表的表尾和下一个单链表的非空表头连接起来。7.单链表交换任意两个元素(不包括表头)先一次遍历找到这两个元素curr1和curr2,同时存储这两个元素的前驱元素pre1和pre2。然后大换血publicstaticLink
推荐度:
点击下载文档文档为doc格式
17g0x8arf2570pk9t1s5
领取福利

微信扫码领取福利

微信扫码分享