1.算法例子描述
给定一个json字符串
{
"a": {
"b": {
"c": {
"d": "h",
"j": "l",
"o": {
"p": "q",
"r": "s"
},
"t": "u"
}
},
"v": {
"w": {
"x": {
"y": "z"
}
}
}
},
"e": {
"f": {
"i": "k"
},
"m": "n"
}
}
要求把同等级的放在一起,打印出来.
[[a, e], [b, v, f, m], [c, w, i], [d, j, o, t, x], [p, r, y]]
2.算法结果打印
字符串遍历流程:
str:{"a":{"b":{"c":{"d":"h","j":"l","o":{"p":"q","r":"s"},"t":"u"}},"v":{"w":{"x":{"y":"z"}}}},"e":{"f":{"i":"k"},"m":"n"}}
key:a level:0
key:b level:1
key:c level:2
key:d level:3
key:j level:3
key:o level:3
key:p level:4
key:r level:4
key:t level:3
key:v level:1
key:w level:2
key:x level:3
key:y level:4
key:e level:0
key:f level:1
key:i level:2
key:m level:1
resultStr:[[a, e], [b, v, f, m], [c, w, i], [d, j, o, t, x], [p, r, y]]
3.算法分析
需要考虑几个问题:
1.要想找到key,那么就需要遍历字符串?.
那么就需要将其转化为charArray,进行遍历即可.
2.怎么计算层级.
需要一个临时变量level,计算当前key的层级.
层级增加就level++
层级降低就level–.
层级不变.不需要改变level.
3.怎么判断层级增加?.
当遇到了 { 那么就是等级增加.
4.怎么判断层级结束?.
当遇到了 } 那么就是等级增加.
5.怎么判断是同等级的?.
如果两个key在同等级.
那么肯定是使用 逗号(,)隔开的,此时不需要降级.
6.怎么区分读到的字母是key还是value?.
可以在上一个key结束后,将对用key置为空,
当前的key为空,那么此时的字母是key,赋给key.
当前的key不为空,那么此时的字母是属性值.不需要赋给key.
7.怎么处理结果字符串格式?.
因为是按照层级存储的,我这里考虑使用List result;
外层的List表示层级,每个索引表是当前的层级.因为需要经常查找,用ArrayList.
外层的List存储层级中的key,因为需要添加相对较多(虽然是进行尾部插入,和ArrayList没区别,但是内存分分配上可以不连续)用LinkedList.
最后遍历result即可.组装对应的字符串.
4.算法实现
4.1 Key结点数据结构
/**
* Key的结点Bean
*/
class KeyNode {
private Character key;//key的值
private int level;//key的等级,这里从0开始
public KeyNode(Character key, int level) {
this.key = key;
this.level = level;
}
public Character getKey() {
return key;
}
public int getLevel() {
return level;
}
}
4.2 存储结果数据结构
/**
* 存储结果Bean
*/
public class KeyResult {
//外层是按照登记区分.里层就是key的集合
//因为外层要频繁的查找,所以要用ArrayList,
//里层的那个频繁的添加,所以用LinkedList
private List<List<Character>> result;
public KeyResult() {
//因为外层要频繁的查找,所以要用ArrayList,
result = new ArrayList<>();
}
/**
* 添加Key
*
* @param keyNode
*/
public void addKey(KeyNode keyNode) {
if (keyNode == null) {
return;
}
//1.先通过等级找到对应的位置的数据.
if (keyNode.getLevel() == result.size()) {
//此时说明result中还未有此位置,则需要创建并添加到result中
result.add(new LinkedList<Character>());
}
List<Character> keys = result.get(keyNode.getLevel());
//2.将key的值添加到对应的位置中
keys.add(keyNode.getKey());
}
/**
* 获取指定格式化的字符串[[a,e],[b,c],[d]]
*
* @return
*/
public String getFormatString() {
StringBuilder resultString = new StringBuilder();
resultString.append("[");
//1.外层
for (int i = 0, size = result.size(); i < size; i++) {
if (i == 0) {
resultString.append("[");
} else {
resultString.append(",").append("[");
}
//2.里层
List<Character> keys = result.get(i);
for (int j = 0, keySize = keys.size(); j < keySize; j++) {
if (j == 0) {
resultString.append(keys.get(j));
} else {
resultString.append(",").append(keys.get(j));
}
}
resultString.append("]");
}
resultString.append("]");
return result.toString();
}
}
4.3 处理字符串方法
/**
* 处理为指定格式的字符串
* [[a, e], [b, v, f, m], [c, w, i], [d, j, o, t, x], [p, r, y]]
*
* @param strs 待处理的字符串
* @return
*/
public static String optFormatStr(String strs) {
//1.将字符串转化成char数组
char[] chars = strs.toCharArray();
//2.辅助变量
KeyResult result = new KeyResult();//存储打印的结果
int level = -1;//当前的等级
char key = ' ';//临时变量,遍历时判断是属性还是对象用的
//3.遍历数组
for (char c : chars) {
if (c == '{') {
//3.1,遇到 { 表示增加了增加,并且将key置为" "
key = ' ';
level++;
} else if (c == ',') {
//3.2,遇到 , 表示当前key对应的属性结束,并且将key置为" "
key = ' ';
} else if (c == '}') {
//3.3.表示当前等级遍历结束.等级-1
level--;
} else if (c >= 'a' && c <= 'z') {
//3.4.表示遇到的是字母
//如果key为" ",说明key是上个key遍历了,此时c有效.
if (key == ' ') {
key = c;
System.out.println("key:" + c + " level:" + level);
result.addKey(new KeyNode(key, level));
}
// else 否则表示c是key的一个属性值,不需要进行存储.
}
}
//4.返回结果
return result.getFormatString();
}
4.4. 调用示例
public static void main(String[] args) {
//1.字符串
String str = "{\n" +
"\t\"a\": {\n" +
"\t\t\"b\": {\n" +
"\t\t\t\"c\": {\n" +
"\t\t\t\t\"d\": \"h\",\n" +
"\t\t\t\t\"j\": \"l\",\n" +
"\t\t\t\t\"o\": {\n" +
"\t\t\t\t\t\"p\": \"q\",\n" +
"\t\t\t\t\t\"r\": \"s\"\n" +
"\t\t\t\t},\n" +
"\t\t\t\t\"t\": \"u\"\n" +
"\t\t\t}\n" +
"\t\t},\n" +
"\t\t\"v\": {\n" +
"\t\t\t\"w\": {\n" +
"\t\t\t\t\"x\": {\n" +
"\t\t\t\t\t\"y\": \"z\"\n" +
"\t\t\t\t}\n" +
"\t\t\t}\n" +
"\t\t}\n" +
"\t},\n" +
"\t\"e\": {\n" +
"\t\t\"f\": {\n" +
"\t\t\t\"i\": \"k\"\n" +
"\t\t},\n" +
"\t\t\"m\": \"n\"\n" +
"\t}\n" +
"}";
//2.将空格,\t,\n,去掉.
str = str.replaceAll(" ", "");
str = str.replaceAll("\t", "");
str = str.replaceAll("\n", "");
//3.调用处理为指定的个数
System.out.println("str:" + str);
String resultStr = optFormatStr(str);
System.out.println("resultStr:" + resultStr);
}
欢迎大家指正和互相学习.