leetcode 获取单值网格的最小操作数

最小操作数转化为单值网格
这篇博客探讨了一个二维整数网格转化为单值网格的优化问题,通过一系列加减x的操作。首先将二维数组转为一维,然后寻找一个基准值,并计算每个元素与基准值的差值对x取模的结果。如果所有结果相同,说明可以转化为单值网格,否则返回-1。优化目标是最小化操作次数,即找到一个点使得所有元素到该点的绝对距离之和最小,证明了取中位数可以达到最优解。最后给出了AC代码实现。

给你一个大小为 m x n 的二维整数网格 grid 和一个整数 x 。每一次操作,你可以对 grid 中的任一元素 加 x 或 减 x 。

单值网格 是全部元素都相等的网格。

返回使网格化为单值网格所需的 最小 操作数。如果不能,返回 -1 。
在这里插入图片描述

  • 先将二维数组转换为一维数组。设数组 a a a,满足 a [ i ∗ m + j ] = g r i d [ i ] [ j ] a[i * m + j] = grid[i][j] a[im+j]=grid[i][j]
  • 设数组b,存操作序列。表示对于每个元素执行 a [ i ] ∗ b [ i ] ∗ x a[i] * b[i] * x a[i]b[i]x

于是优化目标为
m i n ∑ i ∣ b [ i ] ∣ min \quad \sum_{i}|b[i]| minib[i]
s . t . a [ i ] + b [ i ] ∗ x = a [ j ] + b [ j ] ∗ x ∀ i , j s.t. \quad a[i] + b[i] * x = a[j] + b[j]*x\quad \forall i,j s.t.a[i]+b[i]x=a[j]+b[j]xi,j

约束条件等价于
b [ j ] = b [ i ] − a [ i ] − a [ j ] x ∀ i , j b[j] = b[i] - \frac{a[i] - a[j]}{x} \quad \forall i,j b[j]=b[i]xa[i]a[j]i,j
显然约束条件成立的充分必要条件是
( a [ i ] − a [ j ] ) % x = 0 (a[i] -a[j]) \% x= 0 (a[i]a[j])%x=0
固定 i = 0 i = 0 i=0(因为后面的约束都是冗余的)得到 b [ j ] = b [ 0 ] − a [ 0 ] − a [ j ] x b[j] = b[0] - \frac{a[0]-a[j]}{x} b[j]=b[0]xa[0]a[j]
于是原约束问题变成了无约束优化问题
∑ j ∣ b [ 0 ] − a [ 0 ] − a [ j ] x ∣ \sum_{j} |b[0] - \frac{a[0]-a[j]}{x}| jb[0]xa[0]a[j]
这里 a [ 0 ] , a [ j ] , x a[0],a[j],x a[0],a[j],x都是已知的。该形式就是初中学过的找一个点(在这里这些点就是 a [ 0 ] − a [ j ] x \frac{a[0]-a[j]}{x} xa[0]a[j]),使得绝对值距离最小的问题。一般地,选取这个点为所有点的中位数即可。

此类问题的一般形式如下:
m i n ∣ x − a 1 ∣ + ∣ x − a 2 ∣ + ⋯ + ∣ x − a n ∣ min \quad |x - a_1| + |x - a_2| + \cdots + |x - a_n| minxa1+xa2++xan
此类问题的解为点列 a 1 , a 2 , ⋯ a n a_1,a_2,\cdots a_n a1,a2,an的中位数。
当点列个数为偶数时,可以使用绝对值不等式证明这个结论。不妨设 a 1 , a 2 ⋯ a n a_1,a_2\cdots a_n a1,a2an升序排列,如果不是升序排列,将其排序使其是升序。则:
∣ x − a 1 ∣ + ∣ x − a 2 ∣ + ⋯ + ∣ x − a n ∣ = ∣ x − a 1 ∣ + ∣ x − a 2 ∣ + ⋯ + ∣ x − a n 2 ∣ + ∣ a n 2 + 1 − x ∣ + ⋯ ∣ a n − x ∣ |x - a_1| + |x - a_2| + \cdots + |x - a_n| = |x-a_1| + |x-a_2| + \cdots + |x - a_{\frac{n}{2}}| + |a_{\frac{n}{2}+1} - x| + \cdots |a_n - x| xa1+xa2++xan=xa1+xa2++xa2n+a2n+1x+anx
由绝对值不等式得到:
∣ x − a 1 ∣ + ∣ x − a 2 ∣ + ⋯ + ∣ x − a n 2 ∣ + ∣ a n 2 + 1 − x ∣ + ⋯ ∣ a n − x ∣ ≥ ∣ x − a 1 + ⋯ x − a n 2 + a n 2 + 1 − x + ⋯ + a n − x ∣ |x-a_1| + |x-a_2| + \cdots + |x - a_{\frac{n}{2}}| + |a_{\frac{n}{2}+1} - x| + \cdots |a_n - x| \geq |x-a_1 + \cdots x-a_{\frac{n}{2}} + a_{\frac{n}{2}+1} -x + \cdots +a_n -x| xa1+xa2++xa2n+a2n+1x+anxxa1+xa2n+a2n+1x++anx
上述式子右侧的x恰好完全被抵消了,只剩下常数项。上述式子可以取等号的条件是绝对值里的元素是同号的,假设是同正的,则有:
x ≥ a 1 , x ≥ a 2 , ⋯ x ≥ a n 2 x \geq a_1,x\geq a_2,\cdots x\geq a_{\frac{n}{2}} xa1,xa2,xa2n
x ≤ a n 2 + 1 , ⋯ x ≤ a n x \leq a_{\frac{n}{2}+1},\cdots x \leq a_{n} xa2n+1,xan
显然x可以取序列的中位数使得上述式子成立。
对于奇数点,可以证明也是当取得中位数时上述式子最小。AC代码如下:

class Solution {
    public int minOperations(int[][] grid, int x) {
        int[] a = new int[grid.length * grid[0].length];
        for(int i = 0;i<grid.length;i++)
        {
            for(int j = 0;j<grid[0].length;j++)
                a[i * grid[0].length + j] = grid[i][j];
        }
        int[] coffeient = new int[a.length];
        coffeient[0] = 0;
        int min = coffeient[0];
        int Max = coffeient[0];
        for(int i = 1;i<coffeient.length;i++)
        {
            if((a[i] - a[0]) % x != 0)
                return -1;
            coffeient[i] = (a[i] - a[0]) /x;
        }
        int ans = 0;
        Arrays.sort(coffeient);
        int zhi = coffeient[coffeient.length  /2];
        for(int i = 0;i<coffeient.length;i++)
        {
            ans += Math.abs(coffeient[i] - zhi);
        }
        return ans;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值