1.矩阵的变换
将一个矩形顺时针翻转90°
解:先将矩形按行翻转,然后进行mirror操作
class Solution {
public void rotate(int[][] matrix) {
reverse(matrix);
mirrorRotate(matrix);
}
public void reverse(int[][] matrix){
for(int i=0,j=matrix.length-1;i<j;++i,--j){
int[] tmp = matrix[i];
matrix[i]=matrix[j];
matrix[j]=tmp;
}
}
public void mirrorRotate(int[][] matrix){
for(int i=0;i<matrix.length;++i){
for(int j=i+1;j<matrix.length;++j){
swap(matrix,i,j);
}
}
}
public void swap(int[][] matrix,int i,int j){
int tmp=matrix[i][j];
matrix[i][j]=matrix[j][i];
matrix[j][i]=tmp;
}
}
2.线段树(TODO 提交代码)
Range Sum Query
题目:307. Range Sum Query - Mutable(Medium)
解1:使用递归实现buildTree, update和sumRange
class NumArray {
int[] nums;
int[] tree;
int n;
public NumArray(int[] nums) {
this.nums = nums;
//System.out.printf("nums=%s\n",Arrays.toString(nums));
n = nums.length;
//[0]: [0,3]
// [0,1] [2,3]
// 1 2 3 4
// tree[n+i] = nums[i]
tree = new int[4*n+1];
if(n>0){
buildTree(nums,1,0,n-1);
}
//System.out.printf("tree=%s\n",Arrays.toString(tree));
}
public void buildTree(int[] nums,int idx,int left,int right){
// System.out.printf("idx=%s,left=%s,right=%s\n",idx,left,right);
if(left==right){
tree[idx]=nums[left];
}else{
int m=left + (right-left)/2;
buildTree(nums,idx<<1,left,m);
buildTree(nums, (idx<<1)|1,m+1,right);
tree[idx] = tree[idx<<1] + tree[(idx<<1)|1];
}
}
public void update(int i, int val) {
int diff = val - nums[i];
nums[i]=val;
updateSub(1,0,n-1,i,diff);
/*
18
16 2
9 7 2 0
7 2
24
16 8
9 7 2 6
7 2
*/
// System.out.printf("after update %s,%s,tree=%s\n",i,val,Arrays.toString(tree));
}
// update i, from top to bottom
// left,right is the range that idx holds, i is problem being asked
// invariant: left<=i<=right
private void updateSub(int idx,int left,int right,int i,int diff){
tree[idx]+=diff;
if(left==right){
return;
}
int m = left + (right-left)/2;
if(i<=m){
updateSub(idx<<1,left,m,i,diff);
}else{
updateSub((idx<<1)|1,m+1,right,i,diff);
}
}
public int sumRange(int i, int j) {
return sumRangeSub(1,0,n-1,i,j);
}
// invariant: left,right contains i,j
private int sumRangeSub(int idx,int left,int right,int i,int j){
if(i==left && j==right){
return tree[idx];
}
// 0 4
// 0,2,4,2
// 3,4,4,4
int m = left + (right - left)/2;
// sum(i,L,R,x,y)
// i has range L,R, query x,y
// if L,R==x,y return tree[i]
// if L,R intersects x,y
// [L,m R]
// [i,j]
if(m<i){
return sumRangeSub( (idx<<1)|1,m+1,right,i,j);
}else if(m>=j){
return sumRangeSub(idx<<1,left,m,i,j);
}else{
// i<=m<j
return sumRangeSub(idx<<1,left,m,i,m) + sumRangeSub((idx<<1)|1, m+1,right,m+1,j);
}
}
}
/**
* Your NumArray object will be instantiated and called as such:
* NumArray obj = new NumArray(nums);
* obj.update(i,val);
* int param_2 = obj.sumRange(i,j);
*/
解2:update操作不需要原数组nums,只需要重新计算所有受影响的路径即可
class NumArray {
int[] nums;
int[] tree;
int n;
public NumArray(int[] nums) {
// ... 同上
}
public void buildTree(int[] nums,int idx,int left,int right){
// ... 同上
}
public void update(int i, int val) {
// IMPORTANT: not necessary
// int diff = val - nums[i];
// nums[i]=val;
updateSub(1,0,n-1,i,val);
}
private void updateSub(int idx,int left,int right,int i,int val){
if(left==right){
// IMPORTANT: assign directly
tree[idx] = val;
return;
}
int m = left + (right-left)/2;
if(i<=m){
updateSub(idx<<1,left,m,i,val);
}else{
updateSub((idx<<1)|1,m+1,right,i,val);
}
// IMPORTANT: recompute
tree[idx] = tree[idx<<1] + tree[(idx<<1)|1];
}
public int sumRange(int i, int j) {
return sumRangeSub(1,0,n-1,i,j);
}
// invariant: left,right contains i,j
private int sumRangeSub(int idx,int left,int right,int i,int j){
// ... 同上
}
}
其他优化
支持区间添加值
将tree的值定义为区间的累加和,可以在O(logn)的时间内实现区间添加,如下:
tree=[] # init added[v]=0 when build tree
update(int idx,int l,int r,int add):
if l,r is the range:
tree[idx]+=add
....
sumRange(int idx,int l,int r):
return tree[idx] + sumRange(left) + sumRange(right)
支持区间的值设置
增加额外的标记数组和push操作,push操作定义为将marked标记清空,使得复制向下传递, update时,只需要设置一次marked[v]=true即可,get时,需要调用push来获得必要的值
void push(int v):
if marked[v]:
t[v.left]=t[v.right]=t[v]
marked[v.left]=marked[v.right]=true
marked[v]=false
get(int v, int L,int R,int i):
if L==R:return t[v]
push(v)
int m =(L+R)/2
if i<=m:
return get(v.left,L,m,i)
else
return get(v.right,m+1,R,i)
# 设置值
update(int v,int L,int R,int i,int j,int val):
if i>j:return
if(L==i&&R==j):
t[v]=val
marked[v]=true
return
push(v)
... #update sub ranges
3.矩形的面积和
题目
求给定矩形的面积,给定的矩形与X轴和Y轴平行
矩形覆盖
题目
给定n个矩形R1,…,Rn, 求R0是否被R1,…,Rn完全覆盖