leecode更新

This commit is contained in:
markilue 2023-04-05 13:26:24 +08:00
parent e804dbb23b
commit b531d06a02
8 changed files with 575 additions and 42 deletions

View File

@ -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<Integer, Node> cache;
Map<Integer, NodeList> 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;
}
}
}

View File

@ -49,4 +49,31 @@ public class DeleteDuplicatesII {
return fake.next; 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;
}
} }

View File

@ -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<Integer, DNode> 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;
}
}
}

View File

@ -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;
}
}

View File

@ -1,7 +1,10 @@
package com.markilue.leecode.listnode.selftry; package com.markilue.leecode.listnode.selftry;
import com.markilue.leecode.listnode.ListNode;
import com.markilue.leecode.listnode.T04_swapPairs; import com.markilue.leecode.listnode.T04_swapPairs;
import java.util.List;
public class reverseKGroup { public class reverseKGroup {
public static void main(String[] args) { public static void main(String[] args) {
@ -14,20 +17,49 @@ public class reverseKGroup {
return null; 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) { ListNode temp = head;
this.val = val; //寻找终点
for (int i = 0; i < k; i++) {
if (temp == null) return head;//没到k个直接返回
temp = temp.next;
} }
ListNode(int val, T04_swapPairs.ListNode next) { ListNode newHead = reverse(head, temp);
this.val = val; head.next= reverseKGroup1(temp, k);
this.next = next; 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;
} }
} }

View File

@ -1,17 +1,20 @@
package com.markilue.leecode.listnode.selftry; package com.markilue.leecode.listnode.selftry;
import com.markilue.leecode.listnode.ListNode;
import com.markilue.leecode.listnode.ListNodeUtils;
public class swapPairs { public class swapPairs {
public static void main(String[] args) { public static void main(String[] args) {
ListNode l1 = new ListNode(1); ListNode l1 = new ListNode(1);
//l1.next=new ListNode(2); l1.next = new ListNode(2);
//l1.next.next=new ListNode(3); l1.next.next = new ListNode(3);
//l1.next.next.next=new ListNode(4); l1.next.next.next = new ListNode(4);
ListNode listNode = swapPairs(l1); ListNode listNode = swapPairs1(l1);
ListNodeUtils.print(listNode);
} }
@ -44,21 +47,30 @@ public class swapPairs {
return dust; 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) { return fake.next;
this.val = val;
}
ListNode(int val, ListNode next) {
this.val = val;
this.next = next;
}
} }

View File

@ -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 != ji != k j != k 同时还满足 nums[i] + nums[j] + nums[k] == 0
* 你返回所有和为 0 且不重复的三元组
* 注意答案中不可以包含重复的三元组
*@Version: 1.0
*/
public class ThreeSum {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> 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;
}
}

View File

@ -1,5 +1,6 @@
package com.markilue.leecode.test; package com.markilue.leecode.test;
import com.markilue.leecode.hot100.T55_LFUCache;
import com.markilue.leecode.tree.TreeNode; import com.markilue.leecode.tree.TreeNode;
import org.junit.Test; import org.junit.Test;
@ -15,6 +16,22 @@ import java.util.ArrayList;
*/ */
public class test { 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 { static {