385. 迷你语法分析器 / 剑指 Offer 56 - I. 数组中数字出现的次数

这篇博客介绍了两个编程题目。第一题是实现一个迷你语法分析器,用于解析包含嵌套整数的字符串。代码通过栈来处理嵌套结构,识别整数和列表。第二题涉及异或操作,通过异或所有数组元素找到两个不重复的数字。博客内容涵盖了数据结构、算法和编程技巧。
摘要由CSDN通过智能技术生成

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};
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值