网易2017 跳石板

http://www.nowcoder.com/questionTerminal/4284c8f466814870bae7799a07d49ec8

 

最简单的想法就是广度优先搜索,对节点进行分层

public class JumpStoneRoad {
    private int N = 4;
    private int M = 24;

    public List<Integer> getAllStepNumber(int number) {
        ArrayList<Integer> arrayList = new ArrayList<Integer>();
        for (int i = 2; i <= number/2; i++) {
            if (number % i == 0) {
                arrayList.add(i);
            }
        }
        Collections.sort(arrayList, new Comparator<Integer>() {
            public int compare(Integer o1, Integer o2) {
                return o2-o1;
            }
        });
        return arrayList;
    }

    @Test
    public void testMinStep(){
        Queue<Node> queue = new LinkedList<Node>();
        Node node = new Node();
        node.val=N;
        node.level=0;
        queue.add(node);
        ok:
        while(!queue.isEmpty()){
            Node currentNode = queue.poll();
            for(int x:getAllStepNumber(currentNode.val)){
                int tmp= currentNode.val+x;

               if(tmp <=M) {
                   Node tmpNode = new Node();
                   tmpNode.level = currentNode.level+1;
                   tmpNode.val = tmp;
                   if (tmp==M){
                       System.out.println(tmpNode.level);
                       break ok;
                   }
                   queue.offer(tmpNode);
               }
            }
        }
        if(M==N){
            System.out.println(1);
        }else if(queue.isEmpty()){
            System.out.println(-1);
        }

    }

    class Node {
        public int val;
        public int level;
    }
}

用上面的算法举例

 

首先改变下约数的计算方法,从2遍历到number/2 是没有必要的,

最好的办法是 从2 遍历到 number的开平方,然后用number来除以i 获得另外一个对应的公约数

例如12的公约数是  2 3 4 6

可以分成 2 3 跟 4 6  因为他们都是相互对应的,且2 3 两个数的平方都小于 12 ,这样对计算1000以上的公约数是十分有效的

(讲道理这真是个数学题,之前我还只会傻傻的从0遍历到number/2 O(N),找到所有的公约数,没想到人家有O(logN)的算法)

public List<Integer> getAllStepNumber(int number) {
        ArrayList<Integer> arrayList = new ArrayList<Integer>();
        for (int i = 2; i*i <= number; i++) {
            if (number % i == 0) {
                arrayList.add(number/i);
                arrayList.add(i);
            }
        }
        Collections.sort(arrayList, new Comparator<Integer>() {
            public int compare(Integer o1, Integer o2) {
                return o2-o1;
            }
        });
        return arrayList;
    }

 

 

拿4->24为例子

 

 

这是广度搜索

 

下面的是4—>24的广度搜索,

很明显双向的箭头代表存在重复搜索,如果题目是4->24,搜索的时间不会很长,上面的算法是完全可行的。

但是题目如果改成 4->1000, 这样构成的 树 是十分庞大的,这样搜索起来的时间就会相当长

 

 

 

下面说我的一个想法也是从别人那里抄来的,对上图存在双向箭头的点,要解决重复搜索,最简单的方法就是对其进行标记,这样就不会存在双向箭头了

建立一个dst[M+1]标记,如果标记为0,就计算,不为0就跳过

package com.net163.question;

import org.junit.Test;

import java.util.*;

/**
 * Created by Administrator on 2016/11/11 0011.
 */
public class JumpStoneRoad {
    private int N = 4; 
    private int M = 10000;//测试数据
  
    public List<Integer> getAllStepNumber(int number) {
        ArrayList<Integer> arrayList = new ArrayList<Integer>();
        for (int i = 2; i * i <= number; i++) {
            if (number % i == 0) {
                arrayList.add(number / i);
                arrayList.add(i);
            }
        }
        Collections.sort(arrayList, new Comparator<Integer>() {
            public int compare(Integer o1, Integer o2) {
                return o2 - o1;
            }
        });
        return arrayList;
    }

    @Test
    public void testMinStep() {

        int dst[] = new int[M+1];
        Queue<Node> queue = new LinkedList<Node>();
        Node node = new Node();
        node.val = N;//初始化Node为N
        node.level = 0;//第0层
        queue.add(node);
        ok:
        while (!queue.isEmpty()) {
            Node currentNode = queue.poll();
            for (int x : getAllStepNumber(currentNode.val)) {
                int tmp = currentNode.val + x;
                if (tmp <= M && dst[tmp] == 0) {
                    dst[tmp] = 1;
                    Node tmpNode = new Node();
                    tmpNode.level = currentNode.level + 1;
                    tmpNode.val = tmp;
                    if (tmp == M) {
                        System.out.println(tmpNode.val);
                        System.out.println(tmpNode.level);
                        break ok;
                    }
                    queue.offer(tmpNode);
                }
            }
        }
        if (M == N) {
            System.out.println(1);
        } else if (queue.isEmpty()) {
            System.out.println(-1);
        }

    }

    class Node {
        public int val;
        public int level;
    }
}

 

posted on 2016-11-11 10:34  winters86  阅读(185)  评论(0编辑  收藏  举报