K个一组翻转链表
K个一组翻转链表给你链表的头节点 head ,每 k 个节点一组进行翻转,请你返回修改后的链表。
k 是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。
你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。
示例 1:
12输入:head = [1,2,3,4,5], k = 2输出:[2,1,4,3,5]
示例 2:
12输入:head = [1,2,3,4,5], k = 3输出:[3,2,1,4,5]
提示:
链表中的节点数目为 n
1 <= k <= n <= 5000
0 <= Node.val <= 1000
进阶:你可以设计一个只用 O(1) 额外内存空间的算法解决此问题吗?
题目不难,就是涉及到的点很多容易绕晕。
直接看代码
1234567891011121314151617181920212223242526272829303132class Solution { public ListNode reverseKGroup(ListNode ...
多线程
多线程0.并发编程的3个重要特性Java并发编程三大特性
原子性
可见性
有序性
(1)原子性一个线程在CPU中操作不可暂停,也不可中断,要不执行完成,要不不执行
若不保证原子性,可能出现订单超卖问题
解决方案:
1.synchronized:同步加锁
2.JUC里面的lock:加锁
(2)内存可见性内存可见性:让一个线程对共享变量的修改对另一个线程可见
解决方案:
synchronized
volatile(推荐)
LOCK
(3)有序性指令重排:处理器为了提高程序运行效率,可能会对输入代码进行优化,它不保证程序中各个语句的执行先后顺序同代码中的顺序一致,但是它会保证程序最终执行结果和代码顺序执行的结果是一致的
解决方案:
volatile
1.线程进程0.Thread的join()方法1.join()的作用join()是 Thread 类中的一个方法,当我们需要让线程按照自己指定的顺序执行的时候,就可以利用这个方法。「Thread.join()方法表示调用此方法的线程被阻塞,仅当该方法完成以后,才能继续运行」。
❝ 作用于 main( )主线程时,会等待其他线程结束后 ...
两数相加
两数相加给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。
请你将两个数相加,并以相同形式返回一个表示和的链表。
你可以假设除了数字 0 之外,这两个数都不会以 0 开头。
示例 1:
123输入:l1 = [2,4,3], l2 = [5,6,4]输出:[7,0,8]解释:342 + 465 = 807.
示例 2:
12输入:l1 = [0], l2 = [0]输出:[0]
示例 3:
12输入:l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]输出:[8,9,9,9,0,0,0,1]
提示:
每个链表中的节点数在范围 [1, 100] 内
0 <= Node.val <= 9
题目数据保证列表表示的数字不含前导零
参考上一题(数组形式的整数加法)中的模板,两道题基本一样
1234567891011121314151617181920212223242526class Solution { public ListNode addTwoNumbers( ...
数组形式的整数加法
数组形式的整数加法整数的 数组形式 num 是按照从左到右的顺序表示其数字的数组。
例如,对于 num = 1321 ,数组形式是 [1,3,2,1] 。
给定 num ,整数的 数组形式 ,和整数 k ,返回 整数 num + k 的 数组形式 。
示例 1:
123输入:num = [1,2,0,0], k = 34输出:[1,2,3,4]解释:1200 + 34 = 1234
示例 2:
123输入:num = [2,7,4], k = 181输出:[4,5,5]解释:274 + 181 = 455
示例 3:
123输入:num = [2,1,5], k = 806输出:[1,0,2,1]解释:215 + 806 = 1021
提示:
1 <= num.length <= 10^4
0 <= num[i] <= 9
num 不包含任何前导零,除了零本身
1 <= k <= 10^4
加法模板
123456789while ( A 没完 || B 没完 || 进位没加完) A 的当前位 B 的当前位 和 = A ...
消息中间件
消息中间件1.消息队列0.什么是消息队列?我们可以把消息队列看作是一个存放消息的容器,当我们需要使用消息的时候,直接从容器中取出消息供自己使用即可。
队列Queue是一种先进先出的数据结构,所以消费消息时也是按照顺序来消费的。
1.为什么要使用消息队列/消息队列有什么用?总结一下,主要三点原因:解耦、异步、削峰。
1、解耦。使用消息队列,可以避免模块之间直接调用,将所需共享的数据放在消息队列中,对于新增业务模块,只要对该类消息感兴趣,即可订阅该类消息,对原有系统和业务没有任何影响,降低了系统各个模块的耦合度,提高了系统的可扩展性。
2、异步。消息队列允许生产者将消息发送到队列中,而不需要等待消费者立即处理。这样可以实现异步通信,提高系统的响应速度和吞吐量。
3、削峰。消息队列可以将消息存储起来,供消费者在适当的时间进行处理,从而实现延迟处理。高峰期的消息可以被积压起来,在随后的时间内进行平滑的处理完成,而不至于让系统短时间内无法承载而导致崩溃。在电商网站的秒杀抢购这种突发性流量很强的业务场景中,消息队列的强大缓冲能力可以很好的起到削峰作用。
2. 使用了消息队列会有什么缺点
...
合并两个有序链表
合并两个有序链表将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
示例 1:
12输入:l1 = [1,2,4], l2 = [1,3,4]输出:[1,1,2,3,4,4]
示例 2:
12输入:l1 = [], l2 = []输出:[]
示例 3:
12输入:l1 = [], l2 = [0]输出:[0]
提示:
两个链表的节点数目范围是 [0, 50]
-100 <= Node.val <= 100
l1 和 l2 均按 非递减顺序 排列
经典合并问题,遍历两个链表,每次将较小的节点尾插。
12345678910111213141516171819class Solution { public ListNode mergeTwoLists(ListNode list1, ListNode list2) { ListNode head = new ListNode(200); ListNode tail = head; while (list ...
环形链表
环形链表给你一个链表的头节点 head ,判断链表中是否有环。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos 不作为参数进行传递 。仅仅是为了标识链表的实际情况。
如果链表中存在环 ,则返回 true 。 否则,返回 false 。
示例 1:
123输入:head = [3,2,0,-4], pos = 1输出:true解释:链表中有一个环,其尾部连接到第二个节点。
示例 2:
123输入:head = [1,2], pos = 0输出:true解释:链表中有一个环,其尾部连接到第一个节点。
示例 3:
123输入:head = [1], pos = -1输出:false解释:链表中没有环。
提示:
链表中节点的数目范围是 [0, 104]
-105 <= Node.val <= 105
pos 为 -1 或者链表中的一个 有效索引 。
进阶:你能用 O(1)(即,常量)内存解决此问题吗?
方法一,用 ...
回文链表
回文链表给你一个单链表的头节点 head ,请你判断该链表是否为
回文链表
。如果是,返回 true ;否则,返回 false 。
示例 1:
12输入:head = [1,2,2,1]输出:true
示例 2:
12输入:head = [1,2]输出:false
提示:
链表中节点数目在范围[1, 105] 内
0 <= Node.val <= 9
进阶:你能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题?
将所有元素存起来用双指针
123456789101112131415161718class Solution { public boolean isPalindrome(ListNode head) { List<Integer> list = new ArrayList<>(); ListNode p = head; while (p != null) { list.add(p.val); p = ...
搜索二维矩阵 II
搜索二维矩阵 II编写一个高效的算法来搜索 *m* x *n* 矩阵 matrix 中的一个目标值 target 。该矩阵具有以下特性:
每行的元素从左到右升序排列。
每列的元素从上到下升序排列。
示例 1:
12输入:matrix = [[1,4,7,11,15],[2,5,8,12,19],[3,6,9,16,22],[10,13,14,17,24],[18,21,23,26,30]], target = 5输出:true
示例 2:
12输入:matrix = [[1,4,7,11,15],[2,5,8,12,19],[3,6,9,16,22],[10,13,14,17,24],[18,21,23,26,30]], target = 20输出:false
提示:
m == matrix.length
n == matrix[i].length
1 <= n, m <= 300
-109 <= matrix[i][j] <= 109
每行的所有元素从左到右升序排列
每列的所有元素从上到下升序排列
-109 <= target <= ...
搜索二维矩阵
搜索二维矩阵给你一个满足下述两条属性的 m x n 整数矩阵:
每行中的整数从左到右按非严格递增顺序排列。
每行的第一个整数大于前一行的最后一个整数。
给你一个整数 target ,如果 target 在矩阵中,返回 true ;否则,返回 false 。
示例 1:
12输入:matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]], target = 3输出:true
示例 2:
12输入:matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]], target = 13输出:false
提示:
m == matrix.length
n == matrix[i].length
1 <= m, n <= 100
-104 <= matrix[i][j], target <= 104
两次二分,先找到行,再找到列。注意,不能先确定列再确定行。
12345678910111213141516171819202122232425262728class Solution ...