Leetcode训练数据结构入门——数组全刷
Posted 胡毛毛_三月
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Leetcode训练数据结构入门——数组全刷相关的知识,希望对你有一定的参考价值。
目录
- [217. 存在重复元素](https://leetcode-cn.com/problems/contains-duplicate/)——简单
- [53. 最大子数组和](https://leetcode-cn.com/problems/maximum-subarray/)——简单
- [1. 两数之和](https://leetcode-cn.com/problems/two-sum/)——简单
- [88. 合并两个有序数组](https://leetcode-cn.com/problems/merge-sorted-array/)——简单
- [350. 两个数组的交集 II](https://leetcode-cn.com/problems/intersection-of-two-arrays-ii/)——简单
- [121. 买卖股票的最佳时机](https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock/)——简单
- [566. 重塑矩阵](https://leetcode-cn.com/problems/reshape-the-matrix/)——简单
- [118. 杨辉三角](https://leetcode-cn.com/problems/pascals-triangle/)——简单
217. 存在重复元素——简单
题目描述:
题解:
方法一:排序
class Solution
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;
复杂度分析
- 时间复杂度:O(NlogN),其中 N 为数组的长度。需要对数组进行排序。
- 空间复杂度:O(logN),其中 N 为数组的长度。注意我们在这里应当考虑递归调用栈的深度。
方法二:哈希表
java Set自带去重,如果去重后的长度小于原长度,则返回true
class Solution
public boolean containsDuplicate(int[] nums)
Set<Integer> arr = new HashSet<Integer>();
for(int i : nums)
arr.add(i);
return arr.size()<nums.length?true:false;
复杂度分析
- 时间复杂度:O(N),其中 N 为数组的长度。
- 空间复杂度:O(N),其中 N 为数组的长度。
53. 最大子数组和——简单
题目描述
题解
方法一:动态规划
class Solution
public int maxSubArray(int[] nums)
int a = 0;
int max = nums[0];
for (int i : nums)
a = Math.max(a+i, i);
max = Math.max(a, max);
return max;
复杂度分析
- 时间复杂度:O(n),其中 n 为 nums 数组的长度。我们只需要遍历一遍数组即可求得答案。
- 空间复杂度:O(1)。我们只需要常数空间存放若干变量。
方法二:动态规划
复杂度分析
- 时间复杂度:O(n),其中 n 为 nums 数组的长度。我们只需要遍历一遍数组即可求得答案。
- 空间复杂度:O(1)。我们只需要常数空间存放若干变量。
1. 两数之和——简单
题目描述
题解
方法一:暴力枚举
class Solution
public int[] twoSum(int[] nums, int target)
int n = nums.length;
for (int i = 0; i < n; ++i)
for (int j = i + 1; j < n; ++j)
if (nums[i] + nums[j] == target)
return new int[]i, j;
return new int[0];
复杂度分析
方法二:查找表法(哈希表)
class Solution
public int[] twoSum(int[] nums, int target)
HashMap<Integer, Integer> hash = new HashMap<>();
int arr[] = new int [2];
for (int i = 0; i < nums.length; i++)
if (hash.containsKey(target-nums[i]))
// return new int[] hash.get(target-nums[i]),i;
arr[0] = hash.get(target-nums[i]);
arr[1] = i;
hash.put(nums[i], i);
return arr;
复杂度分析
88. 合并两个有序数组——简单
题目描述
题解
方法一:直接合并后排序
class Solution
public void merge(int[] nums1, int m, int[] nums2, int n)
for (int i = 0; i < n; i++)
nums1[m] = nums2[i];
m++;
Arrays.sort(nums1);
复杂度分析
方法二:双指针
class Solution
public void merge(int[] nums1, int m, int[] nums2, int n)
int p1 = 0, p2 = 0;
int[] sorted = new int[m + n];
int cur;
while (p1 < m || p2 < n)
if (p1 == m)
cur = nums2[p2++];
else if (p2 == n)
cur = nums1[p1++];
else if (nums1[p1] < nums2[p2])
cur = nums1[p1++];
else
cur = nums2[p2++];
sorted[p1 + p2 - 1] = cur;
for (int i = 0; i != m + n; ++i)
nums1[i] = sorted[i];
复杂度分析
方法三:
class Solution
public void merge(int[] nums1, int m, int[] nums2, int n)
int nums1copy[] = new int[m];
System.arraycopy(nums1, 0, nums1copy, 0, m);
int p = 0; // nums1指针
int p1 = 0; // nums1copy 指针
int p2 = 0; // nums2 指针
while ((p1<m) && (p2<n))
if (nums1copy[p1]<nums2[p2])
nums1[p] = nums1copy[p1];
p++;
p1++;
else
nums1[p] = nums2[p2];
p++;
p2++;
if (p1<m)
System.arraycopy(nums1copy, p1, nums1, p1+p2,m+n-p1-p2);
if (p2<n)
System.arraycopy(nums2, p2, nums1, p1+p2, m+n-p1-p2);
复杂度分析
方法三:// 逆向双指针
class Solution
public void merge(int[] nums1, int m, int[] nums2, int n)
int p1 = m-1;
int p2 = n-1;
int p = m+n-1;
while (p1>=0&&p2>=0)
if (nums1[p1]<nums2[p2])
nums1[p] = nums2[p2];
p--;
p2--;
else
nums1[p] = nums1[p1];
p--;
p1--;
System.arraycopy(nums2, 0, nums1, 0, p2+1); // 当nums1 为空的时候直接执行此方法
复杂度分析
350. 两个数组的交集 II——简单
题目描述
题解
方法一:使用List集合
class Solution
/**
* 使用集合实现
*/
public int[] intersect(int[] nums1, int[] nums2)
List<Integer> list1 = new ArrayList<>();
for (int i : nums1)
list1.add(i);
List<Integer> list2 = new ArrayList<>();
for (int i : nums2)
if (list1.contains(i))
list2.add(i);
// 从list1 除去已匹配的数值
list1.remove(Integer.valueOf(i));
int arr[] = new int[list2.size()];
int j = 0;
for (int i : list2)
arr[j]=i;
j++;
return arr;
方法二:使用映射实现Map
/**
* 使用映射实现
*/
public int[] intersect_3(int[] nums1, int[] nums2)
Map<Integer, Integer> map = new HashMap<>(nums1.length);
// 将 nums1 出现的数值及频次放入映射中
for (int num : nums1)
Integer count = map.get(num);
if (count == null)
map.put(num, 1);
else
map.put(num, ++count);
List<Integer> list = new ArrayList<>();
for (int num : nums2)
// 获取映射中该数值出现的频次
Integer count = map.get(num);
if (count != null && count != 0)
list.add(num);
// 注意每次匹配后,该数值的频次需要减 1(nums1 和 nums2 匹配的数值的频次要相同)
map.put(num, --count);
int[] res = new int[list.size()];
for (int i = 0; i < list.size(); i++)
res[i] = list.get(i);
return res;
方法三:排序预处理(我)
class Solution
public int[] intersect(int[] nums1, int[] nums2)
List<Integer> list = new ArrayList<>();
Arrays.sort(nums1);
Arrays.sort(nums2);
for (int i = 0,j=0;i<nums1.length && j<nums2.length;)
if (nums1[i]>nums2[j])
j++;
else if (nums1[i]<nums2[j])
i++;
else
list.add(nums1[i]);
i++;
j++;
int arr[] = new int[list.size()];
int num = 0;
for (int i : list)
arr[num] = i;
num ++;
return arr;
复杂度分析
121. 买卖股票的最佳时机——简单
题目描述
题解
方法一:Dp min、max
思路还是挺清晰的,还是DP思想:
-
记录【今天之前买入的最小值】
-
计算【今天之前最小值买入,今天卖出的获利】,也即【今天卖出的最大获利】
-
比较【每天的最大获利】,取最大值即可
class Solution
public int maxProfit(int[] prices)
if(prices.length <= 1)
return 0;
int min=prices[0];
int max = 0;
for (int i = 0; i < prices.length; i++)
max = Math.max(max,prices[i]-min)Leetcode训练算法入门——双指针全刷
Leetcode训练剑指 Offer(专项突击)——双指针全刷