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 但是第四题的思路不清晰 补学了下树状数组
过往不恋 未来不迎 当下不负