leecode更新
This commit is contained in:
parent
e804dbb23b
commit
b531d06a02
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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<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;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -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 {
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue