LeetCode周赛200

1. 统计三元组

按照题意写就行

class Solution {
    
    
    // 题意:i和j的差距小于a,j和k的差距小于b,i和k的差距小于c
    public int countGoodTriplets(int[] arr, int a, int b, int c) {
    
    
        int res = 0;
        int length = arr.length;
        for (int i = 0; i < length - 2; i++) {
    
    
            for (int j = i+1; j < length - 1; j++) {
    
    
                for (int k = j+1; k < length; k++) {
    
    
                    if (Math.abs(arr[i] - arr[j]) <= a && Math.abs(arr[j] - arr[k]) <= b && Math.abs(arr[i] - arr[k]) <= c) {
    
    
                        res++;
                    }
                }
            }
        }
        return res;
    }
}

2.找游戏的赢家

// 比赛中提交的代码
class Solution {
    
    
    public int getWinner(int[] arr, int k) {
    
    
        int length = arr.length;
        // -----------------------------
        // 如果k大于(数组长度-1)也就是说最终的结果至少需要大于(数组长度-1)个不同的数。所以直接返回最大值。
        if(k>=length-1) {
    
    
            Arrays.sort(arr);
            return arr[length-1];
        }
        // --------------------------------
        // 按照题意不断向后遍历寻找,
        // cur为当前最大的值,count为当前最大值比过的次数。
        // 如果满足题意,直接返回即可
        int count = 0;
        int cur = arr[0];
        for(int i=1;i<arr.length;i++) {
    
    
            if(cur>arr[i]) {
    
    
                count++;
            } else {
    
    
                cur = arr[i];
                count = 1;
            }
            if(count==k) return cur;
        }
        // 如果没有在上述操作中返回,可知已经遍历完整个数组了。此时cur就是数组的最大值,
        // 接下来无论如何比较,cur是最大,cur的值不会改变,所以直接返回即可。
        return cur;
    }
}

// 实际上k>length-1并不需要单独讨论。

3. 二进制网格的最小交换次数

// 比赛中提交的代码
class Solution {
    
    
    private void swap(int[] arr, int i, int j) {
    
    
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }
    public int minSwaps(int[][] grid) {
    
    
        int n = grid.length;
        int[] arr = new int[n];
        // 获取每一行的从右到左连续的0的个数
        for (int i = 0; i < n; i++) {
    
    
            //
            int temp = 0;
            for (int j = n - 1; j > 0; j--) {
    
    
                if (grid[i][j] == 0) {
    
    
                    temp++;
                } else {
    
    
                    break;
                }
            }
            arr[i] = temp;
        }
        int index = 0;
        int res = 0;
        for (int i = n - 1; i > 0; i--) {
    
    
            if (arr[index] < i) {
    
    
                // 该行不满足条件,往后找满足条件的那一行
                for (int j = index + 1; j < n; j++) {
    
    
                    if (arr[j] >= i) {
    
    
                        res = res + (j - index);
                        for(int k=j;k>index;k--) {
    
    
                            swap(arr, k, k-1);
                        }
                        break;
                    }
                }
                if(arr[index]<i) return -1;
            }
            index++;
        }
//        // 判断最终是否会成功
//        Arrays.sort(arr);
//        for (int i = 0; i < arr.length; i++) {
    
    
//            if (arr[i] < i) return -1;
//        }
        return res;
    }
}

  • 本题思路:
    • 统计每一行,从右向左的连续为0的个数。保存到一个数组中
    • 模拟交换,使得该数组对应的矩阵满足题目条件,返回交换的次数。
    • 注意只能相邻两行交换,也就是数组的相邻两个数交换。比如1 2 3 4, 将4换到1,交换后结果为4 1 2 3
    • 发现不满足条件的数时,向后查找,发现查找数满足条件,即可将该数交换到不满足位置。因为遍历的顺序是从要求连续0的个数最大到最小,所以后面有更能满足的,也不需要考虑。并且这样能使交换次数最少。
      • 例如要求 第一位大于3,第二位大于2,第三位大于1,第四位大于0.
      • 对于1 0 3 4(只是对问题的抽象)3换到1即可,不用考虑4的问题。4放到条件更宽松的后面位置也不会对是否能成功产生影响。

4. 最大得分

  • 这题还是被大于10_0000_0007需要取余坑了,练的太少…在中间过程也不断取余,结果在最后比较之前取余了,导致结果错误,而且错误的版本数组太大也debug不了没发现错误。
    • Java中long的范围(-2的63次方)-(2的63次方-1)9223372036854775807:十九位
    • 这道题中1 <= nums1[i], nums2[i] <= 10^7
    • 这道题中1 <= nums1/2.length <= 10^5
    • 和最多也是12位,所以使用long是满足要求的。只需要在末尾取余即可。int的范围是(-2的31次方)-(2的31次方-1)2147483647十位显然不满足。
  • 模拟大佬C++的Java版本。
class Solution {
    
    
    public int maxSum(int[] nums1, int[] nums2) {
    
    
        int m = nums1.length;
        int n = nums2.length;
        long t1 = 0, t2 = 0;
        int i = 0, j = 0;
        while (i < m || j < n) {
    
    
            if (i < m && j < n) {
    
    
                if (nums1[i] < nums2[j]) {
    
    
                    t1 += nums1[i++];
                } else if (nums1[i] > nums2[j]) {
    
    
                    t2 += nums2[j++];
                } else {
    
    
                    long best = Math.max(t1, t2) + nums1[i];
                    t1 = t2 = best;
                    ++i;
                    ++j;
                }
            } else if (i < m) {
    
    
                t1 += nums1[i++];
            } else if (j < n) {
    
    
                t2 += nums2[j++];
            }
        }
        return (int) (Math.max(t1, t2) % 1000000007);
    }
}
  • 自己的最终代码修改正确后
class Solution {
    
    
    public static int maxSum(int[] nums1, int[] nums2) {
    
    
        Set<Integer> set = new HashSet<>();
        int index = 0;
        for (int i = 0; i < nums1.length; i++) {
    
    
            for (int j = index; j < nums2.length; j++) {
    
    
                if (nums1[i] == nums2[j]) {
    
    
                    set.add(nums1[i]);
                    index = j + 1;
                    break;
                } else if (nums1[i] < nums2[j]) {
    
    
                    index = j;
                    break;
                }
            }
        }

        long sum1 = 0;
        long sum2 = 0;
        int index2 = 0;
        for (int i = 0; i < nums1.length; i++) {
    
    
            sum1 += nums1[i];
            if (set.contains(nums1[i])) {
    
    
                while (nums2[index2] != nums1[i]) {
    
    
                    sum2 += nums2[index2];
                    index2++;
                }
                sum2 += nums2[index2];
                index2++;
                long max = Math.max(sum1, sum2);
                sum1 = max;
                sum2 = max;
            }
        }
        while (index2<nums2.length) {
    
    
            sum2+=nums2[index2];
            index2++;
        }
        return (int)(Math.max(sum1,sum2)%10_0000_0007);// 这里注意顺序,如果不加后面的括号会先执行int强转,然后取余。这就错了(越界得话丢弃)。必须先取余再强转。
    }
}
  • 自己的思路就是首先找到所有相同的元素,放到一个set中。

  • 从左到右遍历一个数组,一旦发现当前元素在set中,则将比较两个数组前面所有数的最大值,最为两个数组当前的最大值。(类似于动态规划。)

  • 大佬的代码为什么那么简洁呢?大佬的代码每次只比较一位,每次索引只向后移动一位,开始没想到这种写法,导致写得复杂了。

猜你喜欢

转载自blog.csdn.net/o_ogou/article/details/107748688