网易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; } }