LeetCode周赛学习笔记(未完成)

上周的LeetCode周赛#196学习记录:


使用语言:Java
初次体验线上编程比赛,通过完成情况定位了自己的水平欠缺,于此记录学习理解过程,自我整理提升。


第一题:判断能否形成等差数列

难度 - easy

1. 题目

传送:1502. 判断能否形成等差数列

给你一个数字数组 arr
如果一个数列中,任意相邻两项的差总等于同一个常数,那么这个数列就称为 等差数列
如果可以重新排列数组形成等差数列,请返回 true ;否则,返回 false
提示:
2 <= arr.length <= 1000
-10^6 <= arr[i] <= 10^6

示例 1:
输入:arr = [3,5,1]
输出:true
解释:对数组重新排序得到 [1,3,5] 或者 [5,3,1] ,任意相邻两项的差分别为 2 或 -2 ,可以形成等差数列。

2. 个人思路

排序 → 头两个元素相减值保存 → 检查后续元素两两相减值是否同保存值
可能是第一次参加有些紧张又混乱,不相信自己,又去搜了搜…T.T
最后参考了别人TreeSet去重的思路,代码如下:

class Solution {
    public boolean canMakeArithmeticProgression(int[] arr) {
        int gap=0;
        Arrays.sort(arr);
        TreeSet<Integer> arrayTreeSet = new TreeSet<Integer>();
        for(int i=0;i<arr.length-1;i++){
            gap=arr[i+1]-arr[i];
            arrayTreeSet.add(gap);
        }
        if(arrayTreeSet.size()==1)
            return true;
        else
            return false;
    }
}
运行时间内存消耗
4 ms39.5 MB
3. 前排解答

