E81086713E446D36F62B2AA2A3502B5EB155

Java杂家

杂七杂八。。。一家之言

BlogJava 首页 新随笔 联系 聚合 管理
  141 Posts :: 1 Stories :: 174 Comments :: 0 Trackbacks




今天去网上看了一下09年的考研试题,看见该题目(图片):



先来定义结点(为了简便,省略set/get):
public class Node
{
 
public int data;
 
public Node link;
}
我能想到的两种解法,一个基于递归:

递归版的思路就是,基于当前结点,如果后一个是倒数第K-1,那么当前结点是所求,若不然,返回当前是倒数第几个。
public int printRKWithRecur(Node head,int k)
    {
        
if(k==0||head==null||head.link==null)return 0;
        
if(_recurFind(head.link,k)>=k)return 1;
        
return 0;
    }
    
private final int _recurFind(Node node, int k) {
        
if(node.link==null)
        {
            
return 1;
        }
        
int sRet=_recurFind(node.link,k);
        
if(sRet==k-1)
        {
            System.out.println(
"Got:"+node.data);
            
return k;
        }
        
return sRet+1;
    }


对每个结点,该算法都只访问一次,因此复杂度O(N).

第二解法,相对递归来说,这种方法可以算是消除递归版,而且从某种意义上来说比递归更高效,跟省空间,递归版实际上是把回溯的数据存在栈上,而版方法是自己存储,且利用数组实现一个循环队列,只存储K个元素。

public static class CycleIntQueue
    {
        
int[] datas;
        
int top=0;
        
int num=0;
        
public CycleIntQueue(int n)
        {
            datas
=new int[n];
        }
        
        
public void push(int i)
        {
            datas[(top
++)%datas.length]=i;
            num
++;
            
        }
        
public int numPushed()
        {
            
return num;
        }
        
        
        
public int getButtom()
        {
            
return datas[top%datas.length];
        }
    }
    
public int printRKWithCycleQueue(Node head,int k)
    {
        
if(k==0||head==null)return 0;
        CycleIntQueue queue
=new CycleIntQueue(k);
        Node cur
=head.link;
        
while(cur!=null)
        {
            queue.push(cur.data);
            cur
=cur.link;
        }
        
if(queue.numPushed()<k)return 0;
        
        System.out.println(
"Got:"+queue.getButtom());
        
return 1;
    }

本算法,都每个结点也只放一次,另外进行一次入队操作,该操作复杂度O(1),从而,整个算法复杂度仍是O(N).


posted on 2009-01-17 13:56 DoubleH 阅读(2261) 评论(5)  编辑  收藏

Feedback

# re: [算法]09考研数据结构试题解法 2009-01-17 15:41 crtylr
个人觉得根本就用不着那么,麻烦的方法
两个指针,第一个指向头,另一个指向从头开始的指向第K个
然后两个指针分别指向Next,
直到第二个指针指向了Null,那第一个指针的元素就是所求的倒数第K个  回复  更多评论
  

# re: [算法]09考研数据结构试题解法 2009-01-17 20:53 银河使者
这是一个算法,详细解释见我的blog:
http://www.blogjava.net/nokiaguy/archive/2009/01/17/251722.html

    private static int findNode(Node headNode, int k)
    {
        Node p = headNode, p1 = headNode, p2 = null;
        int count = 0;  //  表示结点数
        while (p.nextNode != null)
        {
            p = p.nextNode;
            count++;
            //  遇到k的整数位个结点,进行分块
            if (count % k == 0)
            {                
                if (p2 != null)
                    p1 = p2;
                p2 = p;
            }
        }
        //  k超过链表结点数,未找到,返回0
        if (p2 == null)
        {
            return 0;
        }
        else
        {
            int mod = count % k;
            int offset = mod + 1;  // 任何情况下,最终结果都是p1指向的结点向后移动(mod + 1)个结点
            for (int i = 0; i < offset; i++)
                p1 = p1.nextNode;
            System.out.println(p1.data);
            return 1;
        }
    }

  回复  更多评论
  

# re: [算法]09考研数据结构试题解法 2009-01-17 22:48 DoubleH
@crtylr
@银河使者
恩,二位的想法其实是一样的,银河使者其实就是crtylr的复杂版。crtylr的意思应该是对头K个元素,只移动一个指针,然后一起移动直到第一个指针没法继续。  回复  更多评论
  

# re: [算法]09考研数据结构试题解法 2009-01-18 10:39 银河使者
是的,@crtylr的算法比较好,下面的具体的实现代码,很简单:
    private static int findNode(Node headNode, int k)
    {       
        Node p1 = headNode, p2 = headNode;
        for(int i = 0; i < k && p2.nextNode != null; i++)
            p2 = p2.nextNode;
        if(p2.nextNode == null) return 0;
        while(p2.nextNode != null)
        {
            p1 = p1.nextNode;
            p2 = p2.nextNode;
        }
        System.out.println(p1.nextNode.data);
        return 1;
    }   回复  更多评论
  

# re: [算法]09考研数据结构试题解法[未登录] 2009-01-20 19:14 hehe
这道题目好熟悉阿.. 呵呵
  回复  更多评论
  


只有注册用户登录后才能发表评论。


网站导航: