0801学习

    1. 单词替换-字节
      在英语中,我们有一个叫做 词根(root) 的概念,可以词根后面添加其他一些词组成另一个较长的单词——我们称这个词为 继承词(successor)。例如,词根an,跟随着单词 other(其他),可以形成新的单词 another(另一个)。
      现在,给定一个由许多词根组成的词典 dictionary 和一个用空格分隔单词形成的句子 sentence。你需要将句子中的所有继承词用词根替换掉。如果继承词有许多可以形成它的词根,则用最短的词根替换它。
      你需要输出替换之后的句子。
      示例 1:
      输入:dictionary = [“cat”,”bat”,”rat”], sentence = “the cattle was rattled by the battery”
      输出:”the cat was rat by the bat”

  1. public class PreWords
  2. {
  3. public char Char;
  4. public bool IsWord;
  5. public Dictionary<char, PreWords> Next = new Dictionary<char, PreWords>();
  6. public PreWords(char c, bool isWord)
  7. {
  8. Char = c;
  9. IsWord = isWord;
  10. }
  11. }
  12. private Dictionary<char, PreWords> __dictionary = new Dictionary<char, PreWords>();
  13. public string ReplaceWords(IList<string> dictionary, string sentence)
  14. {
  15. foreach (var str in dictionary)
  16. {
  17. var first = str[0];
  18. if (!__dictionary.TryGetValue(first, out var p))
  19. {
  20. p = new PreWords(first, false);
  21. __dictionary[first] = p;
  22. }
  23. for (int j = 0; j < str.Length;)
  24. {
  25. if (j == str.Length - 1)
  26. {
  27. p.IsWord = true;
  28. break;
  29. }
  30. if (!p.Next.TryGetValue(str[++j], out var next))
  31. {
  32. next = new PreWords(str[j], false);
  33. p.Next[str[j]] = next;
  34. }
  35. p = next;
  36. }
  37. }
  38. var successores = sentence.Split();
  39. var sb = new StringBuilder();
  40. foreach (var successor in successores)
  41. {
  42. __ReplaceStr(successor, sb);
  43. }
  44. sb.Remove(sb.Length - 1, 1);
  45. return sb.ToString();
  46. }
  47. private void __ReplaceStr(string successor, StringBuilder sb)
  48. {
  49. if (successor.Length > 0)
  50. {
  51. var first = successor[0];
  52. if (__dictionary.TryGetValue(first, out var p))
  53. {
  54. if (p.IsWord)
  55. {
  56. sb.Append(first);
  57. sb.Append(" ");
  58. }
  59. else
  60. {
  61. var index = 1;
  62. var find = false;
  63. for (; index < successor.Length; index++)
  64. {
  65. if (p.Next.TryGetValue(successor[index], out var next))
  66. {
  67. p = next;
  68. if (!p.IsWord) continue;
  69. find = true;
  70. }
  71. break;
  72. }
  73. sb.Append(find ? successor.Substring(0, index + 1) : successor);
  74. sb.Append(" ");
  75. }
  76. }
  77. else
  78. {
  79. sb.Append(successor);
  80. sb.Append(" ");
  81. }
  82. }
  83. }
  84. public string ReplaceWords2(IList<string> dictionary, string sentence)
  85. {
  86. var setDictionary = new HashSet<string>(dictionary);
  87. var successors = sentence.Split();
  88. for (var i = 0; i < successors.Length; i++)
  89. {
  90. var successor = successors[i];
  91. for (var j = 0; j < successor.Length; j++)
  92. {
  93. var subSuccessor = successor.Substring(0, j + 1);
  94. if (!setDictionary.Contains(subSuccessor)) continue;
  95. successors[i] = subSuccessor;
  96. break;
  97. }
  98. }
  99. return string.Join(' ', successors);
  100. }

    1. LRU 缓存-mihayou
      请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。
      实现 LRUCache 类:
      LRUCache(int capacity) 以 正整数 作为容量 capacity 初始化 LRU 缓存
      int get(int key) 如果关键字 key 存在于缓存中,则返回关键字的值,否则返回 -1 。
      void put(int key, int value) 如果关键字 key 已经存在,则变更其数据值 value ;如果不存在,则向缓存中插入该组 key-value 。如果插入操作导致关键字数量超过 capacity ,则应该 逐出 最久未使用的关键字。
      函数 get 和 put 必须以 O(1) 的平均时间复杂度运行。

  1. public class LinkList
  2. {
  3. public int Value;
  4. public int Key;
  5. public LinkList Pre;
  6. public LinkList Next;
  7. public LinkList(int key, int value)
  8. {
  9. Value = value;
  10. Key = key;
  11. }
  12. }
  13. public class LRUCache
  14. {
  15. private Dictionary<int, LinkList> __cache = new Dictionary<int, LinkList>();
  16. private LinkList __head = null;
  17. private LinkList __tail = null;
  18. private int __capacity;
  19. public LRUCache(int capacity)
  20. {
  21. __capacity = capacity;
  22. //虚拟头结点以及尾节点
  23. __head = new LinkList(-1, -1);
  24. __tail = new LinkList(-1, -1);
  25. __head.Next = __tail;
  26. __tail.Pre = __head;
  27. }
  28. public int Get(int key)
  29. {
  30. if (__cache.TryGetValue(key, out var v))
  31. {
  32. __Update(v);
  33. return v.Value;
  34. }
  35. return -1;
  36. }
  37. public void Put(int key, int value)
  38. {
  39. if (__cache.TryGetValue(key, out var linkList))
  40. {
  41. __Update(linkList);
  42. linkList.Value = value;
  43. }
  44. else
  45. {
  46. //当容量满的时候,移除最后一个节点
  47. if (__cache.Count == __capacity)
  48. {
  49. //__tail之前大节点才是真正大尾节点
  50. var last = __tail.Pre;
  51. __cache.Remove(last.Key);
  52. var lastPre = last.Pre;
  53. lastPre.Next = __tail;
  54. __tail.Pre = lastPre;
  55. }
  56. //插入新节点,应该插在虚拟头节点的next
  57. var next = __head.Next;
  58. linkList = new LinkList(key, value)
  59. {
  60. Next = next,
  61. };
  62. next.Pre = linkList;
  63. linkList.Pre = __head;
  64. __head.Next = linkList;
  65. }
  66. __cache[key] = linkList;
  67. }
  68. private void __Update(LinkList l)
  69. {
  70. if (__head.Next == l)
  71. {
  72. return;
  73. }
  74. //先把原先的连接起来
  75. var pre = l.Pre;
  76. pre.Next = l.Next;
  77. l.Next.Pre = pre;
  78. //把l插入header下一个节点
  79. var headNext = __head.Next;
  80. headNext.Pre = l;
  81. l.Pre = __head;
  82. l.Next = headNext;
  83. __head.Next = l;
  84. }
  85. }
  • 460-LFU 缓存
    请你为 最不经常使用(LFU)缓存算法设计并实现数据结构。
    实现 LFUCache 类:
    LFUCache(int capacity) - 用数据结构的容量 capacity 初始化对象
    int get(int key) - 如果键 key 存在于缓存中,则获取键的值,否则返回 -1 。
    void put(int key, int value) - 如果键 key 已存在,则变更其值;如果键不存在,请插入键值对。当缓存达到其容量 capacity 时,则应该在插入新项之前,移除最不经常使用的项。在此问题中,当存在平局(即两个或更多个键具有相同使用频率)时,应该去除 最近最久未使用 的键。
    为了确定最不常使用的键,可以为缓存中的每个键维护一个 使用计数器 。使用计数最小的键是最久未使用的键。
    当一个键首次插入到缓存中时,它的使用计数器被设置为 1 (由于 put 操作)。对缓存中的键执行 get 或 put 操作,使用计数器的值将会递增。
    函数 get 和 put 必须以 O(1) 的平均时间复杂度运行。

  1. public class Node
  2. {
  3. public int Key;
  4. public int Value;
  5. public int Cnt;
  6. public Node Pre;
  7. public Node Next;
  8. public Node(int key, int value)
  9. {
  10. Key = key;
  11. Value = value;
  12. Cnt = 0;
  13. }
  14. }
  15. public class LFUCache
  16. {
  17. private Dictionary<int, Node> __cache = new Dictionary<int, Node>();
  18. private Node __head;
  19. private Node __tail;
  20. private int __capacity;
  21. public LFUCache(int capacity)
  22. {
  23. __capacity = capacity;
  24. __head = new Node(-1, -1);
  25. __tail = new Node(-1, -1);
  26. __head.Next = __tail;
  27. __head.Cnt = Int32.MaxValue;
  28. __tail.Pre = __head;
  29. __tail.Cnt = Int32.MinValue;
  30. }
  31. public int Get(int key)
  32. {
  33. if (__cache.TryGetValue(key, out var node))
  34. {
  35. __RefreshLinkList(node);
  36. return node.Value;
  37. }
  38. return -1;
  39. }
  40. public void Put(int key, int value)
  41. {
  42. if (__capacity == 0)
  43. {
  44. return;
  45. }
  46. if (__cache.TryGetValue(key, out var node))
  47. {
  48. node.Value = value;
  49. __RefreshLinkList(node);
  50. }
  51. else
  52. {
  53. if (__cache.Count == __capacity)
  54. {
  55. var last = __tail.Pre;
  56. last.Pre.Next = __tail;
  57. __tail.Pre = last.Pre;
  58. __cache.Remove(last.Key);
  59. }
  60. node = new Node(key, value);
  61. var temp = __tail.Pre;
  62. temp.Next = node;
  63. node.Next = __tail;
  64. __tail.Pre = node;
  65. node.Pre = temp;
  66. __RefreshLinkList(node);
  67. __cache[key] = node;
  68. }
  69. }
  70. private void __RefreshLinkList(Node node)
  71. {
  72. node.Cnt++;
  73. if (node.Pre.Cnt > node.Cnt)
  74. {
  75. return;
  76. }
  77. var pre = node.Pre;
  78. pre.Next = node.Next;
  79. node.Next.Pre = pre;
  80. pre = __GetNode(pre, node);
  81. var next = pre.Next;
  82. node.Next = next;
  83. pre.Next = node;
  84. next.Pre = node;
  85. node.Pre = pre;
  86. }
  87. private Node __GetNode(Node pre, Node cur)
  88. {
  89. var tempHead = __head;
  90. while (true)
  91. {
  92. if (pre.Cnt <= cur.Cnt)
  93. {
  94. pre = pre.Pre;
  95. }
  96. else
  97. {
  98. return pre;
  99. }
  100. if (tempHead.Cnt > cur.Cnt)
  101. {
  102. tempHead = tempHead.Next;
  103. }
  104. else
  105. {
  106. return tempHead.Pre;
  107. }
  108. }
  109. }
  110. }

