LeetCode刷题笔记1——数组
LeetCode刷题笔记1——数组
存在重复元素
题目
给定一个整数数组,判断是否存在重复元素。
如果存在一值在数组中出现至少两次,函数返回
true
。如果数组中每个元素都不相同,则返回false
。
示例
示例 1:
输入: [1,2,3,1]
输出: true示例 2:
输入: [1,2,3,4]
输出: false示例 3:
输入: [1,1,1,3,3,4,3,2,4,2]
输出: true
代码
public class ContainsDuplicate {
public boolean containsDuplicate(int[] nums) {
Arrays.sort(nums);//解题关键点
for(int i = 0;i<nums.length-1;i++) {
if(nums[i]==nums[i+1]) {
return true;
}
}
return false;
}
}
🏷️ 关键点还是排序
最大字数组和
题目
给你一个整数数组
nums
,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。子数组 是数组中的一个连续部分。
示例
示例 1:
输入:nums = [-2,1,-3,4,-1,2,1,-5,4]
输出:6
解释:连续子数组 [4,-1,2,1] 的和最大,为 6 。示例 2:
输入:nums = [1]
输出:1示例 3:
输入:nums = [5,4,-1,7,8]
输出:23提示:
1 <= nums.length <= 10^5
-10^4 <= nums[i] <= 10^4
代码
class Solution {
public int maxSubArray(int[] nums) {
int sum = -10000, temp = 0;
for (int i = 0; i < nums.length; i++) {
if (temp > 0)
temp += nums[i];//大于0就加上去
else
temp = nums[i];//否则重新开始
if (temp > sum)
sum = temp;
}
return sum;
}//动态规划问题
}
🏷️ 关键是动态规划
两数之和
题目
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
示例
示例 1:
输入:nums = [2,7,11,15], target = 9
输出:[0,1]解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
示例 2:
输入:nums = [3,2,4], target = 6
输出:[1,2]示例 3:
输入:nums = [3,3], target = 6
输出:[0,1]提示:
2 <= nums.length <= 104
-109 <= nums[i] <= 109
-109 <= target <= 109
只会存在一个有效答案
暴力求解
class Solution {
public int[] twoSum(int[] nums, int target) {
int[] result = new int[2];
for (int i = 0; i < nums.length; i++) {
for (int j = i + 1; j < nums.length; j++) {
if (nums[i] + nums[j] == target) {
result[0] = i;
result[1] = j;
return result;
}
}
}
return result;
}
}
使用hashMap
class Solution {
public int[] twoSum(int[] nums, int target) {
Map<Integer, Integer> hashtable = new HashMap<Integer, Integer>();
for (int i = 0; i < nums.length; ++i) {
if (hashtable.containsKey(target - nums[i])) {
return new int[]{hashtable.get(target - nums[i]), i};
}
hashtable.put(nums[i], i);//key:num[i] value:i
}
return new int[0];
}
}
使用哈希表,可以将寻找 target - x 的时间复杂度降低到从 O(N) 降低到O(1)。
这样我们创建一个哈希表,对于每一个 x,我们首先查询哈希表中是否存在 target - x,然后将 x 插入到哈希表中,即可保证不会让 x 和自己匹配。
合并两个有序数组
题目
给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。
请你 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。
注意:最终,合并后数组不应由函数返回,而是存储在数组 nums1 中。为了应对这种情况,nums1 的初始长度为 m + n,其中前 m 个元素表示应合并的元素,后 n 个元素为 0 ,应忽略。nums2 的长度为 n 。
示例
示例 1:
输入:nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3
输出:[1,2,2,3,5,6]
解释:需要合并 [1,2,3] 和 [2,5,6] 。
合并结果是 [1,2,2,3,5,6] ,其中斜体加粗标注的为 nums1 中的元素。示例 2:
输入:nums1 = [1], m = 1, nums2 = [], n = 0
输出:[1]
解释:需要合并 [1] 和 [] 。
合并结果是 [1] 。示例 3:
输入:nums1 = [0], m = 0, nums2 = [1], n = 1
输出:[1]
解释:需要合并的数组是 [] 和 [1] 。
合并结果是 [1] 。注意,因为 m = 0 ,所以 nums1 中没有元素。nums1 中仅存的 0 仅仅是为了确保合并结果可以顺利存放到 nums1 中。
提示:
nums1.length == m + n
nums2.length == n
0 <= m, n <= 200
1 <= m + n <= 200
-10^9 <= nums1[i], nums2[j] <= 10^9
直接合并后排序
class Solution {
public void merge(int[] nums1, int m, int[] nums2, int n) {
for (int i = m; i < m+n; i++) {
nums1[i]=nums2[i-m];
}
Arrays.sort(nums1);
}
}
时间复杂度:O((m+n)log(m+n))
排序序列长度为 m+nm+n,套用快速排序的时间复杂度即可,平均情况为 O((m+n)log(m+n))。空间复杂度:O(log(m+n))。
排序序列长度为 m+nm+n,套用快速排序的空间复杂度即可,平均情况为 O(log(m+n))。
双指针法
使用双指针方法。这一方法将两个数组看作队列,每次从两个数组头部取出比较小的数字放到结果中。如下面的动画所示:
class Solution {
public static void merge(int[] nums1, int m, int[] nums2, int n) {
int p1 = 0, p2 = 0;// 双指针
int[] temp = new int[m + n];
int element;
while (p1 < m || p2 < n) {
if (p1 == m) {
element = nums2[p2++];
// 第一个数组已经全部放入
} else if (p2 == n) {
element = nums1[p1++];
// 第二个数组已经全部放入
} else if (nums1[p1] < nums2[p2]) {
element = nums1[p1++];
} else {
element = nums2[p2++];
} // 选取较小的放入temp
temp[p1 + p2 - 1] = element;
}
for (int i = 0; i < m + n; i++) {
nums1[i] = temp[i];
}
}
}
两个数组的交集
题目
给定两个数组 nums1 和 nums2 ,返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。
示例
示例 1:
输入:nums1 = [1,2,2,1], nums2 = [2,2]
输出:[2]示例 2:
输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出:[9,4]
解释:[4,9] 也是可通过的提示:
1 <= nums1.length, nums2.length <= 1000
0 <= nums1[i], nums2[i] <= 1000
使用Set
class Solution {
public int[] intersection(int[] nums1, int[] nums2) {
Set<Integer> set1 = new HashSet<>();
Set<Integer> set2 = new HashSet<>();
for (int i : nums1)
set1.add(i);//将nums1中的元素放入集合set1
for (int i : nums2) {
if (set1.contains(i)) {
set2.add(i);
}//将重复的元素放入set2
}
int[] result = new int[set2.size()];
int j = 0;
for (int i : set2) {
result[j++] = i;
}
return result;
}
}
两个数组的交集Ⅱ
题目
给你两个整数数组 nums1 和 nums2 ,请你以数组形式返回两数组的交集。返回结果中每个元素出现的次数,应与元素在两个数组中都出现的次数一致(如果出现次数不一致,则考虑取较小值)。可以不考虑输出结果的顺序。
示例
示例 1:
输入:nums1 = [1,2,2,1], nums2 = [2,2]
输出:[2,2]
示例 2:输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出:[4,9]提示:
1 <= nums1.length, nums2.length <= 1000
0 <= nums1[i], nums2[i] <= 1000
利用Hash表
class Solution {
public int[] intersect(int[] nums1, int[] nums2) {
if (nums1.length > nums2.length) {
return intersect(nums2, nums1);
} // 从较短的数组开始遍历,以减少空间复杂度
Map<Integer, Integer> record = new HashMap<>();
for (int i : nums1) {
int count = record.getOrDefault(i, 0) + 1;
// getOrDefault: 寻找i的value值,若不存在则返回0
record.put(i, count);
}
int[] result = new int[nums1.length];
int index = 0;
for (int i : nums2) {
int count2 = record.getOrDefault(i, 0);
if (count2 > 0) {
result[index++] = i;
count2--;
if(count2>0){
record.put(i, count2);
}else{
record.remove(i);
}
}
}
return Arrays.copyOfRange(result, 0, index);//复制数组
}
}
首先遍历第一个数组,并在哈希表中记录第一个数组中的每个数字以及对应出现的次数,然后遍历第二个数组,对于第二个数组中的每个数字,如果在哈希表中存在这个数字,则将该数字添加到答案,并减少哈希表中该数字出现的次数。
题目来源
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/contains-duplicate/
链接:https://leetcode-cn.com/problems/maximum-subarray/
链接:https://leetcode-cn.com/problems/two-sum
链接:https://leetcode-cn.com/problems/merge-sorted-array
链接:https://leetcode-cn.com/problems/intersection-of-two-arrays/
链接:https://leetcode-cn.com/problems/intersection-of-two-arrays-ii/
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)