leetcode 279 组成整数的最小平方数数量
原题内容:
For example, given n = 12, return 3 because 12 = 4 + 4 + 4; given n = 13,
return 2 because 13 = 4 + 9.
解法一:可以将每个整数看成图中的一个节点,如果两个整数之差为一个平方数,那么这两个整数所在的节点就有一条边。
要求解最小的平方数数量,就是求解从节点 n 到节点 0 的最短路径。
package leetcode209;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
public class Solution {
/**
* @Author chengxingyuan
* @Description 计算平方数个数
* @Date 10:05 2019/8/29
* @Param
* @return
*/
public int numSquares(int n){
List<Integer> squares =generateSquares(n);
Queue<Integer> queue = new LinkedList<>();
queue.add(n);
//标记从当前第n个节点出发,访问节点差值为平方数的标记
boolean[] marked = new boolean[n+1];
marked[n] = true;
int level = 0;
while(!queue.isEmpty()){
int size = queue.size();
level++;
while (size-- >0){
//取出头元素,在队列中删除
int cur = queue.poll();
for (int s:squares){
int next = cur-s;
if (next<0){
break;
}if (next ==0){
//如果差值为0,说明不能拆分,返回差值访问次数
return level;
}if (marked[next]){
//已经访问过
continue;
}
marked[next] = true;
queue.add(next);
}
}
}
return n;
}
/**
* @Author chengxingyuan
* @Description 生成小于n的平方数个数
* @Date 10:38 2019/8/29
* @Param
* @return
*/
private List<Integer> generateSquares(int n) {
List<Integer> squares = new ArrayList<>();
int square = 1;
int diff = 3;
while (square <= n) {
squares.add(square);
square += diff;
diff += 2;
}
return squares;
}
}
leetcode 219 最短单词路径
Input:
beginWord = "hit"
endWord = "cog"
wordList = ["hot","dot","dog","lot","log"]
Output: 0
Explanation: The endWord "cog" is not in wordList, therefore no possible transformation.
题目描述:找出一条从 beginWord 到 endWord 的最短路径,每次移动规定为改变一个字符,并且改变之后的字符串必须在 wordList 中。
public int ladderLength(String beginWord, String endWord, List<String> wordList) {
wordList.add(beginWord);
int N = wordList.size();
int start = N - 1;
int end = 0;
while (end < N && !wordList.get(end).equals(endWord)) {
end++;
}
if (end == N) {
return 0;
}
List<Integer>[] graphic = buildGraphic(wordList);
return getShortestPath(graphic, start, end);
}
//建图
private List<Integer>[] buildGraphic(List<String> wordList) {
int N = wordList.size();
List<Integer>[] graphic = new List[N];
//把各个需要转换的序列分成几个list 比如
"hit" -> "hot" -> "dot" -> "dog" -> "cog",
"hot" -> "dot" -> "dog"
依次判断从当前关键字出发是否能与下个关键字连接
for (int i = 0; i < N; i++) {
graphic[i] = new ArrayList<>();
for (int j = 0; j < N; j++) {
if (isConnect(wordList.get(i), wordList.get(j))) {
graphic[i].add(j);
}
}
}
return graphic;
}
private boolean isConnect(String s1, String s2) {
int diffCnt = 0;
for (int i = 0; i < s1.length() && diffCnt <= 1; i++) {
if (s1.charAt(i) != s2.charAt(i)) {
diffCnt++;
}
}
return diffCnt == 1;
}
//获取最短路径
private int getShortestPath(List<Integer>[] graphic, int start, int end) {
Queue<Integer> queue = new LinkedList<>();
boolean[] marked = new boolean[graphic.length];
queue.add(start);
marked[start] = true;
int path = 1;
//沿用上一题的做法,不同的地方在于这里已经保存了第i个节点的权重,不需要进行计算,判断是否已经在本次序列中访问过这个节点即可
while (!queue.isEmpty()) {
int size = queue.size();
path++;
while (size-- > 0) {
int cur = queue.poll();
for (int next : graphic[cur]) {
if (next == end) {
return path;
}
if (marked[next]) {
continue;
}
marked[next] = true;
queue.add(next);
}
}
}
return 0;
}