双向链表

  1. public class LFUCache2
  2. {
  3. class DoubleLinkList
  4. {
  5. public int Cnt;
  6. public Node Head;
  7. public Node Tail;
  8. public DoubleLinkList(int cnt)
  9. {
  10. Head = new Node(-1, -1);
  11. Tail = new Node(-1, -1);
  12. Head.Next = Tail;
  13. Tail.Pre = Head;
  14. Cnt = cnt;
  15. }
  16. public void Add(Node node)
  17. {
  18. var next = Head.Next;
  19. node.Next = next;
  20. Head.Next = node;
  21. next.Pre = node;
  22. node.Pre = Head;
  23. }
  24. public void Remove(Node node)
  25. {
  26. var pre = node.Pre;
  27. pre.Next = node.Next;
  28. node.Next.Pre = pre;
  29. }
  30. }
  31. private Dictionary<int, Node> __cache = new Dictionary<int, Node>();
  32. private Dictionary<int, DoubleLinkList> __cacheCnt = new Dictionary<int, DoubleLinkList>();
  33. private int __capacity;
  34. private int __minCnt;
  35. public LFUCache2(int capacity)
  36. {
  37. __capacity = capacity;
  38. __minCnt = 1;
  39. }
  40. public int Get(int key)
  41. {
  42. if (__capacity == 0)
  43. {
  44. return -1;
  45. }
  46. if (__cache.TryGetValue(key, out var node))
  47. {
  48. __UpdateCnt(node);
  49. return node.Value;
  50. }
  51. return -1;
  52. }
  53. public void Put(int key, int value)
  54. {
  55. if (__capacity == 0)
  56. {
  57. return;
  58. }
  59. if (__cache.TryGetValue(key, out var node))
  60. {
  61. node.Value = value;
  62. __UpdateCnt(node);
  63. }
  64. else
  65. {
  66. if (__cache.Count == __capacity)
  67. {
  68. if (__cacheCnt.TryGetValue(__minCnt, out var doubleList) && doubleList.Head.Next != doubleList.Tail)
  69. {
  70. var t = doubleList.Tail.Pre;
  71. __cache.Remove(t.Key);
  72. t.Pre.Next = doubleList.Tail;
  73. doubleList.Tail.Pre = t.Pre;
  74. }
  75. }
  76. node = new Node(key, value);
  77. node.Cnt++;
  78. __InsertNode(node);
  79. __cache[key] = node;
  80. __minCnt = 1;
  81. }
  82. }
  83. private void __UpdateCnt(Node node)
  84. {
  85. if (__cacheCnt.TryGetValue(node.Cnt, out var linkList))
  86. {
  87. linkList.Remove(node);
  88. if (__minCnt == node.Cnt && linkList.Head.Next == linkList.Tail)
  89. {
  90. __minCnt++;
  91. }
  92. }
  93. node.Cnt++;
  94. __InsertNode(node);
  95. }
  96. private void __InsertNode(Node node)
  97. {
  98. if (__cacheCnt.TryGetValue(node.Cnt, out var linkList))
  99. {
  100. linkList.Add(node);
  101. }
  102. else
  103. {
  104. linkList = new DoubleLinkList(node.Cnt);
  105. linkList.Add(node);
  106. __cacheCnt[node.Cnt] = linkList;
  107. }
  108. }
  109. }
0810学习
0731学习