挑战100天 AI In LeetCode Day01(2)
- 一、LeetCode介绍
- 二、LeetCode 热题 HOT 100-2
- 2.1 题目
- 2.2 题解
- 三、面试经典 150 题-2
- 3.1 题目
- 3.2 题解
一、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)完成,后续会持续调整;查阅过程中若遇到问题欢迎留言或私信交流。