From 44f637570730e24fd874fc0f485874ab6edf393a Mon Sep 17 00:00:00 2001 From: markilue <745518019@qq.com> Date: Tue, 14 Mar 2023 09:52:14 +0800 Subject: [PATCH] =?UTF-8?q?=E9=9D=A2=E8=AF=95=E9=A2=98=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_LRUCache.java | 135 ++++++++++ .../leecode/string/second/T06_StrStr.java | 25 +- .../com/markilue/leecode/test/TestBaidu.java | 119 +++++++++ .../com/markilue/interview/Question1.java | 99 ++++++++ .../com/markilue/interview/Question2.java | 160 ++++++++++++ .../com/markilue/interview/Question3.java | 113 +++++++++ .../com/markilue/interview/Question4.java | 240 ++++++++++++++++++ 7 files changed, 879 insertions(+), 12 deletions(-) create mode 100644 Leecode/src/main/java/com/markilue/leecode/hot100/T55_LRUCache.java create mode 100644 Leecode/src/main/java/com/markilue/leecode/test/TestBaidu.java create mode 100644 interview/PDD/src/main/java/com/markilue/interview/Question1.java create mode 100644 interview/PDD/src/main/java/com/markilue/interview/Question2.java create mode 100644 interview/PDD/src/main/java/com/markilue/interview/Question3.java create mode 100644 interview/PDD/src/main/java/com/markilue/interview/Question4.java diff --git a/Leecode/src/main/java/com/markilue/leecode/hot100/T55_LRUCache.java b/Leecode/src/main/java/com/markilue/leecode/hot100/T55_LRUCache.java new file mode 100644 index 0000000..0d70d80 --- /dev/null +++ b/Leecode/src/main/java/com/markilue/leecode/hot100/T55_LRUCache.java @@ -0,0 +1,135 @@ +package com.markilue.leecode.hot100; + +import org.junit.Test; +import org.omg.CORBA.PUBLIC_MEMBER; + +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缓存: + * 请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。 + * 实现 LRUCache 类: + * 1)LRUCache(int capacity) 以 正整数 作为容量 capacity 初始化 LRU 缓存 + * 2)int get(int key) 如果关键字 key 存在于缓存中,则返回关键字的值,否则返回 -1 。 + * 3)void put(int key, int value) 如果关键字 key 已经存在,则变更其数据值 value ; + * 如果不存在,则向缓存中插入该组 key-value 。 + * 如果插入操作导致关键字数量超过 capacity + * 则应该 逐出 最久未使用的关键字。 + * 函数 get 和 put 必须以 O(1) 的平均时间复杂度运行。 + *@Version: 1.0 + */ +public class T55_LRUCache { + + private Map cache = new HashMap(); + private int size; + private int capacity; + private DLinkedNode head, tail; + + + class DLinkedNode { + int key; + int value; + DLinkedNode prev; + DLinkedNode next; + public DLinkedNode() {} + public DLinkedNode(int _key, int _value) {key = _key; value = _value;} + } + + + public T55_LRUCache() { + } + + public T55_LRUCache(int capacity) { + this.size = 0; + this.capacity = capacity; + // 使用伪头部和伪尾部节点 + head = new DLinkedNode(); + tail = new DLinkedNode(); + head.next = tail; + tail.prev = head; + } + + public int get(int key) { + + DLinkedNode node = cache.get(key); + if (node == null) { + return -1; + } + // 如果 key 存在,先通过哈希表定位,再移到头部 + moveToHead(node); + return node.value; + } + + public void put(int key, int value) { + + DLinkedNode node = cache.get(key); + if (node == null) { + // 如果 key 不存在,创建一个新的节点 + DLinkedNode newNode = new DLinkedNode(key, value); + // 添加进哈希表 + cache.put(key, newNode); + // 添加至双向链表的头部 + addToHead(newNode); + ++size; + if (size > capacity) { + // 如果超出容量,删除双向链表的尾部节点 + DLinkedNode tail = removeTail(); + // 删除哈希表中对应的项 + cache.remove(tail.key); + --size; + } + } + else { + // 如果 key 存在,先通过哈希表定位,再修改 value,并移到头部 + node.value = value; + moveToHead(node); + } + + } + + private void addToHead(DLinkedNode node) { + node.prev = head; + node.next = head.next; + head.next.prev = node; + head.next = node; + } + + private void removeNode(DLinkedNode node) { + node.prev.next = node.next; + node.next.prev = node.prev; + } + + private void moveToHead(DLinkedNode node) { + removeNode(node); + addToHead(node); + } + + private DLinkedNode removeTail() { + DLinkedNode res = tail.prev; + removeNode(res); + return res; + } + + + @Test + public void test(){ + T55_LRUCache lRUCache = new T55_LRUCache(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 + } + + +} diff --git a/Leecode/src/main/java/com/markilue/leecode/string/second/T06_StrStr.java b/Leecode/src/main/java/com/markilue/leecode/string/second/T06_StrStr.java index 375a245..1a71620 100644 --- a/Leecode/src/main/java/com/markilue/leecode/string/second/T06_StrStr.java +++ b/Leecode/src/main/java/com/markilue/leecode/string/second/T06_StrStr.java @@ -126,10 +126,11 @@ public class T06_StrStr { @Test - public void testk(){ - String s="aabaaf"; + public void testk() { + String s = "aabaaf"; System.out.println(getNext1(s)); } + /** * 官方获取next数组的方法:精髓在于这次的next[i]可以通过上一次的next[i-1]来获取,分为两种情况: * 1)如果next[i-1]的下一个数和next[i]的下一个数相等,那么最大子串一定是在上一个的基础上+1,对应下面的if的内容 @@ -210,17 +211,17 @@ public class T06_StrStr { } //根据needle构造一个next数组,next[i]表示needle[0-i]的最长公共子串 int[] next = getNext(needle); - int index=0; + int index = 0; for (int i = 0; i < m; i++) { - while (index>0&&haystack.charAt(i)!=needle.charAt(index)){ - index=next[index-1];//匹配不上就找上一个字母在哪重复的,看看之前重复的地方能不能匹配上 + while (index > 0 && haystack.charAt(i) != needle.charAt(index)) { + index = next[index - 1];//匹配不上就找上一个字母在哪重复的,看看之前重复的地方能不能匹配上 } - if(haystack.charAt(i)==needle.charAt(index)){ + if (haystack.charAt(i) == needle.charAt(index)) { index++;//匹配上就试试下一个能不能匹配上 } - if(index==n){ + if (index == n) { //匹配到最末尾了 - return i-index+1; + return i - index + 1; } } return -1; @@ -235,14 +236,14 @@ public class T06_StrStr { for (int i = 1; i < next.length; i++) { //如果匹配不上了 - while (index != 0 && chars[i] != chars[index]){ + while (index != 0 && chars[i] != chars[index]) { //有趣的是:index既是最长公共子串长度,又是上一次匹配上的索引,所以能这样 - index=next[index-1];//匹配不上就找上一个字母在哪重复的,看看之前重复的地方能不能匹配上 + index = next[index - 1];//匹配不上就找上一个字母在哪重复的,看看之前重复的地方能不能匹配上 } - if(chars[i]==chars[index]){ + if (chars[i] == chars[index]) { index++; } - next[i]=index; + next[i] = index; } return next; diff --git a/Leecode/src/main/java/com/markilue/leecode/test/TestBaidu.java b/Leecode/src/main/java/com/markilue/leecode/test/TestBaidu.java new file mode 100644 index 0000000..7afb2cb --- /dev/null +++ b/Leecode/src/main/java/com/markilue/leecode/test/TestBaidu.java @@ -0,0 +1,119 @@ +package com.markilue.leecode.test; + +import org.junit.Test; + +/** + *@BelongsProject: Leecode + *@BelongsPackage: com.markilue.leecode.hot100 + *@Author: markilue + *@CreateTime: 2023-03-13 20:03 + *@Description: TODO 百度面试第三题 + *@Version: 1.0 + */ +public class TestBaidu { + + class node { + public int leftSum; + public int rightSum; + public int value; + public node left; + public node right; + public String color; + + public node() { + } + + public node(String color, int value) { + this.color = color; + this.value = value; + } + + public node(int leftSum, int rightSum, node left, node right, String color) { + this.left = left; + this.right = right; + this.leftSum = leftSum; + this.rightSum = rightSum; + this.color = color; + } + } + + + public int sum(node root) { + + //先遍历记录下各个位置的连通块数量 + if (root == null) { + return 0; + } + + root.leftSum = sum(root.left); + root.rightSum = sum(root.right); + int total = 0; + + if (root.right != null && root.color.equals(root.right.color)) { + total += 1; + } + + if (root.left != null && root.color.equals(root.left.color)) { + total += 1; + } + + return total + root.leftSum + root.rightSum; + } + + public int allSum = 0; + public int result = 0; + + public int check(node root) { +// node temp = root; + allSum = sum(root); + //分别计算当前点断开左右的权值数量 + getResult(root); + return result; + } + + public void getResult(node root) { + if (root == null) { + return; + } + getResult(root.left); + getResult(root.right); + int leftSum = 0; + int rightSum = 0; + if (root.left != null) { + if (root.left.color.equals(root.color)) { + leftSum = Math.abs(root.leftSum - (allSum - root.leftSum - 1)); + } else { + leftSum = Math.abs(root.leftSum - (allSum - root.leftSum)); + } + } + if (root.right != null) { + if (root.right.color.equals(root.color)) { + rightSum = Math.abs(root.rightSum - (allSum - root.rightSum - 1)); + } else { + rightSum = Math.abs(root.rightSum - (allSum - root.rightSum)); + } + + } + result += leftSum; + result += rightSum; + + + } + + @Test + public void test() { + + node node1 = new node("B", 1); + node node2 = new node("B", 2); + node node3 = new node("R", 3); + node node4 = new node("R", 4); + + node1.left = node2; + node1.right = node4; + node2.left = node3; + + check(node1); + System.out.println(result); + + } +} diff --git a/interview/PDD/src/main/java/com/markilue/interview/Question1.java b/interview/PDD/src/main/java/com/markilue/interview/Question1.java new file mode 100644 index 0000000..cfd2721 --- /dev/null +++ b/interview/PDD/src/main/java/com/markilue/interview/Question1.java @@ -0,0 +1,99 @@ +package com.markilue.interview; + +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; +import java.util.Scanner; + +/** + *@BelongsProject: PDD + *@BelongsPackage: com.markilue.interview + *@Author: markilue + *@CreateTime: 2023-03-12 19:02 + *@Description: TODO + *@Version: 1.0 + */ +public class Question1 { + + + public static void main(String[] args) { + Scanner sc = new Scanner(System.in); + String s = sc.nextLine(); + System.out.println(new Question1().solve(s)); + } + + @Test + public void test() { + String s = "10a4b3c"; + System.out.println(solve(s)); + } + + /** + * 思路:本来是想一个一个遍历然后将数字加起来,但是看到了chatgpt的直接substring觉得可以,就继续按他的做了 + * 过15% 具体想不到哪里有问题 + * @param s + * @return + */ + public String solve(String s) { + + if (s.length() == 1) { + return s; + } + char[] chars = s.toCharArray(); + HashMap map = new HashMap<>(); + + + int start = 0; + for (int i = 0; i < chars.length; i++) { + + if (chars[i] >= '0' && chars[i] <= '9') { + continue; + } else { + int nums = Integer.parseInt(s.substring(start, i)); + map.put(chars[i], nums); + start = i + 1; + } + } + + StringBuilder result = new StringBuilder(); + for (Map.Entry entry : map.entrySet()) { + Character key = entry.getKey(); + Integer value = entry.getValue(); + while (value-- > 0) { + result.append(key); + } + } + + return result.toString(); + } + + + /** + * 全过:可能是Character.isDigit()的作用 + * @param s + * @return + */ + public String solve1(String s){ + StringBuilder result = new StringBuilder(); + int i=0; + while (i> total = new ArrayList<>(); + int[][] total = new int[guan][count]; + for (int i = 0; i < guan; i++) { +// List cur = new ArrayList<>(); + for (int j = 0; j < count; j++) { +// cur.add(sc.nextInt()); + total[i][j] = sc.nextInt(); + } + } + int[] ints = new Question2().solve1(guan, count, total); + for (int anInt : ints) { + System.out.println(anInt); + } + + +// System.out.println(total); + } + + @Test + public void test() { + int[][] damage = {{1, 2, 1}, {2, 3, 2}, {1, 2, 3}}; + + for (int[] ints : damage) { + solve(ints); + } +// System.out.println(Arrays.toString(solve1(3, 3, damage))); + } + + + /** + * chatgpt代码 + * @param t + * @param n + * @param damage + * @return + */ + public List solve(int t, int n, int[][] damage) { + + //先给每关的敌人进行排序 + List result = new ArrayList<>(); + + for (int i = 0; i < t; i++) { + int a = 0;//按a + int b = 0;//按b + int[] sortedDamage = Arrays.copyOf(damage[i], n); + Arrays.sort(sortedDamage); + for (int j = 0; j < n; j++) { + int d = sortedDamage[j]; + while (d > 1 && a >= 2) { + d -= 2; + a -= 2; + + } + while (d > 0 && a >= 1) { + a--; + d--; + } + if (d > 0 && b >= 1) { + d = 0; + b++; + } + if (d > 0) { + a += 2; + } + } + result.addAll(Arrays.asList(a, b)); + } + + + return result; + } + + + public int[] solve1(int t, int n, int[][] damage) { + + //先给每关的敌人进行排序 +// List result = new ArrayList<>(); + int[] result = new int[t]; + + for (int i = 0; i < t; i++) { + int a = 0;//按a + int b = 0;//按b + int[] sortedDamage = Arrays.copyOf(damage[i], n); + Arrays.sort(sortedDamage); + for (int j = 0; j < n; j++) { + int d = sortedDamage[j]; + while (d > 1 && a >= 2) { + d = 0; + a -= 1; + b += 1;//使用b + } + while (d > 0 && a >= 1) { + a--; + d--; + } + if (d > 0 && b >= 1) { + d = 0; + a++; + b--; + } + if (d > 0) { + a += 1; + } + } +// result.addAll(Arrays.asList(a, b)); + result[i] = a + b; + } + + + return result; + } + + + /** + * 思路:事实上单独处理每一关的都行,做leetcode做多了就喜欢传回去,又不知道用那种方式传回去 + * TODO 思路:本质上就是贪心算法 一个敌人的血量>2那么他就一定使用B键击败,因为他使用A也需要2次 + * @param damage + */ + public void solve(int[] damage) { + + int b = 0; + int a = 0; + int total1 = 0; + + for (int i : damage) { + if (i >= 2) { + b++; + } else { + total1++; + } + } + + int need = total1 >> 1; + a = total1 % 2 == 0 ? need : (need + 1); + System.out.println(a+b); + + } + + +} diff --git a/interview/PDD/src/main/java/com/markilue/interview/Question3.java b/interview/PDD/src/main/java/com/markilue/interview/Question3.java new file mode 100644 index 0000000..13372c8 --- /dev/null +++ b/interview/PDD/src/main/java/com/markilue/interview/Question3.java @@ -0,0 +1,113 @@ +package com.markilue.interview; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Scanner; + +/** + *@BelongsProject: PDD + *@BelongsPackage: com.markilue.interview + *@Author: markilue + *@CreateTime: 2023-03-12 20:02 + *@Description: TODO + *@Version: 1.0 + */ +public class Question3 { + + public static void main(String[] args) { + Scanner sc = new Scanner(System.in); + int count = sc.nextInt(); + + int[][] demand = new int[3][count]; + int[] limit = new int[3]; + int[] cost = new int[3]; + + for (int i = 0; i < count; i++) { + String vote = sc.next(); + for (int j = 0; j < vote.length(); j++) { + char activity = vote.charAt(j); + switch (activity){ + case 'A': + demand[0][i]++; + break; + case 'B': + demand[1][i]++; + case 'C': + demand[2][i]++; + } + } + } + + for (int i = 0; i < 3; i++) { + limit[i] = sc.nextInt(); + cost[i] = sc.nextInt(); + } + + solve(count,demand,limit,cost); + + + + } + + @Test + public void test() { +// System.out.println(solve().get(0)); +// System.out.println(solve().get(1)); + } + + + public static void solve(int count ,int[][] demand, int[] limit,int[] cost) { + + + int[][][] dp = new int[limit[0] + 1][limit[1] + 1][limit[2] + 1]; + + for (int i = 0; i < limit[0]; i++) { + for (int j = 0; j < limit[1]; j++) { + for (int k = 0; k < limit[2]; k++) { + for (int p = 0; p < count; p++) { + int a=demand[0][p]; + int b=demand[1][p]; + int c=demand[2][p]; + if(i>=1&&j>=b&&k>=c){ + dp[i][j][k]=Math.max(dp[i][j][k],dp[i-a][j-b][k-c]+cost[0]+cost[1]+cost[2]); + } + } + } + } + } + + int minCost=Integer.MAX_VALUE; + int maxCount=0; + + for (int i = 0; i < limit[0]; i++) { + for (int j = 0; j < limit[1]; j++) { + for (int k = 0; k < limit[2]; k++) { + if(dp[i][j][k]>0){ + int count1=0; + for (int p = 0; p < count; p++) { + if(i>=demand[0][p]&&j>=demand[1][p]&&k>=demand[2][p]){ + count1++; + } + } + if(count1==count){ + minCost=Math.min(minCost,dp[i][j][k]); + }else { + maxCount=Math.max(maxCount,count1); + } + } + } + } + } + + if(minCost> 1); + if (length % 2 == 0) { + return (nums[mid - 1] + nums[mid]) >> 1; + } else { + return nums[mid]; + } + + + } + + //返回一个应该要插入的index + public int insert(int[] nums, int left, int right, int find) { + if (left >= right) { + if (nums[left] < find) return left + 1; + return left; + } + + int mid = left + ((right - left) >> 1); + if (nums[mid] > find) { + return insert(nums, left, mid - 1, find); + } else if (nums[mid] < find) { + return insert(nums, mid + 1, right, find); + } else { + return mid; + } + } + + + + PriorityQueue queMax = new PriorityQueue<>(new Comparator() { + @Override + public int compare(Integer o1, Integer o2) { + return o2 - o1; + } + });//大顶堆 + + PriorityQueue queMin = new PriorityQueue<>(new Comparator() { + @Override + public int compare(Integer o1, Integer o2) { + return o1 - o2; + } + });//小顶堆 + public void solve2(int[] nums) { + + int[] avg = new int[nums.length]; + int[] mid = new int[nums.length]; + + int sum = 0; + + + //中位数即是大顶堆和小顶堆的中间 + int bigPeek; + int smallPeek; + + for (int i = 0; i < nums.length; i++) { + sum += nums[i]; + addNum(nums[i]); + int fake = sum / (i + 1); + avg[i] = sum % (i + 1) == 0 ? fake : fake + 1; + + mid[i]=findMedian(); + } + + for (int i = 0; i < avg.length; i++) { + System.out.print(avg[i] + " "); + } + System.out.println(); + + for (int i = 0; i < mid.length; i++) { + System.out.print(mid[i] + " "); + } + + + } + + public void addNum(int num) { + if (queMin.isEmpty() || num <= queMin.peek()) { + queMin.offer(num); + if (queMax.size() + 1 < queMin.size()) { + queMax.offer(queMin.poll());//保证两边size相差不超过1 + } + } else { + queMax.offer(num); + if (queMax.size() > queMin.size()) { + queMin.offer(queMax.poll()); + } + } + } + + public int findMedian() { + if (queMin.size() > queMax.size()) { + return queMin.peek(); + } + return (queMin.peek() + queMax.peek()) >>1; + } + + + + +}