Weekly Contest 387

Problem A

Distribute Elements Into Two Arrays I

思路

按照题意模拟即可.

代码

class Solution {
    public int[] resultArray(int[] nums) {
        int n = nums.length;
        int[] ans = new int[n];
        int[] arr1 = new int[n];
        int[] arr2 = new int[n];
        int l = 1;
        int r = 1;
        arr1[0] = nums[0];
        arr2[0] = nums[1];
        for(int i = 2;i<n;++i){
            if(arr1[l-1]>arr2[r-1]){
                arr1[l++] = nums[i];
            }
            else{
                arr2[r++] = nums[i];
            }
        }
        int i = 0;
        for(int j = 0;j<l;++j){
            ans[i++] = arr1[j];
        }
        for(int j = 0;j<r;++j){
            ans[i++] = arr2[j];
        }
        return ans;
    }
}

Problem B

Count Submatrices with Top-Left Element and Sum Less Than k

思路

二维数组前缀和

代码

class Solution {
    public int countSubmatrices(int[][] grid, int k) {
        int n = grid.length;
        int m = grid[0].length;
        int[][] dp = new int[n+1][m+1];
        // dp[0][0] = grid[0][0];
        int cnt = 0;
        for(int i = 1;i<=n;++i){
            for(int j = 1;j<=m;++j){
                dp[i][j] = dp[i-1][j]+dp[i][j-1]-dp[i-1][j-1]+grid[i-1][j-1];
                if(dp[i][j]<=k){
                    ++cnt;
                }
            }
        }
        return cnt;
        
    }
}

Problem C

Minimum Operations to Write the Letter Y on a Grid

思路

题目不难 按照坐标枚举 求出Y型区域每个数字出现的次数以及非Y型区域每个数字的出现次数,然后枚举两部分的最终字符即可

代码

class Solution {
    public int minimumOperationsToWriteY(int[][] grid) {
        int n = grid.length;
        int[] cnt = new int[3];
        for(int i = 0;i<n;++i){
            for(int j = 0;j<n;++j){
                cnt[grid[i][j]]++;
            }
        }
        int[] Y_cnt = new int[3];
        int d = (n+1)/2;
        for(int i = 0;i<d;++i){
            Y_cnt[grid[i][i]]++;
            Y_cnt[grid[i][n-i-1]]++;
            Y_cnt[grid[i+d-1][d-1]]++;
        }
        Y_cnt[grid[d-1][d-1]]-=2;
        cnt[0]-=Y_cnt[0];
        cnt[1]-=Y_cnt[1];
        cnt[2]-=Y_cnt[2];
        int s1 = cnt[0]+cnt[1]+cnt[2];
        int s2 = Y_cnt[0]+Y_cnt[1]+Y_cnt[2];
        int ans  = n*n*n;
        for(int i = 0;i<3;++i){
            for(int j = 0;j<3;++j){
                if(i==j){
                    continue;
                }
                int cal = s1-cnt[i]+s2-Y_cnt[j];
                ans = Math.min(ans,cal);
            }
        }
        return ans;
        
    }
}
        

Problem D

Distribute Elements Into Two Arrays II

思路

主要问题在于如何两个有序的序列,其他的按照题意模拟即可
比赛时使用的python现有的数据结构进行的模拟 对于 greaterCount则使用二分查找实现
实际上应该使用两个树状数组进行实现,要注意题目中数的取值范围是1e9 所以应该先离散化再取值

代码

比赛代码

def greaterCount(heap, val):
    l = 0
    r = len(heap)
    while(l<r):
        mid= (l+r)>>1
        if(heap[mid]<val):
            l = mid+1
        else:
            r = mid
    return l+1

def distribute(nums):

    arr1 = [nums[0]]
    arr2 = [nums[1]]
    h1 = [-nums[0]]
    h2 = [-nums[1]]
    for i in range(2, len(nums)):
        count1 = greaterCount(h1, -nums[i])
        count2 = greaterCount(h2, -nums[i])
        if count1 > count2:
            bisect.insort_left(h1, -nums[i])
            arr1.append(nums[i])
        elif count1 < count2:
            bisect.insort_left(h2, -nums[i])
            arr2.append(nums[i])
        else:
            if len(arr1) <= len(arr2):
                bisect.insort_left(h1, -nums[i])
                arr1.append(nums[i])
            else:
                bisect.insort_left(h2, -nums[i])
                arr2.append(nums[i])
    result = arr1 + arr2
    return result
class Solution:

    def resultArray(self, nums: List[int]) -> List[int]:
        return distribute(nums)

补题代码

class Solution {
    public int greaterCount(BIT b,int val,int cnt){
        return cnt - b.getSum(val);
    }
    public int[] resultArray(int[] nums) {
        TreeSet<Integer> tree = new TreeSet<Integer>();
        for(int num:nums){
            tree.add(num);
        }
        Map<Integer,Integer> map = new HashMap<>();
        int i = 1;
        for(int k:tree){
            map.put(k,i++);
            
        }
        List<Integer> l1 = new ArrayList<>();
        List<Integer> l2 = new ArrayList<>();
        l1.add(nums[0]);
        l2.add(nums[1]);
        int cnt1 = 1;
        int cnt2 = 1;
        BIT t1 = new BIT(i);
        BIT t2 = new BIT(i);
        t1.add(map.get(nums[0]),1);
        t2.add(map.get(nums[1]),1);
        for( i = 2;i<nums.length;++i){
            int g1 = greaterCount(t1,map.get(nums[i]),cnt1);
            int g2 = greaterCount(t2,map.get(nums[i]),cnt2);
            // System.out.println(" "+g1+ " " + g2);
            if(g1>g2||(g1==g2&&cnt1<=cnt2)){
                ++cnt1;
                l1.add(nums[i]);
                t1.add(map.get(nums[i]),1);
            }
            else{
                ++cnt2;
                l2.add(nums[i]);
                t2.add(map.get(nums[i]),1);
            }
        }
        int[] ans = new int[nums.length];
       
        l1.addAll(l2);
        for(int j = 0;j<nums.length;++j){
            ans[j] = l1.get(j);
        }
        return ans;
    }
}
class BIT {
    
    int n;
    int[] tr;
    BIT(int n){
        this.n = n;
        tr = new int[n+1];
    }
    public static int lowbit(int x){
        return x&-x;
    }
    public  void add(int x,int v){
        while(x<=n){
            tr[x]+=v;
            x+=lowbit(x);
        }
    }
    public int getSum(int k){
        int ret = 0;
        while(k>0){
            ret+=tr[k];
            k-=lowbit(k);
        }
        return ret;
    }

}

总结

本场简单 成功AK 但是第四题的思路不清晰 补学了下树状数组

posted @ 2024-03-09 22:27  浅花迷人  阅读(3)  评论(0编辑  收藏  举报