小和问题
在一个数组中,每一个数左边比当前数小的数累加起来,叫做这个数组的小和。求一个数组的小和。
例子: [1,3,4,2,5]
1左边比1小的数,没有;
3左边比3小的数,1;
4左边比4小的数,1、3;
2左边比2小的数,1;
5左边比5小的数,1、3、4、2;
所以小和为1+1+3+1+1+3+4+2=16
//利用归并排序
public static int smallSum(int[] arr) {
if (arr == null || arr.length < 2) {
return 0;
}
return mergeSort(arr, 0, arr.length - 1);
}
public static int mergeSort(int[] arr, int l, int r) {
if (l == r) {
return 0;
}
int mid = l + ((r - l) >> 1);
return mergeSort(arr, l, mid) + mergeSort(arr, mid + 1, r) + merge(arr, l, mid, r);
}
public static int merge(int[] arr, int l, int m, int r) {
int[] help = new int[r - l + 1];
int i = 0;
int p1 = l;
int p2 = m + 1;
int res = 0;
while (p1 <= m && p2 <= r) {
//计算小于的值的个数
res += arr[p1] < arr[p2] ? (r - p2 + 1) * arr[p1] : 0;
help[i++] = arr[p1] < arr[p2] ? arr[p1++] : arr[p2++];
}
while (p1 <= m) {
help[i++] = arr[p1++];
}
while (p2 <= r) {
help[i++] = arr[p2++];
}
for (i = 0; i < help.length; i++) {
arr[l + i] = help[i];
}
return res;
}
// test
public static void main(String[] args) {
int[] res = new int[5];
res = new int[]{3, 6, 8, 9, 0};
System.out.println(smallSum(res));
}
结果:29
荷兰国旗问题
给定一个数组arr,和一个数num,请把小于num的数放在数组的左边,等于num的数放在数组的中间,大于num的数放在数组的右边。
//利用快速排序
public static int[] partition(int[] arr, int l, int r, int p) {
int less = l - 1;
int more = r + 1;
while (l < more) {
if (arr[l] < p) {
swap(arr, ++less, l++);
} else if (arr[l] > p) {
swap(arr, --more, l);
} else {
l++;
}
}
return new int[] { less + 1, more - 1 };
}
// 交换
public static void swap(int[] arr, int i, int j) {
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
// 打印
public static void printArray(int[] arr) {
if (arr == null) {
return;
}
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
}
public static void main(String[] args) {
int[] res1 = new int[5];
res1 = new int[]{3, 6, 8, 9, 0};
printArray( res1);
int[] res = partition( res1, 0, res1.length - 1, 10);
printArray(res1);
System.out.println(res[0]);
System.out.println(res[1]);
}
旋转正方形矩阵
给定一个整型正方形矩阵matrix,请把该矩阵调整成 顺时针旋转90度的样子。
【要求】 额外空间复杂度为O(1)。
思路:位置对应,对应下标变化
//注:必须是旋转正方形,长方形位数对应不上
public static void rotate(int[][] matrix) {
//左上角位置,行列
int tR = 0;
int tC = 0;
//右下角位置,行列
int dR = matrix.length - 1;
int dC = matrix[0].length - 1;
//一直从最外圈到最里圈
while (tR < dR) {
rotateEdge(matrix, tR++, tC++, dR--, dC--);
}
}
//旋转边界:对应下标变化
public static void rotateEdge(int[][] m, int tR, int tC, int dR, int dC) {
//次数
int times = dC - tC;
int tmp = 0;
for (int i = 0; i != times; i++) {
//每次交换边界值(四个值交换一圈)
tmp = m[tR][tC + i];
m[tR][tC + i] = m[dR - i][tC];
m[dR - i][tC] = m[dR][dC - i];
m[dR][dC - i] = m[tR + i][dC];
m[tR + i][dC] = tmp;
}
}
public static void printMatrix(int[][] matrix) {
for (int i = 0; i != matrix.length; i++) {
for (int j = 0; j != matrix[0].length; j++) {
System.out.print(matrix[i][j] + " ");
}
System.out.println();
}
}
public static void main(String[] args) {
int[][] matrix = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 },
{ 13, 14, 15, 16 } };
printMatrix(matrix);
rotate(matrix);
System.out.println("=========");
printMatrix(matrix);
}
转圈打印矩阵
给定一个整型矩阵matrix,请按照转圈的方式打印它。 例如: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 打印结果为:1,2,3,4,8,12,16,15,14,13,9, 5,6,7,11, 10
【要求】 额外空间复杂度为O(1)。
public static void spiralOrderPrint(int[][] matrix) {
//左上角位置,行列
int tR = 0;
int tC = 0;
//右下角位置,行列
int dR = matrix.length - 1;
int dC = matrix[0].length - 1;
//满足条件:左上角a的行号来到最后一行并且列号来到最后一列(两者同时满足)
while (tR <= dR && tC <= dC) {
printEdge(matrix, tR++, tC++, dR--, dC--);
}
}
public static void printEdge(int[][] m, int tR, int tC, int dR, int dC) {
if (tR == dR) {
//只有一行时
for (int i = tC; i <= dC; i++) {
System.out.print(m[tR][i] + " ");
}
} else if (tC == dC) {
//只有一列时
for (int i = tR; i <= dR; i++) {
System.out.print(m[i][tC] + " ");
}
} else {
int curC = tC;
int curR = tR;
//顺着打印某一行
while (curC != dC) {
System.out.print(m[tR][curC] + " ");
curC++;
}
//顺着打印某一列
while (curR != dR) {
System.out.print(m[curR][dC] + " ");
curR++;
}
//逆着打印某一行
while (curC != tC) {
System.out.print(m[dR][curC] + " ");
curC--;
}
//逆着打印某一列
while (curR != tR) {
System.out.print(m[curR][tC] + " ");
curR--;
}
}
}
public static void main(String[] args) {
int[][] matrix = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 },
{ 13, 14, 15, 16 } };
spiralOrderPrint(matrix);
}
“之”字形打印矩阵
给定一个矩阵matrix,按照“之”字形的方式打印这 个矩阵,例如: 1 2 3 4 5 6 7 8 9 10 11 12 “之”字形打印的结果为:1,2,5,9,6,3,4,7,10,11, 8,12 【要求】 额外空间复杂度为O(1)。
public static void printMatrixZigZag(int[][] matrix) {
//对角线右上方点A行列坐标
int tR = 0;
int tC = 0;
//对角线左下方B行列坐标
int dR = 0;
int dC = 0;
//矩阵右下角点行列坐标
int endR = matrix.length - 1;
int endC = matrix[0].length - 1;
//标志从对角线右上方还是左下方开始打印
boolean fromUp = false;
//当A没有移动到最右端时
while (tR != endR + 1) {
printLevel(matrix, tR, tC, dR, dC, fromUp);
//A的路线:先向右移动,不能再向右移动后,再向下移动
tR = tC == endC ? tR + 1 : tR;
tC = tC == endC ? tC : tC + 1;
//B的路线:先向下移动,不能再向下移动后,再向右移动
dC = dR == endR ? dC + 1 : dC;
dR = dR == endR ? dR : dR + 1;
fromUp = !fromUp;
}
System.out.println();
}
//打印对角线
public static void printLevel(int[][] m, int tR, int tC, int dR, int dC, boolean f) {
if (f) {
//从A向B打印
while (tR != dR + 1) {
System.out.print(m[tR++][tC--] + " ");
}
} else {
//从B向A打印
while (dR != tR - 1) {
System.out.print(m[dR--][dC++] + " ");
}
}
}
public static void main(String[] args) {
int[][] matrix = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 } };
printMatrixZigZag(matrix);
}
在行列都排好序的矩阵中找数
给定一个有N*M的整型矩阵matrix和一个整数K, matrix的每一行和每一 列都是排好序的。实现一个函数,判断K 是否在matrix中。 例如: 0 1 2 5 2 3 4 7 4 4 4 8 5 7 7 9 如果K为7,返回true;如果K为6,返 回false。
【要求】 时间复杂度为O(N+M),额外空间复杂度为O(1)。
//两种方法,从右上角或者左下角找都可以
public static boolean isContains(int[][] matrix, int K) {
//从右上角出发开始找
int row = 0;
int col = matrix[0].length - 1;
//终止位置在左下角
while (row < matrix.length && col > -1) {
if (matrix[row][col] == K) {
return true;
} else if (matrix[row][col] > K) {
col--; //大于k向左
} else {
row++; //小于k向下
}
}
return false;
}
public static void main(String[] args) {
int[][] matrix = new int[][] { { 0, 1, 2, 3, 4, 5, 6 },// 0
{ 10, 12, 13, 15, 16, 17, 18 },// 1
{ 23, 24, 25, 26, 27, 28, 29 },// 2
{ 44, 45, 46, 47, 48, 49, 50 },// 3
{ 65, 66, 67, 68, 69, 70, 71 },// 4
{ 96, 97, 98, 99, 100, 111, 122 },// 5
{ 166, 176, 186, 187, 190, 195, 200 },// 6
{ 233, 243, 321, 341, 356, 370, 380 } // 7
};
int K = 233;
System.out.println(isContains(matrix, K));
}