Array
1月9日
27,26,80 🔸 删除元素 🔸 MID/EASY
双指针操作数组
189 🔸 旋转数组 🔸 EASY
- 三重reverse
- 递归旋转
- 多次转动
- 新建数组
41 🔸 第一个缺失正数 🔸 HARD
桶排序,把每个数字放在对应的位置上
299 🔸 猜数字游戏 🔸 MID
遍历数组,找到在正确位置的,把其他的存在新建的数组里,再次遍历数组
134 🔸 加油站 🔸 MID
如果remain不为负,则一定有一个位置出发能走完整圈,如果i处remain为负数则从i+1处开始
1月10日
274/275 🔸 H-index 🔸 MID
先sort,当citations[i]>=length-i的时候return len-i。其他情况return 0因为没有such index
217 🔸 存在重复元素 🔸 EASY
HashSet的元素不能重复,如果hashset add失败则出现重复元素
55 🔸 Jump Game 🔸 MID
贪心算法,一直记录最远位置看是否涵盖当前位置
121 🔸 买卖股票1 🔸 EASY
随时记录和替换min和profit
122 🔸 买卖股票2 🔸 EASY
贪心算法,找localmin和localMax
123 🔸 买卖股票3 🔸 HARD
只允许买卖两次,动态规划 每一个位置有四种情况,可以是
- 第一次卖
- 第一次买
- 第二次卖
- 第二次买
class Solution {
public int maxProfit(int[] prices) {
int buy1 = Integer.MIN_VALUE;
int buy2 = Integer.MIN_VALUE;
int sell1 = 0;
int sell2 = 0;
for(int price: prices){
buy1 = Math.max(buy1, -price);
sell1 = Math.max(sell1, buy1+price);
buy2 = Math.max(buy2, sell1-price);
sell2 = Math.max(sell2, buy2+price);
}
return sell2;
}
}
11 🔸 乘最多的水 🔸 MID
双指针,一起向中间靠近,取代短的一边
1月12日
42 🔸 接雨水 🔸 HARD
双指针,每一个元素如果大于peak则取代peak,如果小于peak则水量增加
public int trap(int[] height) {
if(height==null || height.length<3) return 0;
int left = 0;
int right = height.length-1;
int res = 0;
int peakLeft = height[0];
int peakRight = height[height.length - 1];
while(left<=right){
if(peakLeft<=peakRight){
if(height[left] > peakLeft){
peakLeft = height[left];
left++;
}else{
res+= peakLeft - height[left];
left++;
}
}else{
if(height[right] > peakRight){
peakRight = height[right];
right--;
}else{
res+= peakRight - height[right];
right--;
}
}
}
return res;
}
334 🔸 递增三元子序列 🔸 MID
动态规划,记录下min1和min2,不停替换,如果大于min2则返回true
1月14日
128 🔸 最长连续序列 🔸 HARD
利用HashSet的contains和add方法为O(1)的特性
public int longestConsecutive(int[] nums) {
if(nums.length<2 || nums==null) return nums.length;
int res = 0;
int cur = 0;
HashSet<Integer> set = new HashSet<>();
for(int num: nums){
set.add(num);
}
for(int i=0; i<nums.length; i++){
int low = nums[i] - 1;
if(!set.contains(low)){
int temp = nums[i];
while(set.contains(temp)){
cur++;
temp++;
}
res = Math.max(res,cur);
cur = 0;
}
}
return res;
}
4 🔸 寻找两个有序数组的中位数 🔸 HARD
两个指针分别指向两个array的开头,每次较小的前进一位
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
int len = nums1.length+nums2.length;
int count = 1;
int odd = 0;
int index1 = 0;
int index2 = 0;
if(len%2!=0){
odd = 1;
}
if(odd==1){//when length is odd
int res = 0;
while(count<=(len/2+1)){
if(index1>=nums1.length){
res = nums2[index2];
index2++;
count++;
}else if(index2>=nums2.length){
res = nums1[index1];
index1++;
count++;
}else{
if(nums1[index1]>=nums2[index2]){
res = nums2[index2];
index2++;
count++;
}else{
res = nums1[index1];
index1++;
count++;
}
}
}
return res;
}else{
int res1 = 0;
int res2 = 0;
while(count<=(len/2+1)){
if(index1>=nums1.length){
res2 = res1;
res1 = nums2[index2];
index2++;
count++;
}else if(index2>=nums2.length){
res2 = res1;
res1 = nums1[index1];
index1++;
count++;
}else{
if(nums1[index1]>=nums2[index2]){
res2 = res1;
res1 = nums2[index2];
index2++;
count++;
}else{
res2 = res1;
res1 = nums1[index1];
index1++;
count++;
}
}
}
double res = (double)(res1+res2)/2;
return res;
}
}
53 🔸 最大子序和 🔸 EASY
Math.max(beforeSum+currentElement,currentElement);
209 🔸 长度最小的子数组 🔸 MID
滑窗算法,双指针一个控制窗子左边一个控制窗子右边
238 🔸 除自身以外数组的乘积 MID
用两个array储存从前往后的到i的乘积和从i开始的乘积 i的值等于到i-1的乘积乘上从i+1开始的乘积
1月15日
152 🔸 乘积最大子序列 🔸 MID
和最大子序和的原理相似,但是要考虑到乘积有正负,所以要有beforeMax和beforeMin
228 🔸 Summary Range 🔸 MID ♍️
双指针,遇到不连续的就add进res然后重置指针
88 🔸 Merge Sorted Array 🔸 EASY
- 两个指针分别指向两个array开头然后每次把较小的传入新array,再赋值回来♍️
- 由于nums1[]的space足够大,可以从后往前赋值,这样的space comlexity 是O(1)
75 🔸 Sort Colors 🔸 MID
- Arrays.sort()
- 双指针,while循环(于桶排序找first missing positive类似)
283 🔸 移动零 🔸 EASY♍️
类似桶排序思想,遇到非零的数就与current ptr换位置
1月16日
239 🔸 滑动窗口最大值 🔸 HARD ♍️
left和right指针代表窗户两端,currMax代表当前窗内最大值,如果滑动后移除的是最大值则重新搜索新窗,如果不是最大值,则currMax = Math.max(nums[left-1],nums[right])
1月17日
376 🔸 摆动序列 🔸 MID
如果当前值大于前一项的值且前一项为valley则当前项为新peak,反之亦然
class Solution {
public int wiggleMaxLength(int[] nums) {
if(nums.length<2) return nums.length;
int count = 1;
Boolean peak = null;
for(int i=1; i<nums.length; i++){
if(nums[i]>nums[i-1] && (peak==null || peak==false)){
peak = true;
count++;
}else if(nums[i]<nums[i-1] && (peak==null || peak==true)){
peak = false;
count++;
}
}
return count;
}
}
45 🔸 跳跃游戏2 🔸 HARD
-
- 动态规划->建立新数组,for i,更新i能到达的每一位的minimum jump,效率低 ♍️
-
- 更好的办法?
118 杨辉三角 EASY
给定一个非负整数 numRows,生成杨辉三角的前 numRows 行。
输入: 5
输出:
[
[1],
[1,1],
[1,2,1],
[1,3,3,1],
[1,4,6,4,1]
]
重点:通过储存前一列来省去两个get() function提升效率
class Solution {
public List<List<Integer>> generate(int numRows) {
List<List<Integer>> list = new ArrayList<List<Integer>>();
if(numRows == 0) return list;
List<Integer> pre = new ArrayList<>();
pre.add(1);
list.add(pre);
for(int i=1; i<numRows; i++){
List<Integer> line = new ArrayList<>();
line.add(1);
for(int j=1;j<i;j++){
line.add(pre.get(j-1) + pre.get(j));
}
line.add(1);
pre = line;
list.add(line);
}
return list;
}
}