LeetCode_Word Ladder

6 篇文章 0 订阅
3 篇文章 0 订阅

原题:

Given two words (start and end), and a dictionary, find the length of shortest transformation sequence from start to end, such that:

  1. Only one letter can be changed at a time
  2. 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 length 5.

Note:

  • Return 0 if there is no such transformation sequence.
  • All words have the same length.
  • All words contain only lowercase alphabetic characters.
题意是:给出两个字符串start和end以及一个字符串集合dict,要求从start变换到end所需的最小步骤。变换规则是:每次只能改变字符串中的一个字符,而且改变后形成的新的字符串要是字典dict中的字符串。

刚看这题可能没有思路,但是把变换过程在纸上画画之后就明白怎么做了。以下是题目的抽象图。


即从图上找寻从起始节点到目标节点的最短路径问题。这是图的遍历问题,使用的方法无非BFS和DFS,要找最短路径,DFS只会一路到底,无疑BFS最合适。用BFS遍历图,一旦碰到目标节点即退出,此时路径即是最短路径。

注意:

(1)BFS搜索应该用队列来模拟;

(2)应该用一个数组类型的数据结构来记录已被遍历的节点,为求速度,可以使用unordered_set或set(竟然会超时可怜);

(3)遍历时,应该将与某个节点相邻的未访问节点push进队列中,但怎么知道两个节点相邻?一个个搜索比较会超时,网上有一种很巧妙的方法,即依次将节点string的第i位变换(26次)然后在字典中查找变换后的节点是否在字典中(用的unordered_set数据结构,查找时间为常数),相同的话push进队列;

(4)节点不仅要记录string,还要记录其在遍历中是第几步,应该用一个struct封装;

好了上代码:

class Solution {
public:
	struct Node{
		string str;
		int count;
		Node(string s, int n) :str(s), count(n){}
	};
public:
	int ladderLength(string start, string end, unordered_set<string> &dict) 
	{
		if (start == end)
			return 1;
		if (isNeibours(start, end))
			return 2;
		visited.clear();
		while (!que.empty())
			que.pop();
		que.push(Node(start, 1));
		int res = 0;
		while (!que.empty())
		{
			Node NowNode(que.front());
			if (isNeibours(NowNode.str, end))
			{
				res = NowNode.count + 1;
				break;
			}
			que.pop();
			for (int i = 0; i < NowNode.str.size(); ++i)
			{
				for (int j = 0; j < 26; ++j)
				{
					string temp = NowNode.str;
					temp[i] = 'a' + j;
					if (temp != NowNode.str && dict.find(temp) != dict.end() && visited.find(temp) == visited.end())
					{
						que.push(Node(temp,NowNode.count+1));
						visited.insert(temp);
					}	
				}
			}
		}
		return res;
	}
private:
	bool isNeibours(string s1, string s2)
	{
		int count = 0;
		for (int i = 0; i < s1.size(); ++i)
		{
			if (s1[i] != s2[i])
				++count;
			if (count > 1)
				return false;
		}
		return true;
	}
private:
	unordered_set<string> visited;
	queue<Node> que;
};


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
题目描述: 给定一个字符串,请将字符串里的字符按照出现的频率降序排列。 示例 1: 输入: "tree" 输出: "eert" 解释: 'e'出现两次,'r'和't'都只出现一次。因此'e'必须出现在'r'和't'之前。此外,"eetr"也是一个有效的答案。 示例 2: 输入: "cccaaa" 输出: "cccaaa" 解释: 'c'和'a'都出现三次。此外,"aaaccc"也是有效的答案。注意"cacaca"是不正确的,因为相同的字母必须放在一起。 示例 3: 输入: "Aabb" 输出: "bbAa" 解释: 此外,"bbaA"也是一个有效的答案,但"Aabb"是不正确的。注意'A'和'a'被认为是两种不同的字符。 Java代码如下: ``` import java.util.*; public class Solution { public String frequencySort(String s) { if (s == null || s.length() == 0) { return ""; } Map<Character, Integer> map = new HashMap<>(); for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); map.put(c, map.getOrDefault(c, 0) + 1); } List<Map.Entry<Character, Integer>> list = new ArrayList<>(map.entrySet()); Collections.sort(list, (o1, o2) -> o2.getValue() - o1.getValue()); StringBuilder sb = new StringBuilder(); for (Map.Entry<Character, Integer> entry : list) { char c = entry.getKey(); int count = entry.getValue(); for (int i = 0; i < count; i++) { sb.append(c); } } return sb.toString(); } } ``` 解题思路: 首先遍历字符串,使用HashMap记录每个字符出现的次数。然后将HashMap转换为List,并按照出现次数从大到小进行排序。最后遍历排序后的List,将每个字符按照出现次数依次添加到StringBuilder中,并返回StringBuilder的字符串形式。 时间复杂度:O(nlogn),其中n为字符串s的长度。遍历字符串的时间复杂度为O(n),HashMap和List的操作时间复杂度均为O(n),排序时间复杂度为O(nlogn),StringBuilder操作时间复杂度为O(n)。因此总时间复杂度为O(nlogn)。 空间复杂度:O(n),其中n为字符串s的长度。HashMap和List的空间复杂度均为O(n),StringBuilder的空间复杂度也为O(n)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值