word-ladder

题目描述

Given two words (start and end), and a dictionary, find the length of shortest transformation sequence from start to end, such that:
Only one letter can be changed at a time
Each intermediate word must exist in the dictionary
For example,
Given:
start =“hit”
end =“cog”
dict =[“hot”,“dot”,“dog”,“lot”,“log”]
As one shortest transformation is"hit" -> “hot” -> “dot” -> “dog” -> “cog”,
return its length5.

Note:
Return 0 if there is no such transformation sequence.
All words have the same length.
All words contain only lowercase alphabetic characters.

主要mark对比下面几种做法,首先是最大复杂度为 n*n 的做法,以前很多时候都喜欢单独创建 int[] visit / int[][] visit / Map<Object,boolean> visit 来记录访问状态,其实很多时候很多场景都可以通过集合类(Set/Map/LinkedList)或者原数组来自维护访问状态,例如下面通过 HashSet<String> dict 来自维护访问状态。
第一种做法实现优点是简单直观,但是算法复杂度可能达不到要求:

import java.util.HashSet;
import java.util.Queue;
import java.util.LinkedList;
import java.util.Iterator;
public class Solution {
    public int ladderLength(String start, String end, HashSet<String> dict) {
        Queue<String> strQueue=new LinkedList<String>();
        strQueue.offer(end);
        dict.remove(end);
        int curLen=1;
        while(!strQueue.isEmpty()){
            int curRoundSize=strQueue.size();
            curLen=curLen+1;
            for(int i=0;i<curRoundSize;i++){
                String str=strQueue.poll();
                for(Iterator<String> it=dict.iterator();it.hasNext();){
                    String kStr=it.next();
                    if(matchSingleChange(str,kStr)){
                        it.remove();
                        strQueue.offer(kStr);
                        if(kStr.equals(start)){
                            return curLen;
                        }
                    }
                }
            }
        }
        return 0;
    }
    public boolean matchSingleChange(String str1,String str2){
        int len=str1.length();
        int charNum=0;
        for(int i=0;i<len;i++){
            if(str1.charAt(i)!=str2.charAt(i))
                charNum++;
        }
        if(charNum==0||charNum==1)
            return true;
        return false;
    }
}

另一种做法主要是通过 26*word.length() 单个字符替换来查找是否存在替换后的字符串,在dict量级比较大的时候优于第一种实现。

public int ladderLength(string start, string end, unordered_set<string>&dict)
{
    queue<string>Q;
    Q.push(start);
    int res = 1;
    while (!Q.empty())
    {
        int qsize = Q.size();
        while (qsize--)
        {
            string cur_front = Q.front();
            Q.pop();
            int size = cur_front.size();
            for (int i = 0; i < size; i++)
            {
                char ch = cur_front[i];
                for (int j = 0; j < 26; j++)
                {
                    cur_front[i] = 'a' + j;
                    if (cur_front == end)return res+1;
                    if (dict.find(cur_front) != dict.end())
                    {
                        Q.push(cur_front);
                        dict.erase(cur_front);
                    }
                }
                cur_front[i] = ch;
            }
        }
        res++;
    }
       return 0;
}

第三种利用双端HashSet,分为起始集合和结束集合,当起始集合中的单词变换一次后得到结束集合中的某词时可以结束。

https://www.nowcoder.com/profile/9249239/codeBookDetail?submissionId=12080096
import java.util.*;
public class Solution {
    public int ladderLength(String start, String end, HashSet<String> dict) {
        HashSet<String> beginSet=new HashSet<String>();
        HashSet<String> endSet=new HashSet<String>();
        HashSet<String> visited=new HashSet<String>();
         
        beginSet.add(start);
        endSet.add(end);
        visited.add(start);
        int res=1;
         
        while(!beginSet.isEmpty()&&!endSet.isEmpty()){
            //保证每次对较少数目的endSet做处理
            if(beginSet.size()>endSet.size()){
                HashSet<String> temp=beginSet;
                beginSet=endSet;
                endSet=temp;
            }
             
            HashSet<String> temp=new HashSet<String>();
             
            for(String str:beginSet){
                char[] chs=str.toCharArray();
                for(int i=0;i<chs.length;i++){
                    char old=chs[i];
                    for(char ch='a';ch<='z';ch++){
                        chs[i]=ch;
                        String cur=String.valueOf(chs);
                        if(endSet.contains(cur)){
                            return res+1;
                        }
                        if(!visited.contains(cur)&&dict.contains(cur)){
                            temp.add(cur);
                            visited.add(cur);
                        }
                    }
                    chs[i]=old;
                }
                 
            }
            beginSet=temp;
            res++;
        }
        return 0;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值