(事实证明我把事情搞复杂了orz

来自LeetCode:tian-tang-6

public boolean canMakeArithmeticProgression(int[] arr) {
        Arrays.sort(arr);
        int delta = arr[1] - arr[0];
        for(int i = 1; i < arr.length; i++){
            if(arr[i] - arr[i - 1] != delta){
                return false;
            }
        }
        return true;
运行时间内存消耗
3 ms39.5 MB
4.本题总结

大致看了下前二三十名的解答,基本都是这样直接明了的思路。
so,本题收获:

  1. 平常心,不要没事怀疑自己,直觉出来的结果没错的话就不要犹豫
  2. 别把事情搞复杂- -

第二题:所有蚂蚁掉下来前的最后一刻

难度 - middle

1. 题目

传送:1503. 所有蚂蚁掉下来前的最后一刻

有一块木板,长度为 n 个 单位 。一些蚂蚁在木板上移动,每只蚂蚁都以 每秒一个单位 的速度移动。其中,一部分蚂蚁向 移动,其他蚂蚁向 移动。
当两只向 不同 方向移动的蚂蚁在某个点相遇时,它们会同时改变移动方向并继续移动。假设更改方向不会花费任何额外时间。
而当蚂蚁在某一时刻 t 到达木板的一端时,它立即从木板上掉下来。
给你一个整数 n 和两个整数数组 left 以及 right 。两个数组分别标识向左或者向右移动的蚂蚁在 t = 0 时的位置。请你返回最后一只蚂蚁从木板上掉下来的时刻。

在这里插入图片描述

示例1:(上图)
输入:n = 4, left = [4,3], right = [0,1]
输出:4
解释:如上图所示:
-下标 0 处的蚂蚁命名为 A 并向右移动。
-下标 1 处的蚂蚁命名为 B 并向右移动。
-下标 3 处的蚂蚁命名为 C 并向左移动。
-下标 4 处的蚂蚁命名为 D 并向左移动。
请注意,蚂蚁在木板上的最后时刻是 t = 4 秒,之后蚂蚁立即从木板上掉下来。(也就是说在 t = 4.0000000001 时,木板上没有蚂蚁)。

2. 个人思路

当时:看起来好复杂,我晕,先看别的

3. 前排解答

来自LeetCode:tian-tang-6

public int getLastMoment(int n, int[] left, int[] right) {
    int ans = 0;
    for(int x : right){
        ans = Math.max(ans, n - x);
    }
    for(int x : left){
        ans = Math.max(ans, x);
    }
    return ans;
}
运行时间内存消耗
1 ms40.2 MB

看到的时候愣住,想不明白为什么直接选出距目标朝向的边缘最远的哪一个就行,还画图模拟了全过程想要弄明白。

草稿
实际上这张图画完了以后本来应当能够看出来了,奈何我当时思维太僵硬了,也没有发现这当中一致的“阶梯形”。直到看到一句留言,瞬间被点醒。

网友留言

可以理解为 接力,无需管某一只蚂蚁的具体路径,离目标方向的边缘最远的那只蚂蚁决定了接力的最长距离,它与目标边缘之间有其他蚂蚁则为接力形式,没有则他独自完成。

  • 7.8补充: 还有一种说法,可以用 “穿透” 来理解,每只蚂蚁并没有区别,不将他们理解为相遇转向,而是穿透或是擦肩而过,也较为容易理解,直接取路程最大值。
4.本题总结

所以本题更加重要的是思路,理解业务本质。
(相比之下我觉得是没有什么算法方面的考核…有一点点脑筋急转弯的意味)

本题收获:跳出固定思维模式,业务过程看起来很复杂的时候不要着急照着原样实现,研究能否提炼中心简化算法内容。


第三题:统计全 1 子矩形

难度 - middle

1.题目

传送:1504. 统计全 1 子矩形

给你一个只包含 0 和 1 的 rows * columns 矩阵 mat ,请你返回有多少个 子矩形 的元素全部都是 1 。

示例 1:
输入:mat = [[1,0,1],
[1,1,0],
[1,1,0]]
输出:13
解释:
有 6 个 1x1 的矩形。
有 2 个 1x2 的矩形。
有 3 个 2x1 的矩形。
有 1 个 2x2 的矩形。
有 1 个 3x1 的矩形。
矩形数目总共 = 6 + 2 + 3 + 1 + 1 = 13 。

2. 个人思路

当时: 好像隐约有思路但是感觉被卡住了

  • 补课线代
3. 前排解答

来自LeetCode: huangyuyang

class Solution {
//****该原答案使用的是C++语言****
//为保证能在java条件下运行
//注释掉部分源码并进行修改

//public:
//    int numSubmat(vector<vector<int>>& a) {
	public int numSubmat(int[][] mat) {
//        int n = a.size(), m = a[0].size();
		int n = mat.length;
		int m = mat[0].length;
//        vector <vector <int> > s = a;
		int[][] s = mat;
        for (int i = 0; i < n; i++) {
            for (int j = 1; j < m; j++) {
                s[i][j] += s[i][j - 1];
            }
        }
        int ans = 0;
        for (int l = 0; l < m; l++) {
            for (int r = l; r < m; r++) {
                int now = 0;
                for (int i = 0; i < n; i++) {
                    int ss = s[i][r];
                    if (l > 0) {
                        ss -= s[i][l - 1];
                    }
                    if (ss == (r - l + 1)) {
                        now++;
                    } else {
                        ans += (now * (now + 1) / 2);
                        now = 0;
                    }
                }
                if (now > 0) {
                    ans += (now * (now + 1) / 2);
                }       
            }
        }
        return ans;
    }
}
运行时间内存消耗
30 ms40.7 MB

【待】

4.本题总结

【待】


第四题:最多 K 次交换相邻数位后得到的最小整数

难度 - hard

1.题目

传送:1505. 最多 K 次交换相邻数位后得到的最小整数

给你一个字符串 num 和一个整数 k 。其中,num 表示一个很大的整数,字符串中的每个字符依次对应整数上的各个 数位
你可以交换这个整数相邻数位的数字 最多 k 次。
请你返回你能得到的最小整数,并以字符串形式返回。

示例 1:
示例
输入:num = “4321”, k = 4
输出:“1342”
解释:4321 通过 4 次交换相邻数位得到最小整数的步骤如上图所示。

2. 个人思路

【待】

3. 前排解答

来自LeetCode:java14

class Solution {
    void sw(char cs[],int i,int j){
        char t = cs[i];
        cs[i] =cs[j];
        cs[j] = t;
    }
        
    public String minInteger(String num, int k) {
        char cs[] = num.toCharArray();
        int l = cs.length;
        for(int i=0;i<l&&k>0;++i){
            int cur = i;
            for(int j=i+1;j<l&&j-i<=k;++j){
                if(cs[j]<cs[cur]){
                    cur = j;
                }
            }
            for(int j=cur;j>i&&k>0;--j){
                k--;
                sw(cs, j, j-1);
            }   
        }
        return new String(cs);  
    }
}
运行时间内存消耗
2182 ms40.1 MB

【待】

4.本题总结

【待】


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值