# 编程，不止有代码，还有艺术

2022/05/30 10:51

## 设计模式的艺术：用状态模式告别if-else

(图源来自leetcode，链接见：https://leetcode.cn/problems/valid-number/solution/you-xiao-shu-zi-by-leetcode-solution-298l/)

class Solution {
public enum CharType {
NUMBER,
OP,
POINT,
E;

public static CharType toCharType(Character c) {
if (Character.isDigit(c)) {
return NUMBER;
} else if (c == '+' || c == '-') {
return OP;
} else if (c == '.') {
return POINT;
} else if (c =='e' || c == 'E') {
return E;
} else {
return null;
}
}
}
public enum State {
INIT(false),
OP1(false),
// 在.前面的数字
BEFORE_POINT_NUMBER(true),
// 前面没数字的点
NO_BEFORE_NUMBER_POINT(false),
// 前面有数字的点
BEFORE_NUMBER_POINT(true),
// 点后面的数字
AFTER_POINT_NUMBER(true),
// e/E
OPE(false),
// E后面的符号
OP2(false),
// e后面的数字
AFTER_E_NUMBER(true);

// 是否可在这个状态结束
private boolean canEnd;

State(boolean canEnd) {
this.canEnd = canEnd;
}

public boolean isCanEnd() {
return canEnd;
}
}

public Map<State, Map<CharType, State>> transferMap = new HashMap<>() {{
Map<CharType, State> map = new HashMap<>() {{
put(CharType.OP, State.OP1);
put(CharType.NUMBER, State.BEFORE_POINT_NUMBER);
put(CharType.POINT, State.NO_BEFORE_NUMBER_POINT);
}};
put(State.INIT, map);

map = new HashMap<>() {{
put(CharType.POINT, State.NO_BEFORE_NUMBER_POINT);
put(CharType.NUMBER, State.BEFORE_POINT_NUMBER);
}};
put(State.OP1, map);

map = new HashMap<>() {{
put(CharType.POINT, State.BEFORE_NUMBER_POINT);
put(CharType.NUMBER, State.BEFORE_POINT_NUMBER);
put(CharType.E, State.OPE);
}};
put(State.BEFORE_POINT_NUMBER, map);

map = new HashMap<>() {{
put(CharType.NUMBER, State.AFTER_POINT_NUMBER);
}};
put(State.NO_BEFORE_NUMBER_POINT, map);

map = new HashMap<>() {{
put(CharType.NUMBER, State.AFTER_POINT_NUMBER);
put(CharType.E, State.OPE);
}};
put(State.BEFORE_NUMBER_POINT, map);

map = new HashMap<>() {{
put(CharType.E, State.OPE);
put(CharType.NUMBER, State.AFTER_POINT_NUMBER);
}};
put(State.AFTER_POINT_NUMBER, map);
map = new HashMap<>() {{
put(CharType.OP, State.OP2);
put(CharType.NUMBER, State.AFTER_E_NUMBER);
}};
put(State.OPE, map);
map = new HashMap<>() {{
put(CharType.NUMBER, State.AFTER_E_NUMBER);
}};
put(State.OP2, map);

map = new HashMap<>() {{
put(CharType.NUMBER, State.AFTER_E_NUMBER);
}};
put(State.AFTER_E_NUMBER, map);
}};
public boolean isNumber(String s) {
State state = State.INIT;
for (char c : s.toCharArray()) {
Map<CharType, State> transMap = transferMap.get(state);
CharType charType = CharType.toCharType(c);
if (charType == null) {
return false;
}
if (!transMap.containsKey(charType)) {
return false;
}
// 状态变更
state = transMap.get(charType);
}
return state.canEnd;
}
}

## 并发编程的艺术：诡异的Java代码揭示了cpu缓存的原理

/** 队列中的头部节点 */
/** 队列中的尾部节点 */
static final class PaddedAtomicReference <T> extends AtomicReference T> {
// 使用很多4个字节的引用追加到64个字节
Object p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, pa, pb, pc, pd, pe;
super(r);
}
}
public class AtomicReference <V> implements java.io.Serializable {
private volatile V value;
// 省略其他代码
｝

“因为对于英特尔酷睿i7、酷睿、Atom和NetBurst，以及Core Solo和Pentium M处理器的L1、L2或L3缓存的高速缓存行是64个字节宽，不支持部分填充缓存行。

## 算法的艺术：用搜索解决迷宫问题

搜索（当前地图，当前点） {
If (是否已经搜索过这个场景) {
Return;
}

If(是否到达边界) {
刷新最新结果;
return;
}

for(遍历当前点的所有选择) {
if (是否是无效的选择) {
continue;
}

将当前选择带来的变化更新到地图中
进入后续的搜索
回退当前选择带来的变化
}
}

## 二进制的艺术：用数学节省了空间

“给定一个非空整数数组，除了某个元素只出现一次以外，其余每个元素均出现两次。找出那个只出现了一次的元素，而且不能用额外空间”

“给你一个整数数组 ，除某个元素仅出现一次外，其余每个元素都恰出现 三次 。请你找出并返回那个只出现了一次的元素。”

class Solution {
public int singleNumber(int[] nums) {
int result = 0;
for(int num : nums) {
result ^= num;
}
return result;
}
}

1 评论
1 收藏
0