385. 迷你语法分析器【中等题】【每日一题】
思路:
看的宫水三叶的题解,并对代码加了详细注释。
代码:
/**
* // This is the interface that allows for creating nested lists.
* // You should not implement it, or speculate about its implementation
* public interface NestedInteger {
* // Constructor initializes an empty nested list.
* public NestedInteger();
*
* // Constructor initializes a single integer.
* public NestedInteger(int value);
*
* // @return true if this NestedInteger holds a single integer, rather than a nested list.
* public boolean isInteger();
*
* // @return the single integer that this NestedInteger holds, if it holds a single integer
* // Return null if this NestedInteger holds a nested list
* public Integer getInteger();
*
* // Set this NestedInteger to hold a single integer.
* public void setInteger(int value);
*
* // Set this NestedInteger to hold a nested list and adds a nested integer to it.
* public void add(NestedInteger ni);
*
* // @return the nested list that this NestedInteger holds, if it holds a nested list
* // Return empty list if this NestedInteger holds a single integer
* public List<NestedInteger> getList();
* }
*/
class Solution {
static NestedInteger ph = new NestedInteger(0);
public NestedInteger deserialize(String s) {
Deque<NestedInteger> d = new ArrayDeque<>();
char[] cs = s.toCharArray();
int n = cs.length,i = 0;
while(i < n){//遍历字符串每一个字符
if(cs[i] == ','){//如果是 , 直接跳过,遍历下一个字符
i++;
continue;
}
//如果是 - 或者 数字
if(cs[i] == '-' || (cs[i] >= '0' && cs[i] <= '9')){
//初始化数字num 初始化数字位的起始下标
int j = cs[i] == '-' ? i+1 : i , num = 0;
//将数字取出,存入num
while(j < n && (cs[j] >= '0' && cs[j] <= '9')){
num = num * 10 + (cs[j++]-'0');
}
//创建一个数值类型的NestedInteger实例并将其压入栈
d.addLast(new NestedInteger(cs[i] == '-' ? -num : num));
//更新下一次遍历的i的位置
i = j;
}else if(cs[i] == '['){
//如果遇到 '['
//创建一个嵌套类型的NestedInteger实例并将其压入栈
d.addLast(new NestedInteger());
//压入一个标识NestedInteger实例标记 [ 实例的位置
d.addLast(ph);
//更新下一次遍历的i的位置
i++;
}else{
//如果遇到 ']'
//说明当前这层嵌套结束了,需要将 '[' 和 ']'之前的栈的元素取出存入集合list
List<NestedInteger> list = new ArrayList<>();
while(!d.isEmpty()){//当栈不为空时,取出栈内元素
//倒序取出栈中元素
NestedInteger poll = d.pollLast();
if(poll == ph){//如果取出的元素为标记元素
break;//说明当前这层嵌套取出完毕,退出循环
}
list.add(poll);//将取出元素存入list
}
//当前 ']' 和 左侧离它最近的 '['之间的元素全部倒序存在list,现在再将它们倒序从list中取出添加到栈的最后一个元素中,两次倒序等于正序
//此时栈的最后一个元素就是 当遇到 '[' 时压入的那个空的NestedInteger实例
for(int j = list.size()-1;j>=0;j--){
d.peekLast().add(list.get(j));
}
//更新下一次遍历的i的位置
i++;
}
}
//因为题目中说 列表中的每个元素只可能是整数或者整数嵌套列表,所以对字符串处理完之后,栈中只剩一个元素,于是返回这个唯一的元素即可
return d.peekLast();//返回栈的最后一个元素,也是第一个元素
}
}
剑指 Offer 56 - I. 数组中数字出现的次数【中等题】
代码:
class Solution {
public int[] singleNumbers(int[] nums) {
//设 a 和 b 为不同的两个数,其余的数都是成对出现
int x = 0;
//将nums中所有数字异或,最后的结果就是 a ^ b
for (int num : nums) {
x ^= num;
}
//x的二进制表示中必然存在1,以任意一个1为分界点,a和b的二进制表示中,这个位置,必然是一个为0,一个为1
//先找出这个分界点1的位置,随便找一个就行,这里取最右侧的那个,即最低位的1
int r = 1;
while ((r & x) == 0){
r <<= 1;
}
int a = 0,b = 0;
//现在假设a的这个位置是1,b的这个位置是0,那么我们再次遍历数组nums,由于分界点的存在,必然导致,在这个位置为1的数有奇数个,在这个点为0的数有奇数个
//多出来的那个数分别是a和b,出现偶数次的数再次被异或运算抵消
for (int num : nums) {
if ((r & num) != 0){
a ^= num;
}else {
b ^= num;
}
}
return new int[]{a,b};
}
}