思路:第一种如果第一列全为0,进入下一列
第二种如果第一列除了第一个元素外全为0,进入第二行第二列
第三种,如果不是第一种第二种情况,找到一列中绝对值最小且大于0的元素,与第一排交换。一列中其他行分别减去第一排直到减到比第一排的元素小为止。然后再进行第三种情况,直到变为第二种情况,然后进行下一行下一列。
每进入新的一行一列时重复这三种情况
每进行一次初等行变换,都要输出矩阵,且矩阵变换过程中需要为整数型
效果如图
public class MatrixTransformer {
// 矩阵初等变换函数
public void transform(int[][] matrix) {
int row = matrix.length; // 矩阵行数
int col = matrix[0].length; // 矩阵列数
int i = 0, j = 0;
while (i < row && j < col) {
// 第一列全为0,进入下一列
if (matrix[i][j] == 0) {
j++;
}
// 第一列除了第一个元素外全为0,进入下一行第二列
else if (isFirstColumnZero(matrix, i)) {
i++;
j = 1;
}
// 进行初等行变换
else {
// 找到主元素所在的行
int pivotRow = findPivotRow(matrix, i, j);
// 交换行,让主元素在第一行
swapRows(matrix, i, pivotRow);
// 将该列其他行的元素消成0
eliminate(matrix, i, j);
// 输出当前矩阵
printMatrix(matrix);
// 进行下一次变换
i++;
j++;
}
}
}
// 判断第一列除了第一个元素外是否全为0
private boolean isFirstColumnZero(int[][] matrix, int i) {
for (int k = 1; k < matrix.length; k++) {
if (matrix[k][0] != 0) {
return false;
}
}
return true;
}
// 找到该列绝对值最小、大于0的元素所在的行
private int findPivotRow(int[][] matrix, int i, int j) {
int min = Integer.MAX_VALUE;
int minRow = i;
for (int k = i; k < matrix.length; k++) {
if (Math.abs(matrix[k][j]) < min && matrix[k][j] != 0) {
min = Math.abs(matrix[k][j]);
minRow = k;
}
}
return minRow;
}
// 将第i行和第pivotRow行交换
private void swapRows(int[][] matrix, int i, int pivotRow) {
int[] temp = matrix[i];
matrix[i] = matrix[pivotRow];
matrix[pivotRow] = temp;
}
// 消元,将该列其他行的元素消成0
private void eliminate(int[][] matrix, int i, int j) {
int pivot = matrix[i][j];
for (int k = i + 1; k < matrix.length; k++) {
int factor = matrix[k][j] / pivot;
for (int l = j; l < matrix[0].length; l++) {
matrix[k][l] -= factor * matrix[i][l];
}
}
}
// 输出矩阵
private void printMatrix(int[][] matrix) {
for (int[] row : matrix) {
for (int num : row) {
System.out.print(num + "\t");
}
System.out.println();
}
System.out.println();
}
// 输出
public static void main(String[] args) {
int[][] matrix = {
{2, 4, 6},
{4, 8, 10},
{6, 12, 19}
};
MatrixTransformer transformer = new MatrixTransformer();
transformer.transform(matrix);
}
}
参考
public static void toRowEchelonForm(int[][] matrix) {
int rows = matrix.length;
int cols = matrix[0].length;
int lead = 0;
for (int r = 0; r < rows; r++) {
if (cols <= lead) {
break;
}
int i = r;
while (matrix[i][lead] == 0) {
i++;
if (rows == i) {
i = r;
lead++;
if (cols == lead) {
return;
}
}
}
swap(matrix, i, r);
int lv = matrix[r][lead];
for (int j = 0; j < cols; j++) {
matrix[r][j] = matrix[r][j] / lv;
}
for (int i1 = 0; i1 < rows; i1++) {
if (i1 != r) {
int lv1 = matrix[i1][lead];
for (int j = 0; j < cols; j++) {
matrix[i1][j] -= lv1 * matrix[r][j];
}
}
}
lead++;
printMatrix(matrix);
}
}
private static void swap(int[][] matrix, int i, int j) {
int[] temp = matrix[i];
matrix[i] = matrix[j];
matrix[j] = temp;
}
private static void printMatrix(int[][] matrix) {
int rows = matrix.length;
int cols = matrix[0].length;
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
System.out.print(matrix[i][j] + " ");
}
System.out.println();
}
System.out.println();
}
package Demo41Allot_Peach;
/**
* 海滩上有一堆桃子,五只猴子来分。第一只猴子把这堆桃子凭据分为五份,
* 多了一个,这只猴子把多的一个扔入海中,拿走了一份。第二只猴子把剩下的桃子又平均分成五份,又多了一个,
* 它同样把多的一个扔入海中,拿走了一份,第三、第四、第五只猴子都是这样做的,问海滩上原来最少有多少个桃子?
*/
/*
分析:猴子分桃问题,按题目的意思来说,这一堆桃子的总数除以五会余一,它的商除以五也会余一,但是难点是我们不知道最后一只猴子拿了几个桃子。
所以呢,就要先定义规则,然后从1开始遍历数字,符合规则的就是最少有的桃子数。
假设有x个桃子,第一只猴子分完后,就是x/5=1,第二只猴子分的时候就是x/5个桃子了。
判断x%5是否等于1,如果不等于1,则直接不符合,继续遍历,如果等于1,则继续比较,最后一个猴子至少要拿到一个桃子,且扔掉一个桃子
*/
public class Allot_Peach {
public static void main(String[] args) {
// 关于index,可以从1开始,但是我们知道桃子数一定是要大于5的,所以从6开始
int index = 6;
// 一直找,一直找
while (true) {
// 对于每一个index都调用finds()方法来判断其是否符合条件
boolean finds = finds(index);
// 如果符合条件,则输出结果,并且终止循环
if (finds) {
System.out.println("海滩上最少有" + index + "个桃子。"); //最少3121只桃子
break;
}
// 6除以5余1,那么步进就得是5,因为1~4得到的余数分别为2,3,4,0,当然,步进为1也是ok,就是效率低了些。
index += 5;
}
}
/**
* 定义一个判断数字是否符合条件,符合就返回一个true,否则返回false
* 所谓条件就是该数每次计算之间,num值一定要大于5,不然怎么分五份呢是不?
* @param num
* @return
*/
public static boolean finds(int num) {
// 定义要返回的布尔值
boolean flag = false;
// 有5只猴子,判断5次
for (int i = 1; i <= 5; i++) {
// 判断num是否大于5,要是还没到第五只猴子呢就不足五个桃子了,那第五只猴子要生气了,并且判断该数是否除5余1
if (num > 5 && num % 5 == 1) {
// 判断是不是最后一只猴子,如果到最后一直猴子了,且符合条件,就返回true,表明找到了该数。
if (i == 5) {
flag = true;
} else {
// 如果不是最后一只猴子,那么该猴子丢掉一个,且拿走五分之一,剩下原来桃子数-1的4/5
num = ((num-1)*4) / 5;
}
} else {
// 如果该数小于5导致没法分了,或者不符合最后能丢掉一个的条件,直接返回false
return false;
}
}
return flag;
}
}