面试题更新

This commit is contained in:
markilue 2023-03-14 09:52:14 +08:00
parent 69049a5e86
commit 44f6375707
7 changed files with 879 additions and 12 deletions

View File

@ -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<Integer, DLinkedNode> cache = new HashMap<Integer, DLinkedNode>();
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
}
}

View File

@ -130,6 +130,7 @@ public class T06_StrStr {
String s = "aabaaf"; String s = "aabaaf";
System.out.println(getNext1(s)); System.out.println(getNext1(s));
} }
/** /**
* 官方获取next数组的方法精髓在于这次的next[i]可以通过上一次的next[i-1]来获取分为两种情况 * 官方获取next数组的方法精髓在于这次的next[i]可以通过上一次的next[i-1]来获取分为两种情况
* 1如果next[i-1]的下一个数和next[i]的下一个数相等那么最大子串一定是在上一个的基础上+1,对应下面的if的内容 * 1如果next[i-1]的下一个数和next[i]的下一个数相等那么最大子串一定是在上一个的基础上+1,对应下面的if的内容

View File

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

View File

@ -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<Character, Integer> 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<Character, Integer> 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<s.length()){
int j=i+1;
while (j<s.length()&&Character.isDigit(s.charAt(j))){
j++;
}
int count = Integer.parseInt(s.substring(i, j));
i=j;
j++;
while (j<s.length()&&!Character.isDigit(s.charAt(j))){
j++;
}
String substr=s.substring(i,j);
for (int k = 0; k < count; k++) {
result.append(substr);
}
i=j;
}
return result.toString();
}
}

View File

@ -0,0 +1,160 @@
package com.markilue.interview;
import org.junit.Test;
import java.util.*;
/**
*@BelongsProject: PDD
*@BelongsPackage: com.markilue.interview
*@Author: markilue
*@CreateTime: 2023-03-12 19:19
*@Description: TODO
*@Version: 1.0
*/
public class Question2 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int guan = sc.nextInt();
int count = sc.nextInt();
// List<List<Integer>> total = new ArrayList<>();
int[][] total = new int[guan][count];
for (int i = 0; i < guan; i++) {
// List<Integer> 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<Integer> solve(int t, int n, int[][] damage) {
//先给每关的敌人进行排序
List<Integer> 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<Integer> 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);
}
}

View File

@ -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<Integer.MAX_VALUE){
System.out.println("YES");
System.out.println(minCost);
}else {
System.out.println("NO");
System.out.println(maxCount);
}
}
}

View File

@ -0,0 +1,240 @@
package com.markilue.interview;
import org.junit.Test;
import java.util.Arrays;
import java.util.Comparator;
import java.util.PriorityQueue;
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 Question4 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int count = sc.nextInt();
int[] want = new int[count];
for (int i = 0; i < count; i++) {
want[i] = sc.nextInt();
}
// solve(want);
}
@Test
public void test() {
// System.out.println(solve().get(0));
// System.out.println(solve().get(1));
int[] nums = {10, 4, 8, 6, 4};
solve2(nums);
}
/**
* 做到这里已经思路混乱大脑宕机了
* 中位数定义都忘了 以为在中间就行
* 实际上应该是排序后的中间位置
* @param nums
*/
public void solve(int[] nums) {
int[] avg = new int[nums.length];
int[] mid = new int[nums.length];
int sum = 0;
int index = 0;
for (int i = 0; i < nums.length; i++) {
sum += nums[i];
float fake = (float) sum / (i + 1);
if (sum / (i + 1) < fake) avg[i] = sum / (i + 1) + 1;
else avg[i] = sum / (i + 1);
float fake1 = (float) i / 2;
if (index < fake1) index++;
mid[i] = nums[index];
}
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]);
}
}
/**
* 快速写法
* @param nums
*/
public void solve1(int[] nums) {
int[] avg = new int[nums.length];
int[] mid = new int[nums.length];
int sum = 0;
int index = 0;
for (int i = 0; i < nums.length; i++) {
sum += nums[i];
int fake = sum / (i + 1);
avg[i] = sum % (i + 1) == 0 ? fake : fake + 1;
mid[i] = getMid(nums, 0, i, nums[i]);
}
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] + " ");
}
}
@Test
public void test2() {
int[] nums = {3, 5, 6, 4};
System.out.println(getMid(nums, 0, nums.length - 1, 4));
System.out.println(Arrays.toString(nums));
}
/**
* 思路:二分插入
* @param nums
* @param right
* @return
*/
public int getMid(int[] nums, int left, int right, int find) {
int index = insert(nums, left, right, find);
System.arraycopy(nums, index, nums, index + 1, right - index);
nums[index] = find;
int length = right - left + 1;//长度
int mid = left + (length >> 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<Integer> queMax = new PriorityQueue<>(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2 - o1;
}
});//大顶堆
PriorityQueue<Integer> queMin = new PriorityQueue<>(new Comparator<Integer>() {
@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;
}
}