Cracking the coding interview--Q1.6


原文:

Given an image represented by an NxN matrix, where each pixel in the image is 4 bytes, write a method to rotate the image by 90 degrees. Can you do this in place?

译文:

一张图像表示成NxN的矩阵,图像中每个像素是4个字节,写一个函数把图像旋转90度。 你能原地进行操作吗?(即不开辟额外的存储空间)



假设矩阵顺时针旋转90度,假设测试数据如下:


1 2 3 4               13  9 5 1
5 6 7 8         ==>   14 10 6 2
9 10 11 12            15 11 7 3 
13 14 15 16           16 12 8 4

方法一:


数组下标0开始,旋转规律:(i,j)->(j,n-1-i)->(n-1-i,n-1-j)->(n-i-j,i)->(i,j)

也就是说开始坐标(i,j)转向(j,n-1-i),(j,n-1-i)转向(n-1-i,n-1-j)类推


	/**
	 * 顺时针旋转90度
	 * 数组下标0开始,旋转规律:(i,j)->(j,n-1-i)->(n-1-i,n-1-j)->(n-i-j,i)->(i,j)
	 * 也就是说开始坐标(i,j)转向(j,n-1-i),(j,n-1-i)转向(n-1-i,n-1-j)类推
	 * 
	 * 去除重复选装数字
	 */
	public static void rotateArray(int array[][], int n) {
		int tem;
		for(int i=0; i<n/2; i++) {
			for(int j=i; j<n-1-i; j++) {
				tem = array[i][j];
				array[i][j] = array[n-1-j][i];
				array[n-1-j][i] = array[n-1-i][n-1-j];
				array[n-1-i][n-1-j] = array[j][n-1-i];
				array[j][n-1-i] = tem;
			}
		}	
	}




方法二:


第一步交换主对角线两侧的对称元素,第二步交换第j列和第n-1-j列


	/**
	 * 规律:第一步交换主对角线两侧的对称元素,第二步交换第j列和第n-1-j列
	 */
	public static void rotateArray2(int array[][], int n) {
		int tem;
		// 主对角线两侧的对称元素
		for (int i = 1; i < n; i++) {
			for (int j = 0; j < i; j++) {
				tem = array[i][j];
				array[i][j] = array[j][i];
				array[j][i] = tem;
			}
		}
		
		for(int j=0; j<n/2; j++) {
			for(int i=0; i<n; i++) {
				tem = array[i][j];
				array[i][j] = array[i][n-1-j];
				array[i][n-1-j] = tem;
			}
		}
	}



主要代码如下:


package chapter_1_arraysandstring;

import java.util.Scanner;

/**
 * 一张图像表示成NxN的矩阵,图像中每个像素是4个字节,写一个函数把图像旋转90度。 你能原地进行操作吗?(即不开辟额外的存储空间)
 * 
 * @author LiangGe
 * 
 */
public class Question_1_6 {

	/**
	 * 顺时针旋转90度 数组下标0开始,旋转规律:(i,j)->(j,n-1-i)->(n-1-i,n-1-j)->(n-i-j,i)->(i,j)
	 * 也就是说开始坐标(i,j)转向(j,n-1-i),(j,n-1-i)转向(n-1-i,n-1-j)类推
	 * 
	 * 去除重复选装数字
	 */
	public static void rotateArray(int array[][], int n) {
		int tem;
		for (int i = 0; i < n / 2; i++) {
			for (int j = i; j < n - 1 - i; j++) {
				tem = array[i][j];
				array[i][j] = array[n - 1 - j][i];
				array[n - 1 - j][i] = array[n - 1 - i][n - 1 - j];
				array[n - 1 - i][n - 1 - j] = array[j][n - 1 - i];
				array[j][n - 1 - i] = tem;
			}
		}
	}

	/**
	 * 规律:第一步交换主对角线两侧的对称元素,第二步交换第j列和第n-1-j列
	 */
	public static void rotateArray2(int array[][], int n) {
		int tem;
		// 主对角线两侧的对称元素
		for (int i = 1; i < n; i++) {
			for (int j = 0; j < i; j++) {
				tem = array[i][j];
				array[i][j] = array[j][i];
				array[j][i] = tem;
			}
		}
		
		for(int j=0; j<n/2; j++) {
			for(int i=0; i<n; i++) {
				tem = array[i][j];
				array[i][j] = array[i][n-1-j];
				array[i][n-1-j] = tem;
			}
		}
	}

	
	/**
	 * 规律:第一步交换副对角线两侧的对称元素,第二步交换第i行和第n-1-i行
	 */
	public static void rotateArray3(int array[][], int n) {
		int tem;
		for(int i=0; i<n-1; i++) {
			for(int j=0; j<n-1-i; j++) {
				tem = array[i][j];
				array[i][j] = array[n-1-j][n-1-i];
				array[n-1-j][n-1-i] = tem;
			}
		}
		
		for(int i=0; i<n/2; i++) {
			for(int j=0; j<n; j++) {
				tem = array[i][j];
				array[i][j] = array[n-1-i][j];
				array[n-1-i][j] = tem;
			}
		}
	}
	
	/**
	 * 打印矩阵
	 */
	public static void printArray(int array[][], int n) {
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < n; j++) {
				System.out.printf("%3d", array[i][j]);
			}
			System.out.println();
		}
	}

	public static void main(String args[]) {
		Scanner scanner = new Scanner(System.in);
		int number = Integer.parseInt(scanner.nextLine());
		// number测试组
		while (number-- > 0) {
			String curStrLine = scanner.nextLine();
			String[] curStr = curStrLine.split(" ");
			int n = Integer.parseInt(curStr[0]);
			int array[][] = new int[n][n];

			for (int i = 0; i < n; i++) {
				for (int j = 0; j < n; j++) {
					array[i][j] = scanner.nextInt();
				}
				scanner.nextLine();
			}
			System.out.println("before rotate ....");
			printArray(array, n);
			// 顺时针旋转90度
			rotateArray3(array, n);

			System.out.println("after rotate ....");
			printArray(array, n);
		}
	}
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值