程序员代码面试指南刷题--第五章.字符串的转换路径问题

题目描述
给定两个字符串,记为start和to,再给定一个字符串列表list,list中一定包含to,list中没有重复的字符串。所有的字符串都是小写的。规定start每次只能改变一个字符,最终的目标是彻底变成to,但是每次变成新字符串必须在list中存在。请返回所有的最短的变换路径(按照字典序最小的顺序输出)。
输入描述:

输出包含多行,第一行包含一个整数n(1≤n≤5000),代表list的中字符串的个数,第二行中包含两个字符串,分别代表start和to。接下来n行,每行一个字符串,代表lis[i](保证字符串长度都为3)。

输出描述:

如果存在转换的路径,请先输出“YES”,然后按照字典序最小的顺序输出所有路径。如果不存在请输出“NO”。

示例1

输入

8
abc cab
cab
acc
cbc
ccc
cac
cbb
aab
abb

输出

YES
abc -> abb -> aab -> cab
abc -> abb -> cbb -> cab
abc -> cbc -> cac -> cab
abc -> cbc -> cbb -> cab

解法一:构建nexts,构建dis,深度遍历

import java.io.*;
import java.util.*;
public class Main{
    public static void main(String[] args) throws Exception{
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int len = Integer.parseInt(br.readLine());
        String[] info = br.readLine().trim().split(" ");
        List<String> list = new ArrayList<>();
        for(int i=0;i<len;i++){
            list.add(br.readLine().trim());                    
        }
        List<List<String>> res = getRes(list,info[0],info[1]);
        Collections.sort(res,new Comparator<List<String>>() {
			@Override
			public int compare(List<String> o1, List<String> o2) {
				for(int i=0;i<o1.size()&&i<o2.size();i++) {
					if(o1.get(i).compareTo(o2.get(i))<0) {
						return -1;
					}else if(o1.get(i).compareTo(o2.get(i))>0){
						return 1;
					}
				}
				return o1.size()>o2.size()?1:-1;
			}
		});


        if(res.size()>0){
            System.out.println("YES");
            for(List<String> l:res){
                StringBuilder sb = new StringBuilder();
                for(String str:l){
                    sb.append(str+" -> ");    
                }
                String print = sb.toString();
                System.out.println(print.substring(0,print.length()-4));
            }
        }else{
            System.out.println("NO");
        }
    }
    public static List<List<String>> getRes(List<String> list,String start,String to){
        list.add(start);
        HashMap<String,ArrayList<String>> nexts = getNexts(list);
        HashMap<String,Integer> dis = getDis(start,nexts);
        LinkedList<String> sol = new LinkedList<>();
        List<List<String>> res = new ArrayList<>();
        getShortPath(start,to,nexts,dis,sol,res);
        return res;
    }
    public static void getShortPath(String cur,String to,
                                    HashMap<String,ArrayList<String>> nexts,
                                    HashMap<String,Integer> dis,
                                    LinkedList<String> sol,
                                    List<List<String>> res
                                   ){
        sol.add(cur);
        if(cur.equals(to)){
            res.add(new LinkedList<String>(sol));
        }else{
            for(String str:nexts.get(cur)){
                if(dis.get(cur)==dis.get(str)-1){
                     getShortPath(str,to,nexts,dis,sol,res);   
                }
            }
        }
        sol.pollLast();
    }
    public static HashMap<String,Integer> getDis(String start,HashMap<String,ArrayList<String>> nexts){
        HashMap<String,Integer> map = new HashMap<>();
        map.put(start,0);
        Queue<String> q = new LinkedList<>();
        Set<String> set = new HashSet<>();
        q.add(start);
        set.add(start);
        while(!q.isEmpty()){
            String cur = q.poll();
            for(String str:nexts.get(cur)){
                if(!set.contains(str)){
                    map.put(str,map.get(cur)+1);
                    q.add(str);
                    set.add(str);
                }
            }
        }
        return map;
    }
    public static HashMap<String,ArrayList<String>> getNexts(List<String> list){
        HashSet<String> set = new HashSet<>(list);
        HashMap<String,ArrayList<String>> res = new HashMap<>();
        for(int i=0;i<list.size();i++){
            res.put(list.get(i),new ArrayList<String>());    
        }
        for(int i=0;i<list.size();i++){
            res.put(list.get(i),getNext(list.get(i),set));
        }
        return res;
    }
    public static ArrayList<String> getNext(String str,HashSet<String> set){
        char[] arr = str.toCharArray();
        ArrayList<String> list = new ArrayList<>();
        for(int i=0;i<arr.length;i++){
            for(char c='a';c<='z';c++){
                if(arr[i]!=c){
                    char tmp = arr[i];
                    arr[i] = c;
                    if(set.contains(String.valueOf(arr))){
                        list.add(String.valueOf(arr));        
                    }
                    arr[i] = tmp;
                }
            }
        }
        return list;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值