Leetcode Array刷题笔记

475 阅读5分钟

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

    1. 动态规划->建立新数组,for i,更新i能到达的每一位的minimum jump,效率低 ♍️
    1. 更好的办法?

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;
    }
}