力扣第59场双周赛与第255场周赛总结解析


力扣第59场双周赛与第255场周赛总结解析

date: 2021-08-22 15:19:02

tags: [dfs,数学,图,竞赛,总结]
categories: 算法

个人博客题解地址
image-20210822152345135

经过昨晚的双周赛以及今日午时的周赛,继续感到自己的实力薄弱。双周赛一题,周赛两题。什么时候我也能来个AC呢?不说了,直接开始总结分析吧。

(吐槽一下力扣官方的网络运维,怎么最近一直被攻击,包括我写这篇题解的时候,网页都打不开了……)

力扣双周赛

image-20210822152834993

  • 使用特殊打字机键入单词的最少时间

image-20210822153301919

这道题利用简单的数学知识即可进行解题,我们将“键入”与“指向”用时分开计算,“键入”用时即为给出字符串的长度。对于“指向”用时,这里涉及了一个贪心策略,即:我们每次都要取得最小的移动路径。我们的“指针”从 a 开始,只可能顺时针逆时针进行移动,而我们需要在这两种选择中获得最小值,最后加上最初的“键入”值,便可以得到答案。


class Solution {
    public int minTimeToType(String word) {
    //shuzi为“键入值”
    int shuzi = word.length();
    //index为“指针”
    int index = 1;
    int answer = 0;
        for(int i = 0;i < word.length();i++){
            char s = word.charAt(i);
            int num = (int)(s-'a')+1;
            answer = answer + findMin(index,num);
            index = num;
        }
        return answer+shuzi;
    }
    //分开讨论,findMin函数用于寻找最短移动路径
    public int findMin(int begin,int end){
        //对指针和目标位置的不同情况进行不同处理。
        if(begin > end){
            return Math.min(begin-end,26-begin+end);
        }
        else{
            return Math.min(end-begin,26-end+begin);
        }
    }
}
//如果对自己写的东西不能很好的清晰理解,建议分成多个模块。笔者在对移动路径分析时,踩了坑。
  • 最大方阵和

image-20210822162011023

这一题笔者在比赛过程中并未进行解答。在后期也没有想出个所以然,但是在查看题解时恍然大悟。

  • 偶数个负数是可以全部清除的。
  • 奇数个负数将最小的减去即可。

那么这题很容易解答(前提是你的思路正确)

class Solution {
    public long maxMatrixSum(int[][] matrix) {

        long res = 0;
        int neg = 0, min = Integer.MAX_VALUE;

        for(int i = 0; i < matrix.length; i++){
            for(int j = 0; j < matrix[0].length; j++){
                if(matrix[i][j] < 0) neg++;
                min = Math.min(min, Math.abs(matrix[i][j]));
                res += Math.abs(matrix[i][j]);
            }
        }

        return (neg & 1) == 0 ? res : res - min * 2;
    }
}
  • 到达目的地的方案数

image-20210822162618116

这一题很容易可以看出使用Floyd或者Dijkstra算法进行求解,可惜笔者忘记了这两种解法。

//Dijkstra
class Solution {
     public int countPaths(int n,int[][] times) {
        final int INF = Integer.MAX_VALUE;
        List<int[]>[] g = new List[n];
        for (int i = 0; i < n; ++i) {
            g[i] = new ArrayList<int[]>();
        }
        for (int[] t : times) {
            int x = t[0] , y = t[1];
            g[x].add(new int[]{y, t[2]});
            g[y].add(new int[]{x, t[2]});
        }
        int mod=1000000007;
        int[][] dist = new int[n][2];
        for (int i = 0; i < n; i++) {
            dist[i][0] = INF;
        }
        
        dist[0][0] = 0;
        dist[0][1] = 1;

        int ans = 0;
        PriorityQueue<int[]> pq = new PriorityQueue<int[]>((a, b) -> a[0] != b[0] ? a[0] - b[0] : a[1] - b[1]);
        pq.offer(new int[]{0, 0});
        while (!pq.isEmpty()) {
            int[] p = pq.poll();
            int time = p[0], x = p[1];
            if (dist[x][0] < time) {
                continue;
            }
            for (int[] e : g[x]) {
                int y = e[0], d = dist[x][0] + e[1];
                if (d == dist[y][0]) {
                    dist[y][1]+=dist[x][1];
                    dist[y][1]%=mod;
                }
                if (d < dist[y][0]) {
                    dist[y][0] = d;
                    pq.offer(new int[]{d, y});
                    dist[y][1]=dist[x][1];
                    
                }

            }
        }
        return  dist[n-1][1];
    }
}

笔者实力有限,最后一题不做题解。

力扣周赛

image-20210822163144458

  • 找出数组的最大公约数

image-20210822163232148

这一题只需记录一个数组中的最大及最小值,随后对其使用辗转相除法即可求解。


class Solution {
    public int findGCD(int[] nums) {
        int min = nums[0];
        int max = nums[0];
        for(int i = 1;i < nums.length;i++){
            if(nums[i] > max) max = nums[i];
            if(nums[i] < min) min = nums[i];
        }
        int answer = max % min;
        while(answer != 0){
            max = min;
            min = answer;
            answer = max % min;
        }
        return min;
    }
}
  • 找出不同进制的二进制字符

image-20210822163532680

相应的,这题我们可以分为两部分来做。

(哈希+递归)

  • 得到二进制字符。

    利用递归得到不同的二进制字符。

  • 与已有的二进制字符进行比较。

    利用链表的contains()方法。

当出现与已有二进制字符不同的二进制字符时,利用flag标志,停止递归,返回相应得二进制字符。

class Solution {
    String cmp = "";
    String answer = "";
    int flag = 0;
    public String findDifferentBinaryString(String[] nums) {
        int n = nums.length;
        List<String> data= new ArrayList<String>();
        for(int i = 0;i < n;i++){
            data.add(nums[i]);
        }
        dfs(0,n,data);
        return answer;
    }
    public void dfs(int index,int des,List<String> data){
        if(flag == 1) return;
        if(index == des){
            if(!(data.contains(cmp))){
            answer = cmp;
            flag = 1;
            }
            return;
        }
        for(int i = 0;i < 2;i++){
            cmp = cmp + i;
            dfs(index+1,des,data);
            cmp = cmp.substring(0,cmp.length()-1);
        }
    }
}

笔者代码写的不够简洁,清晰,仅供参考。

笔者实力有限,最后两题不做解答


总结

从两场可以看出,笔者对数据结构及算法的知识有相应的了解,但在解决具体问题和熟练度上均有待提高。

尤其对于图相关的四种算法应加强相关练习。


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值