- 博客(58)
- 收藏
- 关注
原创 剑指 Offer 52. 两个链表的第一个公共节点
剑指 Offer 52. 两个链表的第一个公共节点思路一:哈希表,分别遍历链表A,B。发现Hash表中contains某个节点,就说明找到了。否则返回null;/** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { * val = x; * next = nul
2021-12-11 10:53:41
384
原创 剑指 Offer 07. 重建二叉树
输入某二叉树的前序遍历和中序遍历的结果,请构建该二叉树并返回其根节点。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。思路:我们知道,如果只由前序遍历或者中序遍历是无法唯一确定一棵二叉树,除非你给的前序遍历或者中序遍历包括了null节点。而通过观察,我们可以发现,前序遍历拿到的根放置中序遍历,根的左区间和右区间分别对应当前根的左子树和右子树。我们递归调用即可完成这棵二叉树的重构。具体见代码;/** * Definition for a binary tree node. * public
2021-12-04 19:36:17
155
原创 剑指 Offer 13. 机器人的运动范围
剑指 Offer 13. 机器人的运动范围地上有一个m行n列的方格,从坐标 [0,0] 到坐标 [m-1,n-1] 。一个机器人从坐标 [0, 0] 的格子开始移动,它每次可以向左、右、上、下移动一格(不能移动到方格外),也不能进入行坐标和列坐标的数位之和大于k的格子。例如,当k为18时,机器人能够进入方格 [35, 37] ,因为3+5+3+7=18。但它不能进入方格 [35, 38],因为3+5+3+8=19。请问该机器人能够到达多少个格子?示例 1:输入:m = 2, n = 3, k = 1
2021-12-04 19:18:21
161
原创 剑指 Offer 12. 矩阵中的路径
剑指 Offer 12. 矩阵中的路径给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false 。单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。 例如,在下面的 3×4 的矩阵中包含单词 "ABCCED"(单词中的字母已标出)。示例 1:输入:board = [["A","B","C","E"],
2021-12-01 19:21:35
141
原创 剑指 Offer 11. 旋转数组的最小数字
剑指 Offer 11. 旋转数组的最小数字把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。给你一个可能存在 重复 元素值的数组 numbers ,它原来是一个升序排列的数组,并按上述情形进行了一次旋转。请返回旋转数组的最小元素。例如,数组 [3,4,5,1,2] 为 [1,2,3,4,5] 的一次旋转,该数组的最小值为1。 示例 1:输入:[3,4,5,1,2]输出:1示例 2:输入:[2,2,2,0,1]输出:0思路:数组分为两部分,两部分都各自有
2021-11-30 22:32:45
441
原创 剑指 Offer 53 - I. 在排序数组中查找数字 I
剑指 Offer 53 - I. 在排序数组中查找数字 I统计一个数字在排序数组中出现的次数。示例 1:输入: nums = [5,7,7,8,8,10], target = 8输出: 2示例 2:输入: nums = [5,7,7,8,8,10], target = 6输出: 0思路一:可以直接遍历数组,记录目标值的个数即可。思路二:我们观察到题目给到的数组是一个已经有序的数组,故我们可以考虑采用二分法分别来查找最左以及最右的目标值的索引,最后进行相减即可,但是我们知道二分法只是
2021-11-15 22:47:28
66
原创 剑指 Offer 47. 礼物的最大价值
剑指 Offer 47. 礼物的最大价值在一个 m*n 的棋盘的每一格都放有一个礼物,每个礼物都有一定的价值(价值大于 0)。你可以从棋盘的左上角开始拿格子里的礼物,并每次向右或者向下移动一格、直到到达棋盘的右下角。给定一个棋盘及其上面的礼物的价值,请计算你最多能拿到多少价值的礼物?示例 1:输入: [ [1,3,1], [1,5,1], [4,2,1]]输出: 12解释: 路径 1→3→5→2→1 可以拿到最多价值的礼物思路一:本题可以使用DFS搜索class Solu
2021-11-14 21:45:52
47
原创 剑指 Offer 46. 把数字翻译成字符串
剑指 Offer 46. 把数字翻译成字符串给定一个数字,我们按照如下规则把它翻译为字符串:0 翻译成 “a” ,1 翻译成 “b”,……,11 翻译成 “l”,……,25 翻译成 “z”。一个数字可能有多个翻译。请编程实现一个函数,用来计算一个数字有多少种不同的翻译方法。示例 1:输入: 12258输出: 5解释: 12258有5种不同的翻译,分别是"bccfi", "bwfi", "bczi", "mcfi"和"mzi"思路:考虑使用动态规划,我们可以假设x1x2x3…xn的解的个数为f
2021-11-14 21:34:47
66
原创 剑指 Offer 56 - II. 数组中数字出现的次数 II
剑指 Offer 56 - II. 数组中数字出现的次数 II在一个数组 nums 中除一个数字只出现一次之外,其他数字都出现了三次。请找出那个只出现一次的数字。 示例 1:输入:nums = [3,4,3,3]输出:4示例 2:输入:nums = [9,1,7,9,7,9,7]输出:1思路:我们记录每个二进制位出现1的次数,统计完成之后将记录的数据对3求余,就可以得到那个只出现一次的那个数字该二进制的情况。class Solution { public int sin
2021-11-13 20:06:58
416
原创 剑指 Offer II 109. 开密码锁
剑指 Offer II 109. 开密码锁一个密码锁由 4 个环形拨轮组成,每个拨轮都有 10 个数字: ‘0’, ‘1’, ‘2’, ‘3’, ‘4’, ‘5’, ‘6’, ‘7’, ‘8’, ‘9’ 。每个拨轮可以自由旋转:例如把 ‘9’ 变为 ‘0’,‘0’ 变为 ‘9’ 。每次旋转都只能旋转一个拨轮的一位数字。锁的初始数字为 ‘0000’ ,一个代表四个拨轮的数字的字符串。列表 deadends 包含了一组死亡数字,一旦拨轮的数字和列表里的任何一个元素相同,这个锁将会被永久锁定,无法再被旋转。
2021-11-08 21:38:48
319
原创 剑指 Offer 39. 数组中出现次数超过一半的数字
剑指 Offer 39. 数组中出现次数超过一半的数字数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。你可以假设数组是非空的,并且给定的数组总是存在多数元素输入: [1, 2, 3, 2, 2, 2, 5, 4, 2]输出: 2思路1:直接排序,然后返回中间索引位置的元素即可,如果调用API的话,只要两行代码,建议可以自己实现快排。class Solution { public int majorityElement(int[] nums) { quick
2021-11-07 15:18:37
52
原创 剑指 Offer 31. 栈的压入、弹出序列
剑指 Offer 31. 栈的压入、弹出序列输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如,序列 {1,2,3,4,5} 是某栈的压栈序列,序列 {4,5,3,2,1} 是该压栈序列对应的一个弹出序列,但 {4,3,5,1,2} 就不可能是该压栈序列的弹出序列。输入:pushed = [1,2,3,4,5], popped = [4,5,3,2,1]输出:true解释:我们可以按以下顺序执行:push(1), push(2),
2021-11-07 10:40:11
70
原创 剑指 Offer 42. 连续子数组的最大和
剑指 Offer 42. 连续子数组的最大和输入一个整型数组,数组中的一个或连续多个整数组成一个子数组。求所有子数组的和的最大值。要求时间复杂度为O(n)。输入: nums = [-2,1,-3,4,-1,2,1,-5,4]输出: 6解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。思路:动态规划,dp[i]代表数组前i个的连续最大值;class Solution { public int maxSubArray(int[] nums) { int[] dp
2021-11-06 16:34:44
48
原创 剑指 Offer 41. 数据流中的中位数
剑指 Offer 41. 数据流中的中位数如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。例如,[2,3,4] 的中位数是 3[2,3] 的中位数是 (2 + 3) / 2 = 2.5设计一个支持以下两种操作的数据结构:void addNum(int num) - 从数据流中添加一个整数到数据结构中。double findMedian() - 返回目前所有元
2021-11-05 10:51:11
62
原创 剑指 Offer 30. 包含min函数的栈
剑指 Offer 30. 包含min函数的栈定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的 min 函数在该栈中,调用 min、push 及 pop 的时间复杂度都是 O(1)思路:再压入元素之前,先将当前元素未压入之前的最小值压入栈中,这样弹栈后就能及时更新最小值。class MinStack { /** initialize your data structure here. */ int min_num = Integer.MAX_VALUE; Dequ
2021-11-05 10:20:23
50
原创 剑指 Offer 40. 最小的k个数
剑指 Offer 40. 最小的k个数输入整数数组 arr ,找出其中最小的 k 个数。例如,输入4、5、1、6、2、7、3、8这8个数字,则最小的4个数字是1、2、3、4。思路一:排序后,选取前k个数值返回。由于是简单题,所以自己实现快排,不调用sort函数。class Solution { public int[] getLeastNumbers(int[] arr, int k) { quickSort(arr, 0, arr.length - 1);
2021-11-04 21:20:46
69
原创 剑指 Offer 35. 复杂链表的复制
剑指 Offer 35. 复杂链表的复制请实现 copyRandomList 函数,复制一个复杂链表。在复杂链表中,每个节点除了有一个 next 指针指向下一个节点,还有一个 random 指针指向链表中的任意节点或者 null。思路:用HashMap去记录节点的信息,构建新的节点,映射到哈希表中的next以及random即可。/*// Definition for a Node.class Node { int val; Node next; Node random;
2021-11-04 19:14:30
62
原创 剑指 Offer 18. 删除链表的节点
剑指 Offer 18. 删除链表的节点给定单向链表的头指针和一个要删除的节点的值,定义一个函数删除该节点。返回删除后的链表的头节点。注意:此题对比原题有改动思路:遍历链表,如果当前节点的后继是我们要删除的节点,就删除。这里解释一下为什么要用节点的后继来判断,而不是用当前节点的值,因为如果用当前节点的值来判断,那么当前节点的删除需要前驱节点,否则节点会丢失,导致链表断链。比如1–>2–>3,如果我要删除2,我必须有1这个节点的地址,反之如果我判断1的后继是不是我们要删除的节点,就不用再
2021-11-04 19:06:20
78
原创 剑指 Offer 22. 链表中倒数第k个节点
剑指 Offer 22. 链表中倒数第k个节点输入一个链表,输出该链表中倒数第k个节点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾节点是倒数第1个节点。例如,一个链表有 6 个节点,从头节点开始,它们的值依次是 1、2、3、4、5、6。这个链表的倒数第 3 个节点是值为 4 的节点。思路分析:使用快慢指针,先让快指针走k步,然后快慢指针同时移动,这样快指针指向null的时候,慢指针就指向倒数第k个元素了/** * Definition for singly-linked list.
2021-10-14 20:21:02
43
原创 剑指 Offer 29. 顺时针打印矩阵
剑指 Offer 29. 顺时针打印矩阵输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。思路分析:依据题意,是顺时针打印矩阵,所以打印方向就是右、下、左、上。一直重复这个过程直到打印结束。所以我们可以定义一个direction方向数组,以及visit访问数组,如果已经访问过了,或者访问的索引越界了,我们就更新方向。class Solution { public int[] spiralOrder(int[][] matrix) { if(matrix == nu
2021-10-14 19:57:32
60
原创 剑指 Offer 09. 用两个栈实现队列
剑指 Offer 09. 用两个栈实现队列用两个栈实现一个队列。队列的声明如下,请实现它的两个函数 appendTail 和 deleteHead ,分别完成在队列尾部插入整数和在队列头部删除整数的功能。(若队列中没有元素,deleteHead 操作返回 -1 )思路:一个栈用来进行入队操作,另一个栈完成出队操作。当我们需要入队时,只需要执行push操作即可,而出队时,由于队列是先进先出,栈是先进后出,即本该出队的元素此时在栈底。我们将stack1的元素弹栈至stack2,这样本该出队的元素就在栈顶了
2021-09-03 11:13:52
45
原创 Leetcode237. 删除链表中的节点
题目思路:这题最ex的是什么知道吗,他只给了你要删除的节点信息,但是不给链表,意思要我原地删除。后来看了评论区,才发现人才济济,我变成你,然后再删除你。public void deleteNode(ListNode node) { node.val = node.next.val; node.next = node.next.next; }自行体会其中的奥义,感觉是出脑筋急转弯来了这题就当娱乐了,也懒得分析什么了...
2021-06-11 17:42:08
38
原创 Leetcode142. 环形链表 II
题目给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。注意,pos 仅仅是用于标识环的情况,并不会作为参数传递到函数中。说明:不允许修改给定的链表。来源:力扣(LeetCode)链接:https://leetcode-cn.com/problems/linked-list-cycle-ii著作权归领扣网络所有。商业转载请联系官
2021-06-11 17:36:05
39
原创 Leetcode86. 分隔链表
题目给你一个链表的头节点 head 和一个特定值 x ,请你对链表进行分隔,使得所有 小于 x 的节点都出现在 大于或等于 x 的节点之前。你应当 保留 两个分区中每个节点的初始相对位置。来源:力扣(LeetCode)链接:https://leetcode-cn.com/problems/partition-list著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。思路:小的放左边,大的放右边,有点像插入排序,那我们只需要维护两个链表,一个链表是小于给定的val值,另一个链表
2021-06-11 17:27:05
93
原创 Leetcode82. 删除排序链表中的重复元素 II
题目存在一个按升序排列的链表,给你这个链表的头节点 head ,请你删除链表中所有存在数字重复情况的节点,只保留原始链表中 没有重复出现 的数字。返回同样按升序排列的结果链表。来源:力扣(LeetCode)链接:https://leetcode-cn.com/problems/remove-duplicates-from-sorted-list-ii著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。思路:这题和83题的删除重复节点不同的是,83题会保留一个重复的元素,而此题
2021-06-11 17:18:21
49
原创 Leetcode61. 旋转链表
题目给你一个链表的头节点 head ,旋转链表,将链表每个节点向右移动 k 个位置。思路:题目很短,但是通过例子不难发现,k是指旋转的次数,但同时也能发现,如果我们将此时的链表当成一个循环链表,那么原来倒数第K个节点就是我们想要的头节点。但同时还要注意一点,这个K是有可能超过链表长度的,而超出的部分其实是在做无用功,比如链表长度是2,K=5,旋转5次,但是通过发现不难得出,旋转5次和旋转1次的结果相同,即我们对k取余,除数是length(链表长度)。最后我们回归到求倒数第K个节点这个问题上即可,通过快
2021-06-11 17:07:07
108
原创 Leetcode24. 两两交换链表中的节点
给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。思路:这题有点投机取巧了,通过观察可以发现,两两交换是由规律的,下面用第几个元素来代表交换后的链表。 2 1 4 3 6 5 8 7 10 9…可以看到遇到第n个节点,如果n是奇数,下一个元素就是n+3,如果n是偶数,下个元素就是n-1。由于待会遍历的数组,所以索引下标和n是差1的,所以以上的结论要反过来。如果链表长度是偶数,那就会全部遍历完,如果是奇数,那还会剩余最后一个,我们需要
2021-06-11 16:51:50
75
原创 Leetcode2. 两数相加
给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。请你将两个数相加,并以相同形式返回一个表示和的链表。你可以假设除了数字 0 之外,这两个数都不会以 0 开头。来源:力扣(LeetCode)链接:https://leetcode-cn.com/problems/add-two-numbers著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。思路:由于给定的链表都是逆序的,也就是第一个节点是个位数,第二个节
2021-06-11 16:40:30
43
原创 Leetcode328. 奇偶链表
题目给定一个单链表,把所有的奇数节点和偶数节点分别排在一起。请注意,这里的奇数节点和偶数节点指的是节点编号的奇偶性,而不是节点的值的奇偶性。请尝试使用原地算法完成。你的算法的空间复杂度应为 O(1),时间复杂度应为 O(nodes),nodes 为节点总数。思路:双指针,一个指针用来指向奇数链表,一个指针用来指向偶数链表,最后把这两个链表合并。public ListNode oddEvenList(ListNode head) { // 如果链表为空 或者只有一个元素,就返回链表即
2021-05-17 15:59:47
54
原创 Leetcode1721. 交换链表中的节点
题目给你链表的头节点 head 和一个整数 k 。交换 链表正数第 k 个节点和倒数第 k 个节点的值后,返回链表的头节点(链表 从 1 开始索引)。思路一:把链表放到list中,这样就可以通过索引下标来定位我们要找到的两个交换节点。public ListNode swapNodes(ListNode head, int k) { // 创建列表 List<ListNode> list = new ArrayList<>();
2021-05-17 15:51:55
187
原创 Leetcode92. 反转链表 II
题目给你单链表的头指针 head 和两个整数 left 和 right ,其中 left <= right 。请你反转从位置 left 到位置 right 的链表节点,返回 反转后的链表 。思路:我们通过一个计数器来找到需要反转的区间,同时我们找到这个区间的前驱以及后继,这样等下拼接的时候就不会丢失地址了。我们把分割的区间单独拎出来进行反转,然后进行拼接。public ListNode reverseBetween(ListNode head, int left, int right) {
2021-05-17 11:26:33
124
原创 Leetcode1290. 二进制链表转整数
题目给你一个单链表的引用结点 head。链表中每个结点的值不是 0 就是 1。已知此链表是一个整数数字的二进制表示形式。请你返回该链表所表示数字的 十进制值 。思路1:链表的值用字符串存储,然后调函数解决。public int getDecimalValue(ListNode head) { StringBuffer sb = new StringBuffer(); while(head!=null){ sb.append(head.val)
2021-05-16 11:39:58
42
原创 Leetcode876. 链表的中间结点
题目给定一个头结点为 head 的非空单链表,返回链表的中间结点。如果有两个中间结点,则返回第二个中间结点。思路1:我们可以遍历链表,记录链表的节点个数,这样我们就知道我们想找的中间的那个链表的位置。这种方法就不贴代码了,提供一种思路而已(好吧,实际上我没写这种hhhh)思路2:我们知道,链表不支持随机访问,只支持顺序访问,也就是只能从头开始遍历才能找到我们想要的节点。我们可以将链表放到Arraylist中,通过索引下标来返回中间节点。public ListNode middleNode(Lis
2021-05-16 11:24:10
56
原创 Leetcode234. 回文链表
题目请判断一个链表是否为回文链表。思路:遍历链表,把链表的val值放到list中。然后用双指针判断是否回文,一旦有一个对称位置不相等,我们就认为不是回文链表。如果循环结束了,说明是回文链表,返回true。public boolean isPalindrome(ListNode head) { // 创建Arraylist存储链表数据 List<Integer> list = new ArrayList<>(); // 遍历列表
2021-05-16 11:06:26
38
原创 Leetcode206. 反转链表
题目给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。思路:创建一个空链表,然后头插法。public ListNode reverseList(ListNode head) { // 头插法 ListNode new_list = new ListNode(0,null); while(head!=null){ ListNode new_list_next = new_list.next;
2021-05-13 21:58:29
31
原创 Leetcode 203. 移除链表元素
题目给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 。思路:遍历加判断,最后根据链表删除的逻辑来删除即可。public ListNode removeElements(ListNode head, int val) { // 定义一个带头节点的新链表,这个头节点指向head链表 ListNode new_head = new ListNode(0,head);
2021-05-12 22:03:10
30
原创 Leetcode160. 相交链表
题目编写一个程序,找到两个单链表相交的起始节点。如下面的两个链表:思路一:用哈希表来做,先遍历链表A,再把各个节点信息存到哈希表中。再遍历链表B,如果第一个加不进去的节点就是相交节点。如果都没有相交,即都存入成功,我们就返回nullpublic ListNode getIntersectionNode(ListNode headA, ListNode headB) { Set<ListNode> set = new HashSet<>();
2021-05-11 22:37:04
174
原创 Leetcode141. 环形链表
题目给定一个链表,判断链表中是否有环。如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。如果链表中存在环,则返回 true 。 否则,返回 false 。进阶:你能用 O(1)(即,常量)内存解决此问题吗?思路一:用哈希表来存储遍历过的节点,如果这个节点在
2021-05-09 22:35:59
58
原创 Leetcode83. 删除排序链表中的重复元素
题目存在一个按升序排列的链表,给你这个链表的头节点 head ,请你删除所有重复的元素,使每个元素 只出现一次 。返回同样按升序排列的结果链表。思路:一边遍历一边比较,设置两个节点指针。如果val值一样,我们就让temp2后移直到val值不一样,然后temp1.next直接指向temp2即可。最后直到temp2为空即可。public ListNode deleteDuplicates(ListNode head) { // 定义一个带头节点的新链表 ListNode
2021-05-08 22:22:06
48
原创 Leetcode 21. 合并两个有序链表
题目将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。思路:把链表2的元素插入到链表1。通过比较val的值来插入。public ListNode mergeTwoLists(ListNode l1, ListNode l2) { // 分别为两个链表创建头节点,变成新链表 ListNode list1 = new ListNode(0,l1); ListNode list2 = new ListNode(0
2021-05-07 21:37:07
50
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人