给你一个大小为 m x n 的二维整数网格 grid 和一个整数 x 。每一次操作,你可以对 grid 中的任一元素 加 x 或 减 x 。
单值网格 是全部元素都相等的网格。
返回使网格化为单值网格所需的 最小 操作数。如果不能,返回 -1 。
- 先将二维数组转换为一维数组。设数组aaa,满足a[i∗m+j]=grid[i][j]a[i * m + j] = grid[i][j]a[i∗m+j]=grid[i][j]
- 设数组b,存操作序列。表示对于每个元素执行a[i]∗b[i]∗xa[i] * b[i] * xa[i]∗b[i]∗x
于是优化目标为
min∑i∣b[i]∣min \quad \sum_{i}|b[i]|mini∑∣b[i]∣
s.t.a[i]+b[i]∗x=a[j]+b[j]∗x∀i,js.t. \quad a[i] + b[i] * x = a[j] + b[j]*x\quad \forall i,js.t.a[i]+b[i]∗x=a[j]+b[j]∗x∀i,j
约束条件等价于
b[j]=b[i]−a[i]−a[j]x∀i,jb[j] = b[i] - \frac{a[i] - a[j]}{x} \quad \forall i,jb[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=0i = 0i=0(因为后面的约束都是冗余的)得到b[j]=b[0]−a[0]−a[j]xb[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}|j∑∣b[0]−xa[0]−a[j]∣
这里a[0],a[j],xa[0],a[j],xa[0],a[j],x都是已知的。该形式就是初中学过的找一个点(在这里这些点就是a[0]−a[j]x\frac{a[0]-a[j]}{x}xa[0]−a[j]),使得绝对值距离最小的问题。一般地,选取这个点为所有点的中位数即可。
此类问题的一般形式如下:
min∣x−a1∣+∣x−a2∣+⋯+∣x−an∣min \quad |x - a_1| + |x - a_2| + \cdots + |x - a_n|min∣x−a1∣+∣x−a2∣+⋯+∣x−an∣
此类问题的解为点列a1,a2,⋯ana_1,a_2,\cdots a_na1,a2,⋯an的中位数。
当点列个数为偶数时,可以使用绝对值不等式证明这个结论。不妨设a1,a2⋯ana_1,a_2\cdots a_na1,a2⋯an升序排列,如果不是升序排列,将其排序使其是升序。则:
∣x−a1∣+∣x−a2∣+⋯+∣x−an∣=∣x−a1∣+∣x−a2∣+⋯+∣x−an2∣+∣an2+1−x∣+⋯∣an−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|∣x−a1∣+∣x−a2∣+⋯+∣x−an∣=∣x−a1∣+∣x−a2∣+⋯+∣x−a2n∣+∣a2n+1−x∣+⋯∣an−x∣
由绝对值不等式得到:
∣x−a1∣+∣x−a2∣+⋯+∣x−an2∣+∣an2+1−x∣+⋯∣an−x∣≥∣x−a1+⋯x−an2+an2+1−x+⋯+an−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|∣x−a1∣+∣x−a2∣+⋯+∣x−a2n∣+∣a2n+1−x∣+⋯∣an−x∣≥∣x−a1+⋯x−a2n+a2n+1−x+⋯+an−x∣
上述式子右侧的x恰好完全被抵消了,只剩下常数项。上述式子可以取等号的条件是绝对值里的元素是同号的,假设是同正的,则有:
x≥a1,x≥a2,⋯x≥an2x \geq a_1,x\geq a_2,\cdots x\geq a_{\frac{n}{2}}x≥a1,x≥a2,⋯x≥a2n
x≤an2+1,⋯x≤anx \leq a_{\frac{n}{2}+1},\cdots x \leq a_{n}x≤a2n+1,⋯x≤an
显然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;
}
}