Algorithm
Description
Given a 2D integer matrix M representing the gray scale of an image, you need to design a smoother to make the gray scale of each cell becomes the average gray scale (rounding down) of all the 8 surrounding cells and itself. If a cell has less than 8 surrounding cells, then use as many as you can.
Example 1:
Input:
[[1,1,1],
[1,0,1],
[1,1,1]]
Output:
[[0, 0, 0],
[0, 0, 0],
[0, 0, 0]]
Explanation:
For the point (0,0), (0,2), (2,0), (2,2): floor(3/4) = floor(0.75) = 0
For the point (0,1), (1,0), (1,2), (2,1): floor(5/6) = floor(0.83333333) = 0
For the point (1,1): floor(8/9) = floor(0.88888889) = 0
Note:
- The value in the given matrix is in the range of [0, 255].
- The length and width of the given matrix are in the range of [1, 150].
solution
思路:遍历矩阵中的每一个元素,把周边的所有元素的和加起来放到一个跟矩阵一样的二维数组中去,加完以后,对元素之和求平均值。
if (M == null) return null;
int xLen = M.length,yLen = M[0].length;
int[][] smoothArray = new int[xLen][yLen];
for (int i = 0; i < xLen; i++) {
for (int j = 0; j < yLen; j++) {
int cnt = 0;
for (int inRow = i-1; inRow <= i+1 ; inRow++) {
for (int inCol = j-1; inCol <= j+1 ; inCol++) {
if (inRow >= 0 && inRow < xLen && inCol >= 0 && inCol < yLen) {
smoothArray[i][j] += M[inRow][inCol];
cnt++;
}
}
}
smoothArray[i][j] /= cnt;
}
}
return smoothArray;
Review
读《Effective Java》–Item 28: Prefer list to arrays Array 和 泛型两个非常不同的点:
-
array 是
covariant
, 意思是协变的。就是如果Sub
是Super
的子类,那么 数组Sub[]
也是 数组Super[]
的子类。反过来是,泛型是invariant
,不变的。两个不同的类型Type1
、Type2
,List<Type1>
既不是List<Type2>
的子类也不是超类。//运行时异常 Object[] objectArray = new Long[1]; objectArray[0] = "I don't fit in"; // Throws ArrayStoreException
//编译异常 List<Object> ol = new ArrayList<Long>(); //Incomatible type ol.add("I don't fit in");
我们常说,错误要尽早出现,泛型在编译时就直接错误了。
-
第二个不同点是,
array
是reified
,具体化的。这意味着数组在运行时知道它元素的类型。所以你在运行时的时候,上面那个例子就会由于你往一个Long
类型的数组中间放入了一个String
, 所以就得到了一个ArrayStoreException
。而泛型的实现是由于erasure
, 擦除。这意味着它只在编译时知道它的类型,在运行时就会丢失它的元素信息。Erasure
就是泛型能够非常好的兼容古老代码的原因,可以让Java 5
以前的代码平滑过渡。
因为这两点的不同,所以数组和泛型没办法很好的结合在一起。
new List<E>[]
,new List<String>[]
,new E[]
像这些创建数组的语句都是不合法的,都会有编译异常。
Tip
new ArrayList<>(Arrays.asList()) 和 Arrays.asList() 的区别
public static void main(String[] args) {
Random rand = new Random(47);
Integer[] ia = {1, 2, 3, 4, 5, 6, 7, 8, 9};
List<Integer> list1 = new ArrayList<>(Arrays.asList(ia));
System.out.println("before" + list1);
Collections.shuffle(list1);
System.out.println("aftere" + list1);
System.out.println("array" + Arrays.toString(ia));
System.out.println("===========");
List<Integer> list2 = Arrays.asList(ia);
Object[] list3 = list2.toArray();
System.out.println("before" + list2);
Collections.shuffle(list2);
System.out.println("after" + list2);
System.out.println("array" + Arrays.toString(ia));
}
当我们在对list1 进行操作的时候,Arrays.asList()
是被放在了 ArrayList()
的构造方法下面,构造方法会调用toArray()
方法。看ArrayList
构造方法和 Arrays.ArrayList
的源码
public ArrayList(Collection<? extends E> c) {
elementData = c.toArray();
if ((size = elementData.length) != 0) {
// c.toArray might (incorrectly) not return Object[] (see 6260652)
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, size, Object[].class);
} else {
// replace with empty array.
this.elementData = EMPTY_ELEMENTDATA;
}
}
private static class ArrayList<E> extends AbstractList<E>
implements RandomAccess, java.io.Serializable
{
private static final long serialVersionUID = -2764017481108945198L;
private final E[] a;
ArrayList(E[] array) {
a = Objects.requireNonNull(array);
}
@Override
public Object[] toArray() {
return a.clone();
}
}
所以,直接操作 Arrays.List()
,你会更改最原始的那个数组,但是如果你操作的是 new ArrayList<>(Arrays.asList())
, 操作的只是数组的一个clone,不会操作原有的数组。
Share
最近一直要登录我自己的VPS, 以前是用的secureCRT, 所以还没有觉得有什么不方便。但是最近用上ubuntu了,可以直接用系统终端,不需要secureCRT或者xshell之类的软件了,这个时候登录VPS的时候就感觉比较麻烦了,每次都需要用ssh命令,而且还需要把密码找出来输入。
多方寻找,找到了expect
的工具。首先可以直接用teminal 输入 apt-get install expect
, 还是不要用snap install expect
,因为我用这个snap
安装的 expect
在执行 spawn ssh user@host
的时候总是permission denied。 所以就卸载用apt-get 进行安装,会安装到 /usr/bin/expect
下面。
好了,先铺代码:
#!/usr/bin/expect
set timeout 3
set user "[user]"
set host "[host]"
set pwd "[password]" //自己的VPS服务器ip和密码
proc func_login {password} {
expect {
"*(yes/no)? " {
send "yes\r";
exp_continue
}
"*password*" {
send "$password\r";
exp_continue
}
"*]\$ " {
#send_log "\r>>>>>>>>>> Login in SUCCESS <<<<<<<<<<<<\r";
puts "\r>>>>>>>>>> Login in SUCCESS <<<<<<<<<<<<\r"
}
"Permission denied*" {
send_error "\r>>>>>>>>>> Login in FAILED <<<<<<<<<<<<\r";
close;
exit
}
}
}
spawn ssh $user@$host
func_login $pwd
interact
简单解释:
-
spawn 命令会激活一个进程来进行交互式的程序运行
-
send 会向进程发送字符串
-
expect 会等待进程的一些字符串,可以用正则匹配。也可以同时等待多个字符串,并对每一个字符串执行不同的操作。expect还能理解一些特殊情况,如超时和遇到文件尾。所以我们在前面设置了3秒的超时。
-
interact 命令最后把进程移交给用户进行交互。如果这段代码没有interact ,执行完登录后,你就会看到它又自己退出了。