搜索
查看
编辑修改
首页
UNITY
NODEJS
PYTHON
AI
GIT
PHP
GO
CEF3
JAVA
HTML
CSS
搜索
小丑西瓜9
这个屌丝很懒,什么也没留下!
关注作者
热门标签
jquery
HTML
CSS
PHP
ASP
PYTHON
GO
AI
C
C++
C#
PHOTOSHOP
UNITY
iOS
android
vue
xml
爬虫
SEO
LINUX
WINDOWS
JAVA
MFC
CEF3
CAD
NODEJS
GIT
Pyppeteer
article
热门文章
1
雨云游戏云VPS搭建MCSM面板和我的世界(MC)Paper服务器教程_mcsmanager 配置文件改不了
2
Web3js 03: 访问区块链网络_前端web怎么调用区块链
3
公考备考方法_申论老邹和小马谁教的好
4
【DevOps】Linux网络桥接:实现灵活组网与虚拟机高效通信的关键技术_linux 桥接网络
5
Vue3项目性能优化(图片压缩)_vite-plugin-image-optimizer
6
redis.clients.jedis.exceptions.JedisException: Could not get a resource from the pool异常的解决方案
7
图解支付-金融级密钥管理系统:构建支付系统的安全基石(3)
8
FPGA时钟:驱动数字逻辑的核心
9
从0开始学习 GitHub 系列之「07.福利开源项目」
10
【python-致用】为嫖掘金月更奖品,我用刚学的python做了个批量文件内容替换_python 批量替换文件
当前位置:
article
> 正文
常见的Java算法面试题_java算法面试题 经典
作者:小丑西瓜9 | 2024-06-09 11:11:38
赞
踩
java算法面试题 经典
1、 使用jedis客户端实现分布式锁方式
public boolean lock(Jedis jedis,String key,String val,int expireTime){
String lock = jedis.set(key, val, "NX", "PX",
expireTime);
return "OK".equals(lock);
}
2、 jedis释放锁实现方式
public void unlock(Jedis jedis,String key,String value) {
String script_command = "if redis.call('get',KEYS[1]) == ARGV[1] then " +
"return redis.call('del',KEYS[1]) else return 0 end";
// 解锁
jedis.eval(script_command, Collections.singletonList(key), Collections.singletonList(value));
}
3、手写一个阻塞队列
public class AxinBlockQueue {
//队列容器
private List<Integer> container = new ArrayList<>();
private volatile int size; 被volatile修饰时,它会保证修改的值会立即被更新到内存
private volatile int capacity;
private Lock lock = new ReentrantLock(); ReentrantLock也是独占锁、可重入,加锁和解锁的过程需要手动进行,次数要一样
//Condition
private final Condition isNull = lock.newCondition();
private final Condition isFull = lock.newCondition();
AxinBlockQueue(int cap) {
this.capacity = cap;
}
/**
* 添加方法
*
* @param data
*/
public void add(int data) {
try {
lock.lock();
try {
while (size >= capacity) {
System.out.println("阻塞队列满了");
isFull.await();
}
} catch (InterruptedException e) {
isFull.signal();
e.printStackTrace();
}
++size;
container.add(data);
isNull.signal();
} finally {
lock.unlock();
}
}
/**
* 取出元素
*
* @return
*/
public int take() {
try {
lock.lock();
try {
while (size == 0) {
System.out.println("阻塞队列空了");
isNull.await();
}
} catch (InterruptedException e) {
isNull.signal();
e.printStackTrace();
}
--size;
int res = container.get(0);
container.remove(0);
isFull.signal();
return res;
} finally {
lock.unlock();
}
}
}
4、手写一个堆排序
八大排序-堆排序(手写堆排序) - 知乎
public class Test {
public static void main(String[] args) {
int n[] = { 6, 5, 2, 7, 3, 9, 8 };
heapsort(n);
System.out.print("堆排序结果:");
for (int m : n) {
System.out.print(m + " ");
}
}
/**
* 堆排序
* @param n 待排序数组
*/
public static void heapsort(int n[]) {
for (int i = n.length - 1; i >= 1; i--) {
buildHeap(n, i);
swap(n, 0, i);
}
}
/**
*
* @param n 待排序数组
* @param end 待排序数组末位下标
*/
public static void buildHeap(int n[], int end) {
int len = end + 1;
for (int i = len / 2 - 1; i >= 0; i--) {
//堆中i节点对应的左右子节点l和r
int l = 2 * i + 1, r = l + 1;
//指向较大数节点的指针
int p = l;
if (r <= len - 1 && n[l] < n[r]) {
p = r;
}
if (n[i] < n[p]) {
swap(n, i, p);
}
}
}
/**
*
* @param n 待排序数组
* @param i 待交换数字数组下标
* @param j 待交换数字数组下标
*/
private static void swap(int n[], int i, int j) {
n[i] ^= n[j];
n[j] ^= n[i];
n[i] ^= n[j];
}
}
5、怎么实现一个线程安全的计数器
public class MySafeThread implements Runnable {
//设置计数初值为0
private static AtomicInteger count = new AtomicInteger(0);
@Override
public void run() {
while (true) {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
MySafeThread.calc();
}
}
private synchronized static void calc() {
if (count.get() < 1000) {
// 自增1,返回更新后的值
int c = count.incrementAndGet();
System.out.println("线程:" + Thread.currentThread().getName()+" :" + c);
}
}
public static void main(String[] args) {
for (int i = 0; i < 5; i++) {
MySafeThread myThread = new MySafeThread();
Thread t = new Thread(myThread);
t.start();
}
}
}
6、快速排序
static int RandPartition(int[] arr, int left, int right) {
Random rd = new Random();
int p = rd.Next(left, right + 1);
Swap(ref arr[p], ref arr[left]);
int temp = arr[left];
while (left < right) {
while (left < right && arr[right] > temp) { right--; count++; }
arr[left] = arr[right];
while (left < right && arr[left] <= temp) { left++; count++; }
arr[right] = arr[left];
}
arr[left] = temp;
return left;
}
static int RandSelect(int[] arr, int left, int right, int k) {
if (left == right) {
return arr[left];
}
int index = RandPartition(arr, left, right);
int M = index + 1;
if (M == k) {
return arr[index];
}
int result = -1;
if (M < k) {
result = RandSelect(arr, index + 1, right, k);
}
else if (M > k) {
result = RandSelect(arr, left, index - 1, k);
}
return result;
}
7、已经有一个查询好友的接口,设计一个微信朋友圈,可以实现发表朋友圈,添加评论,查看评论等功能。主要是设计数据结构
(1)消息表( 存储用户发布的信息,utf8m64 可以存表情包 )
字段
类型
备注
id
bigint
自增主键
uid
varchar(20)
用户id
content
varchar(500)
内容
picture
varchar(200)
图片
location
varbinary(100)
位置
create_time
detetime
创建日期
(2)时间轴表( 存储这所有有用时间轴的信息,用户拉取朋友圈是查的这张表,根据type判定是否是自己发的)
字段
类型
备注
id
bigInt(15)
自增主键
fcm_id
bigint
朋友圈信息id,消息表中的id
uid
varchar(20)
用户id
type
tinyInt
0 表示自己的,1表示朋友发的
create_time
datetime
创建时间
(3) 评论表(记录评论和点赞数的)
字段
类型
备注
id
bigInt
自增主键
fcm_id
bigInt
朋友圈信息id,消息表中id
uid
varchar
用户id
content
varchar(200)
评论内容
like_count
int(10)
点赞数
create_time
datetime
时间
8、LRU算法实现
import java.util.HashMap;
public class LRU<K, V> {
private int currentSize;//当前的大小
private int capcity;//总容量
private HashMap<K, Node> caches;//所有的node节点
private Node first;//头节点
private Node last;//尾节点
public LRU(int size) {
currentSize = 0;
this.capcity = size;
caches = new HashMap<K, Node>(size);
}
/**
* 放入元素
* @param key
* @param value
*/
public void put(K key, V value) {
Node node = caches.get(key);
//如果新元素
if (node == null) {
//如果超过元素容纳量
if (caches.size() >= capcity) {
//移除最后一个节点
caches.remove(last.key);
removeLast();
}
//创建新节点
node = new Node(key,value);
}
//已经存在的元素覆盖旧值
node.value = value;
//把元素移动到首部
moveToHead(node);
caches.put(key, node);
}
/**
* 通过key获取元素
* @param key
* @return
*/
public Object get(K key) {
Node node = caches.get(key);
if (node == null) {
return null;
}
//把访问的节点移动到首部
moveToHead(node);
return node.value;
}
/**
* 根据key移除节点
* @param key
* @return
*/
public Object remove(K key) {
Node node = caches.get(key);
if (node != null) {
if (node.pre != null) {
node.pre.next = node.next;
}
if (node.next != null) {
node.next.pre = node.pre;
}
if (node == first) {
first = node.next;
}
if (node == last) {
last = node.pre;
}
}
return caches.remove(key);
}
/**
* 清除所有节点
*/
public void clear() {
first = null;
last = null;
caches.clear();
}
/**
* 把当前节点移动到首部
* @param node
*/
private void moveToHead(Node node) {
if (first == node) {
return;
}
if (node.next != null) {
node.next.pre = node.pre;
}
if (node.pre != null) {
node.pre.next = node.next;
}
if (node == last) {
last = last.pre;
}
if (first == null || last == null) {
first = last = node;
return;
}
node.next = first;
first.pre = node;
first = node;
first.pre = null;
}
/**
* 移除最后一个节点
*/
private void removeLast() {
if (last != null) {
last = last.pre;
if (last == null) {
first = null;
} else {
last.next = null;
}
}
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
Node node = first;
while (node != null) {
sb.append(String.format("%s:%s ", node.key, node.value));
node = node.next;
}
return sb.toString();
}
public static void main(String[] args) {
LRU<Integer, String> lru = new LRU<Integer, String>(5);
lru.put(1, "a");
lru.put(2, "b");
lru.put(3, "c");
lru.put(4,"d");
lru.put(5,"e");
System.out.println("原始链表为:"+lru.toString());
lru.get(4);
System.out.println("获取key为4的元素之后的链表:"+lru.toString());
lru.put(6,"f");
System.out.println("新添加一个key为6之后的链表:"+lru.toString());
lru.remove(3);
System.out.println("移除key=3的之后的链表:"+lru.toString());
}
}
9、手写一个栈实现Push、pop以及max,要求时间复杂度为O(1)
package com.my.test.datastructure.stack;
import java.util.Stack;
/*
* 实现一个栈 获取最大、最小值、pop()、push()都是O(1)复杂度
*/
public class MinMaxStack
{
private Stack<Integer> stack = new Stack<>();
private Stack<Integer> minStack = new Stack<>();
private Stack<Integer> maxStack = new Stack<>();
public void push(int value) {
// 插入元素
stack.push(value);
// 第一次push元素直接插入 或者 小于等于栈顶元素,则插入最小栈
if (minStack.empty() || minStack.peek() >= value) {
minStack.push(value);
}
// 第一次push元素 或者 大于等于栈顶元素,则插入最大栈
if (maxStack.empty() || maxStack.peek() <= value) {
maxStack.push(value);
}
}
public int pop() {
if (stack.empty()) {
System.out.println("stack is empty");
throw new RuntimeException("stack is empty");
}
int popValue = stack.pop();
// 元素为最大值或最小值则弹出
if (popValue == minStack.peek()) {
minStack.pop();
}
if (popValue == maxStack.peek()) {
maxStack.pop();
}
return popValue;
}
public int getMin() {
if (minStack.empty()) {
throw new RuntimeException("min stack is empty");
}
return minStack.peek();
}
public int getMax() {
if (maxStack.empty()) {
throw new RuntimeException("max stack is empty");
}
return maxStack.peek();
}
public static void main(String args[]) {
MinMaxStack stack = new MinMaxStack();
stack.push(2);
stack.push(3);
stack.push(1);
stack.push(3);
stack.push(1);
stack.push(4);
stack.push(2);
System.out.println(String.format("min: %s, max: %s", stack.getMin(), stack.getMax()));
stack.pop();
System.out.println(String.format("min: %s, max: %s", stack.getMin(), stack.getMax()));
stack.pop();
System.out.println(String.format("min: %s, max: %s", stack.getMin(), stack.getMax()));
stack.pop();
System.out.println(String.format("min: %s, max: %s", stack.getMin(), stack.getMax()));
stack.pop();
System.out.println(String.format("min: %s, max: %s", stack.getMin(), stack.getMax()));
}
}
10、合并链表
/**
* @auther: lawt
* @date: 2018/11/4 08
* @Description: 结点信息
*/
public class Node {
/**
* 为了方便,这两个变量都使用public,而不用private就不需要编写get、set方法了。
* 存放数据的变量,简单点,直接为int型
*/
public int data;
/**
* 存放结点的变量,默认为null
*/
public Node next;
/**
* 构造方法,在构造时就能够给data赋值
*/
public Node(int data) {
this.data = data;
}
}
/**
* @auther: lawt
* @date: 2018/11/6 09
* @Description: 两个有序单链表合并
*/
public class MyList {
/**
* 递归方式合并两个单链表
*
* @param head1 有序链表1
* @param head2 有序链表2
* @return 合并后的链表
*/
public static Node mergeTwoList(Node head1, Node head2) {
//递归结束条件
if (head1 == null && head2 == null) {
return null;
}
if (head1 == null) {
return head2;
}
if (head2 == null) {
return head1;
}
//合并后的链表
Node head = null;
if (head1.data > head2.data) {
//把head较小的结点给头结点
head = head2;
//继续递归head2
head.next = mergeTwoList(head1, head2.next);
} else {
head = head1;
head.next = mergeTwoList(head1.next, head2);
}
return head;
}
/**
* 非递归方式
*
* @param head1 有序单链表1
* @param head2 有序单链表2
* @return 合并后的单链表
*/
public static Node mergeTwoList2(Node head1, Node head2) {
if (head1 == null || head2 == null) {
return head1 != null ? head1 : head2;
}
//合并后单链表头结点
Node head = head1.data < head2.data ? head1 : head2;
Node cur1 = head == head1 ? head1 : head2;
Node cur2 = head == head1 ? head2 : head1;
Node pre = null;//cur1前一个元素
Node next = null;//cur2的后一个元素
while (cur1 != null && cur2 != null) {
//第一次进来肯定走这里
if (cur1.data <= cur2.data) {
pre = cur1;
cur1 = cur1.next;
} else {
next = cur2.next;
pre.next = cur2;
cur2.next = cur1;
pre = cur2;
cur2 = next;
}
}
pre.next = cur1 == null ? cur2 : cur1;
return head;
}
public static void main(String[] args) {
Node node1 = new Node(1);
Node node2 = new Node(2);
Node node3 = new Node(3);
Node node4 = new Node(4);
Node node5 = new Node(5);
node1.next = node3;
node3.next = node5;
node2.next = node4;
// Node node = mergeTwoList(node1, node2);
Node node = mergeTwoList2(node2, node1);
while (node != null) {
System.out.print(node.data + " ");
node = node.next;
}
}
}
11、求二叉树深度
利用递归求解
class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}
public class Solution {
public int TreeDepth(TreeNode root) {
if(root==null){
return 0;
}
int left=TreeDepth(root.left);
int right=TreeDepth(root.right);
return left>right?left+1:right+1;
}
}
利用非递归求解:利用队列(Queue)进行层次遍历
import java.util.Queue;
import java.util.LinkedList;
class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}
public class Solution {
public int TreeDepth(TreeNode root) {
if(root==null){
return 0;
}
int deep=0,count=0,nextCount=1;
//Queue<TreeNode> queue=new Queue<TreeNode>();
//Solution.java:17: error: Queue is abstract; cannot be instantiated
Queue<TreeNode> queue=new LinkedList<TreeNode>();
queue.add(root);
while(!queue.isEmpty()){
TreeNode p=queue.poll();
count++;
if(p.left!=null){
queue.add(p.left);
}
if(p.right!=null){
queue.add(p.right);
}
if(count==nextCount){
nextCount=queue.size();
count=0;
deep++;
}
}
return deep;
}
}
12、 两个栈实现队列
class CQueue {
Stack<Integer> stack1;
Stack<Integer> stack2;
int size;
public CQueue() {
stack1 = new Stack<Integer>();
stack2 = new Stack<Integer>();
size = 0;
}
public void appendTail(int value) {
while (!stack1.isEmpty()) {
stack2.push(stack1.pop());
}
stack1.push(value);
while (!stack2.isEmpty()) {
stack1.push(stack2.pop());
}
size++;
}
public int deleteHead() {
if (size == 0) {
return -1;
}
size--;
return stack1.pop();
}
}
13、给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
private TreeNode lca = null;
public TreeNode lowestCommonAncestor(TreeNode root,TreeNode p,TreeNode q){
if(root == null){
return null;
}
findNode(root,p,q);
return lca;
}
private boolean findNode(TreeNode root,TreeNode p,TreeNode q){
if(root == null){
return false;
}
int left = findNode(root.left,p,q)?1:0;
int right = findNode(root.right,p,q)?1:0;
int mid = (root == p || root == q)?1:0;
if(left + right + mid >= 2){
lca = root;
}
return (left + right + mid)>0;
}
声明:
本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:
https://www.wpsshop.cn/w/小丑西瓜9/article/detail/693854
推荐阅读
article
[
Java
]
Spring
Boot
3.0
升级
实战踩坑记录_
springboot
没有
3.0
.1...
Spring
Boot
常用于
Java
后端开发,于2022年11月24日正式发布了
3.0
.0版本,带来了全新的特性、
升级
了...
赞
踩
article
上传
Matlab
/
Python
/
Java
/毕设相关
资源
,奖金+创作分多项
奖励
!_
chatgpt
镜像6...
上传
资源
,快速赚钱_
chatgpt
镜像6月
chatgpt
镜像6月 一、活动任务
资源
类型时间
上传
...
赞
踩
article
【华为OD机试】
最多
购买
宝石
数目
(贪心算法实现-
Java
&
Python
&
C++
&JS实现)_
最多
购买
...
【华为OD机试】
最多
购买
宝石
数目
(贪心算法实现-
Java
&
Python
&
C++
&JS实现)橱窗里有一排
宝石
,不同的
宝石
对...
赞
踩
article
华为OD机试C、D卷 - 最多
购买
宝石
数目(
Java
& JS &
Python
& C & C++...
橱窗里有一排
宝石
,不同的
宝石
对应不同的价格,
宝石
的价格标记为 gems[i]0 ≤ i < nn = gems.leng...
赞
踩
article
java
curator
_
关于
Curator
学习过程问题...
今天在学习
Curator
框架,查询了很多别人的例子照写都报错。然后上
Curator
(http://
curator
.apa...
赞
踩
article
java
多
线程
线程
安全
及非
线程
安全
的
集合
对象_
java
多
线程
环境下使用非
线程
安全
的
集合
...
一、概念:
线程
安全
:就是当多
线程
访问时,采用了加锁
的
机制;即当一个
线程
访问该类
的
某个数据时,会对这个数据进行保护,其他线...
赞
踩
article
java
多线程
面试题
及答案_
java
多线程
面试题
...
并行和并发有什么区别?并行是指两个或者多个事件在同一时刻发生;而并发是指两个或多个事件在同一时间间隔发生。并行没有对 C...
赞
踩
article
Java
多线程
常见基础
面试
题
总结
,
面试
必看!_
java
多线程
面试
题
...
1.1. 何为进程?进程是程序的一次执行过程
,
是系统运行程序的基本单位
,
因此进程是动态的。系统运行一个程序即是一个进程从...
赞
踩
article
java
多线程
面试题
整理(
更新
......)_
java
多线程
面试题
...
一、基础知识1、什么是线程和进程?什么是进程?进程的特点:什么是线程?区别与联系?2、什么是并行与并发?3、什么是同步执...
赞
踩
article
Java
多
线程
面试题_
java
线程
安全面试...
前言在看完《
Java
多
线程
编程核心技术》与《
Java
并发编程的艺术》之后,对于
多
线程
的理解到了新的境界. 先拿如下的题目...
赞
踩
article
小
程序
消息
订阅
(
java
版)_微信
小
程序
订阅
消息
java
...
小
程序
消息
订阅
(
java
版)_微信
小
程序
订阅
消息
java
微信
小
程序
订阅
消息
java
1、
小
程...
赞
踩
article
spring
boot
微信小程序实现发现一次性订阅消息_wx-
java
-
miniapp
-
spring
...
spring
boot
使用wx-
java
-
miniapp
-
spring
-
boot
-
starter
实现小程序发送订阅消息推送...
赞
踩
article
Java
项目
-
SpringBoot
+Vue的
智慧
养老
系统_
智慧
养老
java
...
Java
项目
-
SpringBoot
+Vue的
智慧
养老
系统_
智慧
养老
java
智慧
养老
java
...
赞
踩
article
ElasticSearch 实现
全文
检索
支持(PDF、TXT、Word、HTML等
文件
)通过 i...
后续我们的
文件
需要base64后储存到
attachment
.content 索引字段中。接下来我们需要创建一个关于in...
赞
踩
article
数据结构
(
一)-
数据结构
基本概念
(
Java
、
C语言
)_
数据结构
java
纶绪...
一、引言
数据结构
这门课相信大家都不陌生,只要想从事计算机相关与互联网相关的工作,这门课都是必不可少的课。但是我并不是计算...
赞
踩
article
华为
OD机试
C
卷
--
结队
编程
(
Java
& JS &
Python
&
C
)...
某部门计划通过
结队
编程
来进行项目开发,已知该部门有 N 名员工,每个员工有独一无二的职级,每三个员工形成一个小组进行
结队
...
赞
踩
article
Java
实现
微信
扫码
登录
方法(提供前端及后端核心代码)_
java
微信
扫码
登录
...
Java
实现
微信
扫码
登录
方法(提供前端及后端核心代码)_
java
微信
扫码
登录
java
微信
扫码
登录
...
赞
踩
article
华为
OD机试C卷
--
可以组成网络
的
服务器
(
Java
& JS &
Python
& C)...
在一个机房中,
服务器
的
位置标识在 n*m
的
整数矩阵网格中,1 表示单元格上有
服务器
,0 表示没有。如果两台
服务器
位于同...
赞
踩
article
jadx
-
gui
-1.5
反
编译
工具
使用教程
反
混淆
Java
android
查看签名...
JADX:JADX是一个强大的
反
编译
工具
,它支持命令行和图形界面操作。除了基本的
反
编译
功能外,JADX还提供了
反
混淆功能...
赞
踩
article
数据库
课程设计
:
会议
预约
管理系统
(
Java
+MySQL)_
数据库
课程设计
会议
预约
管理系统
报告...
分享一个简单的
Java
+JDBC+MySQL
数据库
开发的
会议
预约
管理系统
,完成简单的基础功能,如登录验证,
会议
预约
,个人...
赞
踩
相关标签
java
spring boot
spring
活动
实时互动
内容运营
华为od
c语言
贪心算法
最多购买宝石数目
python
javascript
java curator
多线程
线程安全
非线程安全
集合对象
面试
开发语言
锁
并发