当前位置:   article > 正文

算法中要了解的图和树

算法 树和图

树和图

1. 什么是图?

图由顶点(vertex,node)和边(edge)组成。顶点就是代表对象,因为有时候题不会直接给顶点,而是某种对象,直接看成顶点即可。我们使用链接两顶点之间的线段来表示。顶点的集合V,边的集合是E,所以图记为G = (V,E), 连接两点u和v的边用e=(u,v)表示。

2. 图是一种特殊的图

树(tree)是包含n(n>=1)个结点,(n-1)条边的有穷集,其中:

(1)每个元素称为结点(node);

(2)有一个特定的结点被称为根结点或树根(root)。

(3)除根结点之外的其余数据元素被分为m(m≥0)个互不相交的集合T1,T2,……Tm-1,其中每一个集合Ti(1<=i<=m)本身也是一棵树,被称作原树的子树(subtree)。

3. 二叉树是一种特殊的树

二叉树(Binary tree)是树形结构的一个重要类型。许多实际问题抽象出来的数据结构往往是二叉树形式,即使是一般的树也能简单地转换为二叉树,而且二叉树的存储结构及其算法都较为简单,因此二叉树显得特别重要。二叉树特点是每个结点最多只能有两棵子树,且有左右之分 [1] 。

二叉搜索树: 又称二叉搜索树, 有序二叉树, 排序二叉树, 是指一颗空树或者有下列特性的二叉树:

  1. 若任意节点的左子树不空, 则左子树上所有节点的值均小于它的根节点的值;

  2. 若任意节点的右子树不空, 则右子树上所有节点的值均大于它的根节点的值

  3. 任意节点的左, 右子树也分别为二叉树找数

4. 树的不通编程语言的创建

java

  1. public class TreeNode {
  2. public int val;
  3. public TreeNode left, right;
  4. public TreeNode(int val) {
  5. this.val = val;
  6. this.left = null;
  7. this.right = null;
  8. }
  9. }

python

  1. class TreeNode:
  2. def __init__(self, val):
  3. self.val = val;
  4. sllf.left, self.right = None, None

C++

  1. struct TreeNode {
  2. int val;
  3. TreeNode *left;
  4. TreeNode *right;
  5. TreeNode(int x): val(x), left(NULL), right(NULL) {}
  6. }

5. 实战题目

  1. 前K个高频单词

给一非空的单词列表,返回前 k 个出现次数最多的单词。

返回的答案应该按单词出现频率由高到低排序。如果不同的单词有相同出现频率,按字母顺序排序。

示例 1:

输入: ["i", "love", "leetcode", "i", "love", "coding"], k = 2 输出: ["i", "love"] 解析: "i" 和 "love" 为出现次数最多的两个单词,均为2次。 注意,按字母顺序 "i" 在 "love" 之前。

示例 2:

输入: ["the", "day", "is", "sunny", "the", "the", "the", "sunny", "is", "is"], k = 4 输出: ["the", "is", "sunny", "day"] 解析: "the", "is", "sunny" 和 "day" 是出现次数最多的四个单词, 出现次数依次为 4, 3, 2 和 1 次。

方法1: 排序

Java

  1. class Solution {
  2. public List<String> topKFrequent(String[] words, int k) {}
  3. Map<String, Integer> count = new HashMap();
  4. for (String word: words) {
  5. count.put(word, count.getOrDefault(word, 0) + 1);
  6. }
  7. List<String> candidates = new ArrayList(count.keySet());
  8. Collections.sort(candidates, (w1, w2) -> count.get(w1).equals(count(.get(w2)) ? w1.compareTo(w2) : count.get(w2) - count.get(w1));
  9. return candidates.subList(0, k);
  10. }
  11. }

python

  1. class Solution(object):
  2. def topKFrequent(self, words, k):
  3. count = collections.Counter(words)
  4. candidates = count.keys()
  5. candidates.sort(key = lambda w: (-count[w], w))
  6. return candidates[:k]

2. 使用堆来实现

堆是一种非常好的方式来解决前K个最大元素或者最小元素的方法

java

  1. class Solution {
  2. public List<String> topKFrequent(String[] words, int k) {
  3. Map<String, Integer> count = new HashMap();
  4. // 先用HashMap缓存
  5. for (String word: words) {
  6. count.put(word, count.getOrDefault(word, 0) + 1);
  7. }
  8. // 定义一个堆的存储顺序, 头一定是最小元素
  9. PriorityQueue<String> heap = new PriorityQueue<String>(
  10. (w1, w2) -> count.get(w1).equals(count.get(w2) ? w2.comareTo(w1) : count.get(w1) - count.get(w2)
  11. );
  12. for (String word : count.keySet()) {
  13. // 入堆
  14. heap.offer(word);
  15. // 堆元素超过k个, 直接把顶点的元素出堆
  16. if (heap.size() > k) {
  17. heap.poll();
  18. }
  19. }
  20. List<String> ans = new ArrayList();
  21. while (!heap.isEmpty()) {
  22. ans.add(heap.poll());
  23. }
  24. // 出来以后是一个频率从小到大顺序, 需要倒转
  25. Collections.reverse(ans);
  26. return ans;
  27. }
  28. }
  • 在 Python 中,我们使用 heapq\heapify,它可以在线性时间内将列表转换为堆,从而简化了我们的工作。

  1. class Solution(object):
  2. def topKFrequent(self, words, k):
  3. count = collection.Counter(words)
  4. heap = [(-freq, word) for word, freq in count.items()]
  5. heapq.heapify(heap)
  6. return [heapq.heappop(heap)[1] for _ in xrange(k)]

6. 二叉树的遍历

1. 前序(Pre-order): 根-左-右

遍历以后的结果为: A  B C D E F G

代码:

  1. def preorder(self, root):
  2. if root:
  3. self.traverse_path.append(root.val)
  4. self.preorder(root.left)
  5. self.preorder(root.right)

2. 中序(In-order):  左-根-右

中序遍历是排序好的

遍历以后的结果为: D B E A F C G

代码:

  1. def inorder(self, root):
  2. if root:
  3. self.inorder(root.left)
  4. self.traverse_path.append(root.val)
  5. self.inorder(root.right)

3. 后序(Post-order): 左-右-根

遍历以后的结果为: D E B F G C A

代码:

  1. def postorder(self, root):
  2. if root:
  3. self.postorder(root.left)
  4. self.postorder(root.right)
  5. self.traverse_path.append(root.val)
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/567166
推荐阅读
相关标签
  

闽ICP备14008679号