天天看點

LeetCode第200場周賽Java雙百解法

1534. 統計好三元組

給你一個整數數組 arr ,以及 a、b 、c 三個整數。請你統計其中好三元組的數量。

如果三元組 (arr[i], arr[j], arr[k]) 滿足下列全部條件,則認為它是一個 好三元組 。

0 <= i < j < k < arr.length

|arr[i] - arr[j]| <= a

|arr[j] - arr[k]| <= b

|arr[i] - arr[k]| <= c

其中 |x| 表示 x 的絕對值。

傳回 好三元組的數量 。

LeetCode第200場周賽Java雙百解法

分析 水題,數組長度極小,可直接三次循環解答。

class Solution {
    public int getAbs(int n){
        return Math.abs(n);
    }
    public int countGoodTriplets(int[] arr, int a, int b, int c) {
        int ans=0,len=arr.length;
        for(int i=0;i<len;i++){
            for(int j=i+1;j<len;j++){
                for(int k=j+1;k<len;k++){
                    if(getAbs(arr[i]-arr[j])<=a&&getAbs(arr[j]-arr[k])<=b&&getAbs(arr[i]-arr[k])<=c)
                        ans++;
                }
            }
        }
        return ans;
    }
}
           

1535. 找出數組遊戲的赢家

.給你一個由 不同 整數組成的整數數組 arr 和一個整數 k 。

每回合遊戲都在數組的前兩個元素(即 arr[0] 和 arr[1] )之間進行。比較 arr[0] 與 arr[1] 的大小,較大的整數将會取得這一回合的勝利并保留在位置 0 ,較小的整數移至數組的末尾。當一個整數赢得 k 個連續回合時,遊戲結束,該整數就是比賽的 赢家 。

傳回赢得比賽的整數。

題目資料 保證 遊戲存在赢家。

LeetCode第200場周賽Java雙百解法

分析 水題,模拟即可。

1536. 排布二進制網格的最少交換次數

給你一個 n x n 的二進制網格 grid,每一次操作中,你可以選擇網格的 相鄰兩行 進行交換。

一個符合要求的網格需要滿足主對角線以上的格子全部都是 0 。

請你傳回使網格滿足要求的最少操作次數,如果無法使網格符合要求,請你傳回 -1 。

主對角線指的是從 (1, 1) 到 (n, n) 的這些格子。

LeetCode第200場周賽Java雙百解法
LeetCode第200場周賽Java雙百解法

分析 很容易猜到,我們要将這個二維數組轉化為一維數組的形式,此一維數組即為從每一行右邊開始向左邊周遊,1第一次出現的位置。然後模拟交換步驟即可。

class Solution {
    public int minSwaps(int[][] grid) {
        int ans=0,len=grid.length;
        int[] arr=new int[len];
        for(int i=0;i<len;i++){
            for(int j=len-1;j>=0;j--){
                if(grid[i][j]==1){
                    arr[i]=j;
                    break;
                }
            }
        }
        for(int i=0;i<len;i++){
            if(arr[i]<=i) continue;
            int pos=-1;
            for(int j=i+1;j<len;j++){
                if(arr[j]<=i)
                {
                    pos=j;
                    break;
                }
            }
            if(pos==-1) return -1;
            for(int k = pos; k > i; k--){
                int tmp = arr[k-1];
                arr[k-1] = arr[k];
                arr[k] = tmp;
            }
            ans += (pos - i);
        }
        return ans;
    }
}
           

1537. 最大得分

你有兩個 有序 且數組内元素互不相同的數組 nums1 和 nums2 。

一條 合法路徑 定義如下:

選擇數組 nums1 或者 nums2 開始周遊(從下标 0 處開始)。

從左到右周遊目前數組。

如果你遇到了 nums1 和 nums2 中都存在的值,那麼你可以切換路徑到另一個數組對應數字處繼續周遊(但在合法路徑中重複數字隻會被統計一次)。

得分定義為合法路徑中不同數字的和。

請你傳回所有可能合法路徑中的最大得分。

由于答案可能很大,請你将它對 10^9 + 7 取餘後傳回。

LeetCode第200場周賽Java雙百解法

分析 可dp,可雙指針。此處使用雙指針解答。

以第一個示例畫圖舉例(較為潦草,見諒)

LeetCode第200場周賽Java雙百解法

這就是主要算法運作過程。

代碼

class Solution {
    public int maxSum(int[] nums1, int[] nums2) {
        long ans1=0,ans2=0;
        int i=0,j=0;
        int mod=(int)(Math.pow(10,9)+7);
        while(i<nums1.length&&j<nums2.length){
            if(nums1[i]<nums2[j]){
                ans1+=nums1[i++];
            }else if(nums1[i]>nums2[j]){
                ans2+=nums2[j++];
            }else{
                ans1=Math.max(ans1,ans2)+nums2[j];
                ans2=ans1;
                i++;
                j++;
            }
        }
        while(i<nums1.length)
        ans1+=nums1[i++];
        while(j<nums2.length)
        ans2+=nums2[j++];
        return (int)(Math.max(ans1,ans2)%mod);
    }
}
           

但是我們需要驗證,這樣如何保證是跟題目一樣的過程。

ans1 與 ans2 可以看做每次兩個數組擁有相同的值的時候,所走的不同的路徑,然後在下一次兩個數組再次擁有相同的值的時候,将 ans1 與 ans2 整合,繼續走不同的路徑。思路類似于dp。

而在一個指針已經到達數組末尾時,将另外一個指針之後的數組數字累加,最後輸出這兩條路徑中的最大值即為答案。

算法:雙指針、dp

比賽總結

LeetCode的比賽相較cf而言更為簡單,不要想太複雜了,而且出題較為有規律,一般競賽如果有題目考數學與思維較多,那麼競賽大體解法較為偏數學。

而感覺此次模拟較多,我的模拟較為薄弱,還需要加強。