一、LeetCode介绍
LeetCode是一个在线编程网站,提供各种算法和数据结构的题目,面向程序员、计算机科学专业学生和技术爱好者等人群,旨在帮助他们提高算法和编程技能。LeetCode上的问题通常来自各种技术公司的面试题目,因此它也是程序员面试准备的重要资源之一。
LeetCode上的问题涵盖了各种难度级别,从入门级到专家级都有不同难度的题目可供练习。用户可以选择使用不同的编程语言提交答案,LeetCode能够对结果进行评估并返回测试结果。
除了题目外,LeetCode还提供了讨论区、排行榜等社区功能,用户可以在这里交流学习心得、解决疑难问题,并与其他用户比较自己的做题成绩。
挑战100天 AI In LeetCode是基于LeetCode题库,借助AI的能力进行解题、并学习其解题过程。
二、LeetCode 热题 HOT 100-2
2.1 题目
两数相加
给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。 请你将两个数相加,并以相同形式返回一个表示和的链表。 你可以假设除了数字 0 之外,这两个数都不会以 0 开头。 示例 1: 输入:l1 = [2,4,3], l2 = [5,6,4] 输出:[7,0,8] 解释:342 + 465 = 807. 示例 2: 输入:l1 = [0], l2 = [0] 输出:[0] 示例 3: 输入: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 题目数据保证列表表示的数字不含前导零
2.2 题解
这个算法的时间复杂度是 O(max(m, n)),其中 m 和 n 分别是两个链表的长度。
解题思路:
这道题目要求我们对两个链表表示的逆序数字进行相加,并返回一个新的链表表示结果。
我们可以使用一个指针 curr 来遍历两个链表,同时使用一个变量 carry 来保存进位值。
- 首先,我们创建一个虚拟头节点 dummyHead,并将 curr 指向虚拟头节点。
- 然后,我们分别遍历两个链表,将对应位置上的数字相加,并加上进位值 carry。
- 每次相加后,我们将得到的个位数作为新节点的值,并将 curr 指向这个新节点。
- 同时,我们更新进位值 carry 为当前和除以 10 的结果,表示是否有进位。
- 最后,如果还存在进位,我们需要创建一个新节点来保存进位值。
- 最后返回虚拟头节点的下一个节点,即为结果链表。
/** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode() {} * ListNode(int val) { this.val = val; } * ListNode(int val, ListNode next) { this.val = val; this.next = next; } * } */ public class Solution { public ListNode addTwoNumbers(ListNode l1, ListNode l2) { ListNode dummyHead = new ListNode(0); // 创建一个虚拟头节点 ListNode curr = dummyHead; // 当前指针 int carry = 0; // 进位 while (l1 != null || l2 != null) { int x = (l1 != null) ? l1.val : 0; int y = (l2 != null) ? l2.val : 0; int sum = x + y + carry; carry = sum / 10; curr.next = new ListNode(sum % 10); curr = curr.next; if (l1 != null) l1 = l1.next; if (l2 != null) l2 = l2.next; } if (carry > 0) { curr.next = new ListNode(carry); } return dummyHead.next; } }
三、面试经典 150 题-2
数组 / 字符串
3.1 题目
移除元素
给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。 不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。 元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。 说明: 为什么返回数值是整数,但输出的答案是数组呢? 请注意,输入数组是以「引用」方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。 你可以想象内部操作如下: // nums 是以“引用”方式传递的。也就是说,不对实参作任何拷贝 int len = removeElement(nums, val); // 在函数里修改输入数组对于调用者是可见的。 // 根据你的函数返回的长度, 它会打印出数组中 该长度范围内 的所有元素。 for (int i = 0; i < len; i++) { print(nums[i]); } 示例 1: 输入:nums = [3,2,2,3], val = 3 输出:2, nums = [2,2] 解释:函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。你不需要考虑数组中超出新长度后面的元素。例如,函数返回的新长度为 2 ,而 nums = [2,2,3,3] 或 nums = [2,2,0,0],也会被视作正确答案。 示例 2: 输入:nums = [0,1,2,2,3,0,4,2], val = 2 输出:5, nums = [0,1,4,0,3] 解释:函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。注意这五个元素可为任意顺序。你不需要考虑数组中超出新长度后面的元素。 提示: 0 <= nums.length <= 100 0 <= nums[i] <= 50 0 <= val <= 100
3.2 题解
这是一道非常经典的数组操作题目,可以采用双指针法来解决。
解题思路:
- 定义两个指针 i 和 j,初始时 i = 0,j = 0。
- 从头遍历数组,当 nums[j] 不等于 val 时,将 nums[j] 赋值给 nums[i],然后将 i 和 j 均加 1。
- 当 nums[j] 等于 val 时,仅将 j 加 1。
- 最后返回 i 的值,即为新数组的长度。
在 main 方法中,我们创建了一个示例数组 nums 和一个整数 val,并调用 removeElement 方法来移除数组中值等于 val 的元素。然后,我们分别输出了新数组的长度和内容。
public class Solution { public int removeElement(int[] nums, int val) { int i = 0; for (int j = 0; j < nums.length; j++) { if (nums[j] != val) { nums[i++] = nums[j]; } } return i; } public static void main(String[] args) { int[] nums = {3, 2, 2, 3}; int val = 3; Solution solution = new Solution(); int len = solution.removeElement(nums, val); System.out.println(len); for (int i = 0; i < len; i++) { System.out.print(nums[i] + " "); } } }
至此,挑战100天 AI In LeetCode Day01(2)完成,后续会持续调整;查阅过程中若遇到问题欢迎留言或私信交流。