From b531d06a0204dac2c5caed51db9f19dc569c5e2b Mon Sep 17 00:00:00 2001 From: markilue <745518019@qq.com> Date: Wed, 5 Apr 2023 13:26:24 +0800 Subject: [PATCH] =?UTF-8?q?leecode=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../markilue/leecode/hot100/T55_LFUCache.java | 217 ++++++++++++++++++ .../listnode/selftry/DeleteDuplicatesII.java | 33 ++- .../leecode/listnode/selftry/LRUCache.java | 117 ++++++++++ .../leecode/listnode/selftry/ReorderList.java | 51 ++++ .../listnode/selftry/reverseKGroup.java | 52 ++++- .../leecode/listnode/selftry/swapPairs.java | 70 +++--- .../com/markilue/leecode/test/ThreeSum.java | 60 +++++ .../java/com/markilue/leecode/test/test.java | 17 ++ 8 files changed, 575 insertions(+), 42 deletions(-) create mode 100644 Leecode/src/main/java/com/markilue/leecode/hot100/T55_LFUCache.java create mode 100644 Leecode/src/main/java/com/markilue/leecode/listnode/selftry/LRUCache.java create mode 100644 Leecode/src/main/java/com/markilue/leecode/listnode/selftry/ReorderList.java create mode 100644 Leecode/src/main/java/com/markilue/leecode/test/ThreeSum.java diff --git a/Leecode/src/main/java/com/markilue/leecode/hot100/T55_LFUCache.java b/Leecode/src/main/java/com/markilue/leecode/hot100/T55_LFUCache.java new file mode 100644 index 0000000..e0ddc8f --- /dev/null +++ b/Leecode/src/main/java/com/markilue/leecode/hot100/T55_LFUCache.java @@ -0,0 +1,217 @@ +package com.markilue.leecode.hot100; + +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + +/** + *@BelongsProject: Leecode + *@BelongsPackage: com.markilue.leecode.hot100 + *@Author: markilue + *@CreateTime: 2023-03-13 17:13 + *@Description: + * TODO 力扣146题 LRU缓存: + * 请你为 最不经常使用(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) 的平均时间复杂度运行。 + *@Version: 1.0 + */ +public class T55_LFUCache { + + Map cache; + Map freqMap; + int capacity; + int min; + int size; + + + public T55_LFUCache() { + } + + + public T55_LFUCache(int capacity) { + this.capacity = capacity; + cache = new HashMap<>(); + freqMap = new HashMap<>(); + min = 0; + size = 0; + + } + + public int get(int key) { + Node node = cache.get(key); + if (node == null) { + return -1; + } + freqInc(node); + return node.value; + } + + public void put(int key, int value) { + if (capacity == 0) { + return; + } + Node node = cache.get(key); + if (node != null) { + //更新即可 + node.value = value; + freqInc(node); + } else { + if (size == capacity) { + //如果已经等于了就要进行删除 + removeNode(); + + } + Node node1 = new Node(key, value, 1); + cache.put(key, node1); + addNode(node1); + size++; + } + + } + + public void freqInc(Node node) { + int freq = node.freq; + NodeList nodeList = freqMap.get(freq); + if (nodeList != null) { + nodeList.removeNode(node); + } else { + nodeList = new NodeList(); + freqMap.put(freq, nodeList); + } + if (freq == min && nodeList.isEmpty()) { + min = freq + 1; + } + node.freq++; + NodeList nodeList1 = freqMap.get(freq + 1); + if (nodeList1 == null) { + nodeList1 = new NodeList(); + freqMap.put(freq + 1, nodeList1); + } + nodeList1.addNode(node); + + } + + public void addNode(Node node) { + int freq = node.freq; + NodeList nodeList = freqMap.get(freq); + if (nodeList == null) { + nodeList = new NodeList(); + freqMap.put(freq, nodeList); + } + nodeList.addNode(node); + min = 1; + + } + + public void removeNode() { + NodeList nodeList = freqMap.get(min); + + Node node = nodeList.removeNode(); + cache.remove(node.key); + size--; + } + + + @Test + public void test() { + T55_LFUCache lRUCache = new T55_LFUCache(2); + lRUCache.put(1, 1); // 缓存是 {1=1} + lRUCache.put(2, 2); // 缓存是 {1=1, 2=2} + System.out.println(lRUCache.get(1)); // 返回 1 + lRUCache.put(3, 3); // 该操作会使得关键字 2 作废,缓存是 {1=1, 3=3} + System.out.println(lRUCache.get(2)); // 返回 -1 (未找到) + lRUCache.put(4, 4); // 该操作会使得关键字 1 作废,缓存是 {4=4, 3=3} + System.out.println(lRUCache.get(1)); // 返回 -1 (未找到) + System.out.println(lRUCache.get(3)); // 返回 3 + System.out.println(lRUCache.get(4)); // 返回 4 + } + + public class Node { + + int key; + int value; + int freq; + Node pre; + Node next; + + + public Node() { + } + + public Node(int key, int value) { + this.key = key; + this.value = value; + this.freq = 1; + } + + public Node(int key, int value, int freq) { + this.key = key; + this.value = value; + this.freq = freq; + } + + public Node(int key, int value, int freq, Node pre, Node next) { + this.key = key; + this.value = value; + this.freq = freq; + this.pre = pre; + this.next = next; + } + + + } + + + public class NodeList { + + Node head; + Node tail; + int size; + + public NodeList() { + head = new Node(); + tail = new Node(); + head.next = tail; + tail.pre = head; + size = 0; + } + + //移除链表中的最后一个节点 + public Node removeNode() { + return removeNode(tail.pre); + } + + //移除链表指定元素 + public Node removeNode(Node node) { + node.pre.next = node.next; + node.next.pre = node.pre; + size--; + return node; + + } + + //加在链表中第一个位置 + public void addNode(Node node) { + node.next = head.next; + head.next.pre = node; + head.next = node; + node.pre = head; + size++; + } + + public boolean isEmpty() { + return size == 0; + } + + + } + + +} diff --git a/Leecode/src/main/java/com/markilue/leecode/listnode/selftry/DeleteDuplicatesII.java b/Leecode/src/main/java/com/markilue/leecode/listnode/selftry/DeleteDuplicatesII.java index 9dbbd69..33e1c1e 100644 --- a/Leecode/src/main/java/com/markilue/leecode/listnode/selftry/DeleteDuplicatesII.java +++ b/Leecode/src/main/java/com/markilue/leecode/listnode/selftry/DeleteDuplicatesII.java @@ -16,8 +16,8 @@ import org.junit.Test; public class DeleteDuplicatesII { @Test - public void test(){ - ListNode root = ListNodeUtils.build(new int[]{1, 1, 2,2,2}); + public void test() { + ListNode root = ListNodeUtils.build(new int[]{1, 1, 2, 2, 2}); ListNodeUtils.print(deleteDuplicates(root)); } @@ -39,7 +39,7 @@ public class DeleteDuplicatesII { temp1 = temp1.next; } temp.next = temp1.next; - }else { + } else { temp = temp.next; } @@ -49,4 +49,31 @@ public class DeleteDuplicatesII { return fake.next; } + + + public ListNode deleteDuplicates1(ListNode head) { + + if (head == null) { + return head; + } + ListNode fake = new ListNode(); + fake.next = head; + ListNode temp = fake; + + while (temp.next != null) { + //存在重复 + if (temp.next.next != null && temp.next.val == temp.next.next.val) { + ListNode temp1 = temp.next.next; + while (temp1.next != null && temp1.val == temp1.next.val) { + temp1 = temp1.next; + } + temp.next = temp1.next; + } else { + temp = temp.next; + } + } + + return fake.next; + + } } diff --git a/Leecode/src/main/java/com/markilue/leecode/listnode/selftry/LRUCache.java b/Leecode/src/main/java/com/markilue/leecode/listnode/selftry/LRUCache.java new file mode 100644 index 0000000..2936326 --- /dev/null +++ b/Leecode/src/main/java/com/markilue/leecode/listnode/selftry/LRUCache.java @@ -0,0 +1,117 @@ +package com.markilue.leecode.listnode.selftry; + +import java.util.HashMap; +import java.util.Map; + +/** + *@BelongsProject: Leecode + *@BelongsPackage: com.markilue.leecode.listnode.selftry + *@Author: markilue + *@CreateTime: 2023-04-04 13:45 + *@Description: + * TODO 力扣146 LRU缓存: + * 请你设计并实现一个满足 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) 的平均时间复杂度运行。 + *@Version: 1.0 + */ +public class LRUCache { + + int size; + int capacity; + DNode head; + DNode tail; + Map map; + + + //HashMap+链表:本质上就是LinkedHashMap + public LRUCache() { + } + + public LRUCache(int capacity) { + this.capacity = capacity; + head = new DNode(); + tail = new DNode(); + map = new HashMap<>(); + size = 0; + head.next = tail; + tail.prev = head; + } + + public int get(int key) { + DNode dNode = map.get(key); + if (dNode == null) return -1; + deleteNode(dNode); + addToHead(dNode); + return dNode.value; + + } + + public void put(int key, int value) { + DNode dNode = map.get(key); + if(dNode==null){ + DNode node = new DNode(key,value); + map.put(key, node); + addToHead(node); + size++; + if (size > capacity) { + DNode dNode1 = deleteTailNode(); + map.remove(dNode1.key); + --size; + } + }else { + dNode.value=value; + deleteNode(dNode); + addToHead(dNode); + } + + + } + + public void addToHead(DNode node) { + head.next.prev = node; + node.next = head.next; + head.next = node; + node.prev = head; + } + + //自删除 + public void deleteNode(DNode node) { + node.prev.next = node.next; + node.next.prev = node.prev; + } + + //删除尾节点 + public DNode deleteTailNode() { + + DNode prev = tail.prev; + deleteNode(prev); + return prev; + } + + public class DNode { + + DNode prev; + DNode next; + int value; + int key; + + public DNode() { + } + + public DNode(int key , int value) { + this.key=key; + this.value = value; + } + + public DNode(int value, DNode prev, DNode next) { + this.value = value; + this.prev = prev; + this.next = next; + } + + } +} diff --git a/Leecode/src/main/java/com/markilue/leecode/listnode/selftry/ReorderList.java b/Leecode/src/main/java/com/markilue/leecode/listnode/selftry/ReorderList.java new file mode 100644 index 0000000..178f11b --- /dev/null +++ b/Leecode/src/main/java/com/markilue/leecode/listnode/selftry/ReorderList.java @@ -0,0 +1,51 @@ +package com.markilue.leecode.listnode.selftry; + +import com.markilue.leecode.listnode.ListNode; + +/** + *@BelongsProject: Leecode + *@BelongsPackage: com.markilue.leecode.listnode.selftry + *@Author: markilue + *@CreateTime: 2023-04-04 12:56 + *@Description: + * TODO 力扣143 重排链表: + * 给定一个单链表 L 的头节点 head ,单链表 L 表示为: + * L0 → L1 → … → Ln - 1 → Ln + * 请将其重新排列后变为: + * L0 → Ln → L1 → Ln - 1 → L2 → Ln - 2 → … + * 不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。 + *@Version: 1.0 + */ +public class ReorderList { + + + /** + * 递归法 + * @param head + */ + ListNode p; + + public void reorderList(ListNode head) { + p = head; + recur(head); + + } + + public void recur(ListNode head) { + if (head == null) { + return; + } + + recur(head.next); + if (p.next == null || p == head || head.next == p) { + //判断当前节点是否需要合并 + p.next = null;//不需要合并了,直接把p置为null + return; + } + head.next = p.next;//把p的后面拼在head的后面 + p.next = head;//把head加在p的后面 + p = p.next.next; + + } + +} diff --git a/Leecode/src/main/java/com/markilue/leecode/listnode/selftry/reverseKGroup.java b/Leecode/src/main/java/com/markilue/leecode/listnode/selftry/reverseKGroup.java index d0a52df..b8de4a3 100644 --- a/Leecode/src/main/java/com/markilue/leecode/listnode/selftry/reverseKGroup.java +++ b/Leecode/src/main/java/com/markilue/leecode/listnode/selftry/reverseKGroup.java @@ -1,7 +1,10 @@ package com.markilue.leecode.listnode.selftry; +import com.markilue.leecode.listnode.ListNode; import com.markilue.leecode.listnode.T04_swapPairs; +import java.util.List; + public class reverseKGroup { public static void main(String[] args) { @@ -10,24 +13,53 @@ public class reverseKGroup { } public ListNode reverseKGroup(ListNode head, int k) { - + return null; } - public static class ListNode { - int val; - T04_swapPairs.ListNode next; - ListNode() { + + /** + * 反转部分链表 + * @param head + * @param k + * @return + */ + public ListNode reverseKGroup1(ListNode head, int k) { + if (head == null) { + return head; } - ListNode(int val) { - this.val = val; + ListNode temp = head; + //寻找终点 + for (int i = 0; i < k; i++) { + if (temp == null) return head;//没到k个,直接返回 + temp = temp.next; } - ListNode(int val, T04_swapPairs.ListNode next) { - this.val = val; - this.next = next; + ListNode newHead = reverse(head, temp); + head.next= reverseKGroup1(temp, k); + return newHead; + + + } + + public ListNode reverse(ListNode start, ListNode end) { + //反转部分链表 + if (start == null) return start; + + + ListNode fake = new ListNode(); + fake.next = start; + ListNode temp = start; + while (temp != end) { + ListNode tempnext = temp.next; + temp.next = fake.next; + fake.next = temp; + temp = tempnext; } + + return fake.next; + } } diff --git a/Leecode/src/main/java/com/markilue/leecode/listnode/selftry/swapPairs.java b/Leecode/src/main/java/com/markilue/leecode/listnode/selftry/swapPairs.java index 8b81157..5ca1a18 100644 --- a/Leecode/src/main/java/com/markilue/leecode/listnode/selftry/swapPairs.java +++ b/Leecode/src/main/java/com/markilue/leecode/listnode/selftry/swapPairs.java @@ -1,42 +1,45 @@ package com.markilue.leecode.listnode.selftry; +import com.markilue.leecode.listnode.ListNode; +import com.markilue.leecode.listnode.ListNodeUtils; public class swapPairs { public static void main(String[] args) { ListNode l1 = new ListNode(1); - //l1.next=new ListNode(2); - //l1.next.next=new ListNode(3); - //l1.next.next.next=new ListNode(4); + l1.next = new ListNode(2); + l1.next.next = new ListNode(3); + l1.next.next.next = new ListNode(4); - ListNode listNode = swapPairs(l1); + ListNode listNode = swapPairs1(l1); + ListNodeUtils.print(listNode); } public static ListNode swapPairs(ListNode head) { - if(head==null){ + if (head == null) { return null; } - ListNode dust=head; - ListNode swap=head.next; - int temp=0; - while (swap!=null){ - temp=swap.val; - swap.val=head.val; - head.val=temp; + ListNode dust = head; + ListNode swap = head.next; + int temp = 0; + while (swap != null) { + temp = swap.val; + swap.val = head.val; + head.val = temp; - if(swap.next!=null){ - if(swap.next.next!=null){ - swap=swap.next.next; - head=head.next.next; - }else { + if (swap.next != null) { + if (swap.next.next != null) { + swap = swap.next.next; + head = head.next.next; + } else { break; } - }else { + } else { break; } @@ -44,21 +47,30 @@ public class swapPairs { return dust; } - public static class ListNode { - int val; - ListNode next; - ListNode() { + public static ListNode swapPairs1(ListNode head) { + if (head == null || head.next == null) { + return head; + } + ListNode fake = new ListNode(); + fake.next = head; + ListNode tempcur = fake; + + while (tempcur != null && tempcur.next != null) { + ListNode temp = tempcur.next.next; + if (tempcur.next.next != null) { + tempcur.next.next = tempcur.next.next.next; + temp.next = tempcur.next; + tempcur.next=temp; + } + tempcur = tempcur.next.next; +// tempcur = temp; + } - ListNode(int val) { - this.val = val; - } + return fake.next; + - ListNode(int val, ListNode next) { - this.val = val; - this.next = next; - } } diff --git a/Leecode/src/main/java/com/markilue/leecode/test/ThreeSum.java b/Leecode/src/main/java/com/markilue/leecode/test/ThreeSum.java new file mode 100644 index 0000000..0138630 --- /dev/null +++ b/Leecode/src/main/java/com/markilue/leecode/test/ThreeSum.java @@ -0,0 +1,60 @@ +package com.markilue.leecode.test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + *@BelongsProject: Leecode + *@BelongsPackage: com.markilue.leecode.test + *@Author: markilue + *@CreateTime: 2023-04-04 11:01 + *@Description: + * TODO 力扣15题 三数之和: + * 给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请 + * 你返回所有和为 0 且不重复的三元组。 + * 注意:答案中不可以包含重复的三元组。 + *@Version: 1.0 + */ +public class ThreeSum { + + + public List> threeSum(int[] nums) { + List> result = new ArrayList<>(); + if (nums.length < 3) { + return result; + } + Arrays.sort(nums); + + for (int i = 0; i < nums.length-2; i++) { + if (i != 0 && nums[i] == nums[i - 1]) { + continue; + } + if (nums[i] > 0) break; + + int left = i + 1; + int right = nums.length - 1; + + while (left < right) { + int sum = nums[i] + nums[left] + nums[right]; + + if (sum < 0) { + left++; + } else if (sum > 0) { + right--; + } else { + result.add(new ArrayList<>(Arrays.asList(nums[i], nums[left], nums[right]))); + + while (left < right && nums[left] == nums[left + 1]) left++; + while (left < right && nums[right] == nums[right - 1]) right--; + left++; + right--; + } + } + + } + + return result; + + } +} diff --git a/Leecode/src/main/java/com/markilue/leecode/test/test.java b/Leecode/src/main/java/com/markilue/leecode/test/test.java index 4e39125..c3604b5 100644 --- a/Leecode/src/main/java/com/markilue/leecode/test/test.java +++ b/Leecode/src/main/java/com/markilue/leecode/test/test.java @@ -1,5 +1,6 @@ package com.markilue.leecode.test; +import com.markilue.leecode.hot100.T55_LFUCache; import com.markilue.leecode.tree.TreeNode; import org.junit.Test; @@ -15,6 +16,22 @@ import java.util.ArrayList; */ public class test { + @Test + public void test2(){ + T55_LFUCache lfuCache = new T55_LFUCache(2); + lfuCache.put(1,1); + lfuCache.put(2,2); + System.out.println(lfuCache.get(1)); + lfuCache.put(3,3); + System.out.println(lfuCache.get(2)); + System.out.println(lfuCache.get(3)); + lfuCache.put(4,4); + System.out.println(lfuCache.get(1)); + System.out.println(lfuCache.get(3)); + System.out.println(lfuCache.get(4)); + + } + static {